






















@@ -7,6 +7,35 @@ import {
77shouldCreateBundleMcpRuntimeForAttempt,
88} from "./attempt-tool-construction-plan.js";
9910+type EmbeddedAttemptToolConstructionPlan = ReturnType<
11+typeof resolveEmbeddedAttemptToolConstructionPlan
12+>;
13+14+function expectConstructionPlan(
15+plan: EmbeddedAttemptToolConstructionPlan,
16+expected: {
17+constructTools?: boolean;
18+includeCoreTools?: boolean;
19+runtimeToolAllowlist?: string[];
20+coding?: Partial<EmbeddedAttemptToolConstructionPlan["codingToolConstructionPlan"]>;
21+},
22+) {
23+if ("constructTools" in expected) {
24+expect(plan.constructTools).toBe(expected.constructTools);
25+}
26+if ("includeCoreTools" in expected) {
27+expect(plan.includeCoreTools).toBe(expected.includeCoreTools);
28+}
29+if ("runtimeToolAllowlist" in expected) {
30+expect(plan.runtimeToolAllowlist).toEqual(expected.runtimeToolAllowlist);
31+}
32+if (expected.coding) {
33+for (const [key, value] of Object.entries(expected.coding)) {
34+expect(plan.codingToolConstructionPlan[key as keyof typeof expected.coding]).toBe(value);
35+}
36+}
37+}
38+1039describe("applyEmbeddedAttemptToolsAllow", () => {
1140it("keeps explicit toolsAllow authoritative after force-added tools are built", () => {
1241const tools = [{ name: "exec" }, { name: "read" }, { name: "message" }];
@@ -85,10 +114,10 @@ describe("applyEmbeddedAttemptToolsAllow", () => {
8511486115describe("resolveEmbeddedAttemptToolConstructionPlan", () => {
87116it("builds all tool families when no runtime allowlist is present", () => {
88-expect(resolveEmbeddedAttemptToolConstructionPlan({})).toMatchObject({
117+expectConstructionPlan(resolveEmbeddedAttemptToolConstructionPlan({}), {
89118constructTools: true,
90119includeCoreTools: true,
91-codingToolConstructionPlan: {
120+coding: {
92121includeBaseCodingTools: true,
93122includeShellTools: true,
94123includeChannelTools: true,
@@ -99,10 +128,10 @@ describe("resolveEmbeddedAttemptToolConstructionPlan", () => {
99128});
100129101130it("short-circuits all local tool construction for explicit no-tools runs", () => {
102-expect(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: [] })).toMatchObject({
131+expectConstructionPlan(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: [] }), {
103132constructTools: false,
104133includeCoreTools: false,
105-codingToolConstructionPlan: {
134+coding: {
106135includeBaseCodingTools: false,
107136includeShellTools: false,
108137includeChannelTools: false,
@@ -113,125 +142,137 @@ describe("resolveEmbeddedAttemptToolConstructionPlan", () => {
113142});
114143115144it("materializes only plugin candidates for plugin-only allowlists", () => {
116-expect(
145+expectConstructionPlan(
117146resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["memory_search"] }),
118-).toMatchObject({
119-constructTools: true,
120-includeCoreTools: false,
121-runtimeToolAllowlist: ["memory_search"],
122-codingToolConstructionPlan: {
123-includeBaseCodingTools: false,
124-includeShellTools: false,
125-includeChannelTools: true,
126-includeOpenClawTools: false,
127-includePluginTools: true,
147+{
148+constructTools: true,
149+includeCoreTools: false,
150+runtimeToolAllowlist: ["memory_search"],
151+coding: {
152+includeBaseCodingTools: false,
153+includeShellTools: false,
154+includeChannelTools: true,
155+includeOpenClawTools: false,
156+includePluginTools: true,
157+},
128158},
129-});
159+);
130160});
131161132162it("limits known core allowlists to the matching local families", () => {
133-expect(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["read"] })).toMatchObject({
163+expectConstructionPlan(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["read"] }), {
134164constructTools: true,
135165includeCoreTools: true,
136-codingToolConstructionPlan: {
166+coding: {
137167includeBaseCodingTools: true,
138168includeShellTools: false,
139169includeChannelTools: false,
140170includeOpenClawTools: false,
141171includePluginTools: false,
142172},
143173});
144-expect(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["exec"] })).toMatchObject({
145-codingToolConstructionPlan: {
174+expectConstructionPlan(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["exec"] }), {
175+coding: {
146176includeBaseCodingTools: false,
147177includeShellTools: true,
148178includeChannelTools: false,
149179includeOpenClawTools: false,
150180includePluginTools: false,
151181},
152182});
153-expect(
183+expectConstructionPlan(
154184resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["session_status"] }),
155-).toMatchObject({
156-codingToolConstructionPlan: {
157-includeBaseCodingTools: false,
158-includeShellTools: false,
159-includeChannelTools: false,
160-includeOpenClawTools: true,
161-includePluginTools: false,
185+{
186+coding: {
187+includeBaseCodingTools: false,
188+includeShellTools: false,
189+includeChannelTools: false,
190+includeOpenClawTools: true,
191+includePluginTools: false,
192+},
162193},
163-});
164-expect(
194+);
195+expectConstructionPlan(
165196resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["update_plan"] }),
166-).toMatchObject({
167-codingToolConstructionPlan: {
168-includeBaseCodingTools: false,
169-includeShellTools: false,
170-includeChannelTools: false,
171-includeOpenClawTools: true,
172-includePluginTools: false,
197+{
198+coding: {
199+includeBaseCodingTools: false,
200+includeShellTools: false,
201+includeChannelTools: false,
202+includeOpenClawTools: true,
203+includePluginTools: false,
204+},
173205},
174-});
206+);
175207});
176208177209it("keeps plugin-owned catalog tools on the plugin construction path", () => {
178-expect(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["browser"] })).toMatchObject({
179-constructTools: true,
180-includeCoreTools: false,
181-codingToolConstructionPlan: {
182-includeBaseCodingTools: false,
183-includeShellTools: false,
184-includeChannelTools: true,
185-includeOpenClawTools: false,
186-includePluginTools: true,
210+expectConstructionPlan(
211+resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["browser"] }),
212+{
213+constructTools: true,
214+includeCoreTools: false,
215+coding: {
216+includeBaseCodingTools: false,
217+includeShellTools: false,
218+includeChannelTools: true,
219+includeOpenClawTools: false,
220+includePluginTools: true,
221+},
187222},
188-});
189-expect(
223+);
224+expectConstructionPlan(
190225resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["code_execution"] }),
191-).toMatchObject({
192-constructTools: true,
193-includeCoreTools: false,
194-codingToolConstructionPlan: {
195-includeBaseCodingTools: false,
196-includeShellTools: false,
197-includeChannelTools: true,
198-includeOpenClawTools: false,
199-includePluginTools: true,
226+{
227+constructTools: true,
228+includeCoreTools: false,
229+coding: {
230+includeBaseCodingTools: false,
231+includeShellTools: false,
232+includeChannelTools: true,
233+includeOpenClawTools: false,
234+includePluginTools: true,
235+},
200236},
201-});
202-expect(resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["x_search"] })).toMatchObject({
203-includeCoreTools: false,
204-codingToolConstructionPlan: {
205-includeChannelTools: true,
206-includeOpenClawTools: false,
207-includePluginTools: true,
237+);
238+expectConstructionPlan(
239+resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["x_search"] }),
240+{
241+includeCoreTools: false,
242+coding: {
243+includeChannelTools: true,
244+includeOpenClawTools: false,
245+includePluginTools: true,
246+},
208247},
209-});
248+);
210249});
211250212251it("keeps channel tools available for narrow channel-owned allowlists", () => {
213-expect(
252+expectConstructionPlan(
214253resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["whatsapp_login"] }),
215-).toMatchObject({
216-constructTools: true,
217-includeCoreTools: false,
218-codingToolConstructionPlan: {
219-includeBaseCodingTools: false,
220-includeShellTools: false,
221-includeChannelTools: true,
222-includeOpenClawTools: false,
223-includePluginTools: true,
254+{
255+constructTools: true,
256+includeCoreTools: false,
257+coding: {
258+includeBaseCodingTools: false,
259+includeShellTools: false,
260+includeChannelTools: true,
261+includeOpenClawTools: false,
262+includePluginTools: true,
263+},
224264},
225-});
265+);
226266});
227267228268it("skips local construction when only bundled tool runtimes can match", () => {
229-expect(
269+expectConstructionPlan(
230270resolveEmbeddedAttemptToolConstructionPlan({ toolsAllow: ["strict__strict_probe"] }),
231-).toMatchObject({
232-constructTools: false,
233-includeCoreTools: false,
234-});
271+{
272+constructTools: false,
273+includeCoreTools: false,
274+},
275+);
235276});
236277});
237278此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。