Skip to content

Commit 60bf565

Browse files
fix(feishu): honor wildcard group config for reply policy (#29456)
## Summary - honor Feishu wildcard group policy fallback via `channels.feishu.groups["*"]` when no explicit group entry matches - keep exact and case-insensitive explicit group matches higher precedence than wildcard fallback - add changelog credit and TypeScript-safe test assertions ## Verification - pnpm install --frozen-lockfile - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: Wayne Pika <[email protected]> Co-authored-by: Tak Hoffman <[email protected]>
1 parent 8a2273e commit 60bf565

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Docs: https://docs.openclaw.ai
3232
- Feishu/Inbound rich-text parsing: preserve `share_chat` payload summaries when available and add explicit parsing for rich-text `code`/`code_block`/`pre` tags so forwarded and code-heavy messages keep useful context in agent input. (#28591) Thanks @kevinWangSheng.
3333
- Feishu/Local media sends: propagate `mediaLocalRoots` through Feishu outbound media sending into `loadWebMedia` so local path attachments work with post-CVE local-root enforcement. (#27884) Thanks @joelnishanth.
3434
- Feishu/Group sender allowlist fallback: add global `channels.feishu.groupSenderAllowFrom` sender authorization for group chats, with per-group `groups.<id>.allowFrom` precedence and regression coverage for allow/block/precedence behavior. (#29174) Thanks @1MoreBuild.
35+
- Feishu/Group wildcard policy fallback: honor `channels.feishu.groups["*"]` when no explicit group match exists so unmatched groups inherit wildcard reply-policy settings instead of falling back to global defaults. (#29456) Thanks @WaynePika.
3536
- Feishu/Docx append/write ordering: insert converted Docx blocks sequentially (single-block creates) so Feishu append/write preserves markdown block order instead of returning shuffled sections in asynchronous batch inserts. (#26172, #26022) Thanks @echoVic.
3637
- Feishu/Docx convert fallback chunking: recursively split oversized markdown chunks (including long no-heading sections) when `document.convert` hits content limits, while keeping fenced-code-aware split boundaries whenever possible. (#14402) Thanks @lml2468.
3738
- Feishu/Inbound media regression coverage: add explicit tests for message resource type mapping (`image` stays `image`, non-image maps to `file`) to prevent reintroducing unsupported Feishu `type=audio` fetches. (#16311, #8746) Thanks @Yaxuan42.

extensions/feishu/src/policy.test.ts

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,62 @@
11
import { describe, expect, it } from "vitest";
2-
import { isFeishuGroupAllowed, resolveFeishuAllowlistMatch } from "./policy.js";
2+
import {
3+
isFeishuGroupAllowed,
4+
resolveFeishuAllowlistMatch,
5+
resolveFeishuGroupConfig,
6+
} from "./policy.js";
7+
import type { FeishuConfig } from "./types.js";
38

49
describe("feishu policy", () => {
10+
describe("resolveFeishuGroupConfig", () => {
11+
it("falls back to wildcard group config when direct match is missing", () => {
12+
const cfg = {
13+
groups: {
14+
"*": { requireMention: false },
15+
"oc-explicit": { requireMention: true },
16+
},
17+
} as unknown as FeishuConfig;
18+
19+
const resolved = resolveFeishuGroupConfig({
20+
cfg,
21+
groupId: "oc-missing",
22+
});
23+
24+
expect(resolved).toEqual({ requireMention: false });
25+
});
26+
27+
it("prefers exact group config over wildcard", () => {
28+
const cfg = {
29+
groups: {
30+
"*": { requireMention: false },
31+
"oc-explicit": { requireMention: true },
32+
},
33+
} as unknown as FeishuConfig;
34+
35+
const resolved = resolveFeishuGroupConfig({
36+
cfg,
37+
groupId: "oc-explicit",
38+
});
39+
40+
expect(resolved).toEqual({ requireMention: true });
41+
});
42+
43+
it("keeps case-insensitive matching for explicit group ids", () => {
44+
const cfg = {
45+
groups: {
46+
"*": { requireMention: false },
47+
OC_UPPER: { requireMention: true },
48+
},
49+
} as unknown as FeishuConfig;
50+
51+
const resolved = resolveFeishuGroupConfig({
52+
cfg,
53+
groupId: "oc_upper",
54+
});
55+
56+
expect(resolved).toEqual({ requireMention: true });
57+
});
58+
});
59+
560
describe("resolveFeishuAllowlistMatch", () => {
661
it("allows wildcard", () => {
762
expect(

extensions/feishu/src/policy.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function resolveFeishuGroupConfig(params: {
5656
groupId?: string | null;
5757
}): FeishuGroupConfig | undefined {
5858
const groups = params.cfg?.groups ?? {};
59+
const wildcard = groups["*"];
5960
const groupId = params.groupId?.trim();
6061
if (!groupId) {
6162
return undefined;
@@ -68,7 +69,10 @@ export function resolveFeishuGroupConfig(params: {
6869

6970
const lowered = groupId.toLowerCase();
7071
const matchKey = Object.keys(groups).find((key) => key.toLowerCase() === lowered);
71-
return matchKey ? groups[matchKey] : undefined;
72+
if (matchKey) {
73+
return groups[matchKey];
74+
}
75+
return wildcard;
7276
}
7377

7478
export function resolveFeishuGroupToolPolicy(

0 commit comments

Comments
 (0)