

















@@ -7,8 +7,10 @@ import {
77filterToolsByPolicy,
88isToolAllowedByPolicyName,
99resolveEffectiveToolPolicy,
10+resolveGroupToolPolicy,
1011resolveSubagentToolPolicy,
1112resolveSubagentToolPolicyForSession,
13+resolveTrustedGroupId,
1214} from "./pi-tools.policy.js";
1315import { createStubTool } from "./test-helpers/pi-tool-stubs.js";
1416import { providerAliasCases } from "./test-helpers/provider-alias-cases.js";
@@ -40,6 +42,137 @@ describe("pi-tools.policy", () => {
4042});
4143});
424445+describe("resolveGroupToolPolicy group context validation", () => {
46+const cfg: OpenClawConfig = {
47+channels: {
48+whatsapp: {
49+groups: {
50+"safe-room": {
51+tools: { allow: ["read"] },
52+},
53+"trusted-group": {
54+tools: { allow: ["exec", "read", "write", "edit"] },
55+},
56+},
57+},
58+},
59+tools: { allow: ["read"] },
60+};
61+62+it("rejects forged groupId when the session has no group context", () => {
63+expect(
64+resolveGroupToolPolicy({
65+config: cfg,
66+sessionKey: "agent:main:main",
67+messageProvider: "whatsapp",
68+groupId: "trusted-group",
69+groupChannel: "whatsapp",
70+}),
71+).toBeUndefined();
72+});
73+74+it("uses session-derived group policy when caller groupId disagrees", () => {
75+expect(
76+resolveGroupToolPolicy({
77+config: cfg,
78+sessionKey: "agent:main:whatsapp:group:safe-room",
79+messageProvider: "whatsapp",
80+groupId: "trusted-group",
81+groupChannel: "whatsapp",
82+}),
83+).toEqual({ allow: ["read"] });
84+});
85+86+it("accepts caller groupId when it matches session-derived group context", () => {
87+expect(
88+resolveTrustedGroupId({
89+sessionKey: "agent:main:whatsapp:group:trusted-group",
90+groupId: "trusted-group",
91+}),
92+).toEqual({ groupId: "trusted-group", dropped: false });
93+expect(
94+resolveGroupToolPolicy({
95+config: cfg,
96+sessionKey: "agent:main:whatsapp:group:trusted-group",
97+messageProvider: "whatsapp",
98+groupId: "trusted-group",
99+groupChannel: "whatsapp",
100+}),
101+).toEqual({ allow: ["exec", "read", "write", "edit"] });
102+});
103+104+it("accepts caller groupId when spawnedBy provides the trusted group context", () => {
105+expect(
106+resolveTrustedGroupId({
107+sessionKey: "agent:main:main",
108+spawnedBy: "agent:main:whatsapp:group:trusted-group",
109+groupId: "trusted-group",
110+}),
111+).toEqual({ groupId: "trusted-group", dropped: false });
112+expect(
113+resolveGroupToolPolicy({
114+config: cfg,
115+sessionKey: "agent:main:main",
116+spawnedBy: "agent:main:whatsapp:group:trusted-group",
117+messageProvider: "whatsapp",
118+groupId: "trusted-group",
119+}),
120+).toEqual({ allow: ["exec", "read", "write", "edit"] });
121+});
122+123+it("keeps specific session group policy ahead of trusted parent caller groupId", () => {
124+const scopedCfg: OpenClawConfig = {
125+channels: {
126+whatsapp: {
127+groups: {
128+room: {
129+tools: { allow: ["exec", "read"] },
130+},
131+"room:sender:alice": {
132+tools: { allow: ["read"] },
133+},
134+},
135+},
136+},
137+};
138+139+expect(
140+resolveGroupToolPolicy({
141+config: scopedCfg,
142+sessionKey: "agent:main:whatsapp:group:room:sender:alice",
143+messageProvider: "whatsapp",
144+groupId: "room",
145+}),
146+).toEqual({ allow: ["read"] });
147+});
148+149+it("prefers the session-derived channel over caller-supplied messageProvider", () => {
150+const channelCfg = {
151+channels: {
152+discord: {
153+groups: {
154+C123: { tools: { allow: ["exec"] } },
155+},
156+},
157+slack: {
158+groups: {
159+C123: { tools: { allow: ["read"] } },
160+},
161+},
162+},
163+} as unknown as OpenClawConfig;
164+165+const policy = resolveGroupToolPolicy({
166+config: channelCfg,
167+sessionKey: "agent:main:slack:group:C123",
168+messageProvider: "discord",
169+groupId: "C123",
170+});
171+172+expect(policy).toEqual({ allow: ["read"] });
173+});
174+});
175+43176describe("resolveSubagentToolPolicy depth awareness", () => {
44177const baseCfg = {
45178agents: { defaults: { subagents: { maxSpawnDepth: 2 } } },
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。