

























@@ -1,5 +1,6 @@
11import { describe, expect, it } from "vitest";
22import type { OpenClawConfig } from "../config/config.js";
3+import { createOpenClawTools } from "./openclaw-tools.js";
34import { isUpdatePlanToolEnabledForOpenClawTools } from "./openclaw-tools.registration.js";
45import { createUpdatePlanTool } from "./tools/update-plan-tool.js";
56@@ -31,6 +32,25 @@ describe("openclaw-tools update_plan gating", () => {
3132expectUpdatePlanEnabled({ config: {} as OpenClawConfig }, false);
3233});
333435+it("does not expose update_plan from default tool construction", () => {
36+const defaultTools = createOpenClawTools({
37+config: {} as OpenClawConfig,
38+disablePluginTools: true,
39+modelProvider: "anthropic",
40+modelId: "claude-sonnet-4-6",
41+});
42+const emptyAllowlistTools = createOpenClawTools({
43+config: {} as OpenClawConfig,
44+disablePluginTools: true,
45+pluginToolAllowlist: [],
46+modelProvider: "anthropic",
47+modelId: "claude-sonnet-4-6",
48+});
49+50+expect(defaultTools.some((tool) => tool.name === "update_plan")).toBe(false);
51+expect(emptyAllowlistTools.some((tool) => tool.name === "update_plan")).toBe(false);
52+});
53+3454it("registers update_plan when explicitly enabled", () => {
3555const config = {
3656tools: {
@@ -44,6 +64,54 @@ describe("openclaw-tools update_plan gating", () => {
4464expect(createUpdatePlanTool().displaySummary).toBe("Track a short structured work plan.");
4565});
466667+it("registers update_plan when the runtime allowlist explicitly requests it", () => {
68+const tools = createOpenClawTools({
69+config: {} as OpenClawConfig,
70+disablePluginTools: true,
71+pluginToolAllowlist: ["update_plan"],
72+modelProvider: "anthropic",
73+modelId: "claude-sonnet-4-6",
74+});
75+76+expect(tools.some((tool) => tool.name === "update_plan")).toBe(true);
77+});
78+79+it("registers update_plan when a config allowlist group includes it", () => {
80+const tools = createOpenClawTools({
81+config: { tools: { allow: ["group:agents"] } } as OpenClawConfig,
82+disablePluginTools: true,
83+modelProvider: "anthropic",
84+modelId: "claude-sonnet-4-6",
85+});
86+87+expect(tools.some((tool) => tool.name === "update_plan")).toBe(true);
88+});
89+90+it("registers update_plan when a runtime allowlist group includes it", () => {
91+const tools = createOpenClawTools({
92+config: {} as OpenClawConfig,
93+disablePluginTools: true,
94+pluginToolAllowlist: ["group:agents"],
95+modelProvider: "anthropic",
96+modelId: "claude-sonnet-4-6",
97+});
98+99+expect(tools.some((tool) => tool.name === "update_plan")).toBe(true);
100+});
101+102+it("respects deny policy while constructing update_plan for grouped allowlists", () => {
103+const tools = createOpenClawTools({
104+config: {} as OpenClawConfig,
105+disablePluginTools: true,
106+pluginToolAllowlist: ["group:agents"],
107+pluginToolDenylist: ["update_plan"],
108+modelProvider: "anthropic",
109+modelId: "claude-sonnet-4-6",
110+});
111+112+expect(tools.some((tool) => tool.name === "update_plan")).toBe(false);
113+});
114+47115it("auto-enables update_plan for unconfigured GPT-5 openai runs", () => {
48116// Criterion 1 of the GPT-5.4 parity gate ("no stalls after planning") is
49117// universal, not opt-in. Unspecified executionContract on a supported
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。