mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
fix: keep custom pi tools executable
This commit is contained in:
@@ -132,7 +132,7 @@ import {
|
||||
buildEmbeddedSystemPrompt,
|
||||
createSystemPromptOverride,
|
||||
} from "./system-prompt.js";
|
||||
import { collectAllowedToolNames } from "./tool-name-allowlist.js";
|
||||
import { collectAllowedToolNames, toSessionToolAllowlist } from "./tool-name-allowlist.js";
|
||||
import {
|
||||
logProviderToolSchemaDiagnostics,
|
||||
normalizeProviderToolSchemas,
|
||||
@@ -839,10 +839,14 @@ export async function compactEmbeddedPiSessionDirect(
|
||||
contextTokenBudget: ctxInfo.tokens,
|
||||
});
|
||||
|
||||
const { builtInTools, customTools } = splitSdkTools({
|
||||
const { customTools } = splitSdkTools({
|
||||
tools: effectiveTools,
|
||||
sandboxEnabled: !!sandbox?.enabled,
|
||||
});
|
||||
// Pi treats `tools` as a name allowlist. Compaction uses the same custom
|
||||
// tool path as normal turns, so pass names here to keep those tools active
|
||||
// across compaction retries.
|
||||
const sessionToolAllowlist = toSessionToolAllowlist(allowedToolNames);
|
||||
|
||||
const providerStreamFn = resolveCompactionProviderStream({
|
||||
effectiveModel,
|
||||
@@ -880,7 +884,7 @@ export async function compactEmbeddedPiSessionDirect(
|
||||
modelRegistry,
|
||||
model: effectiveModel,
|
||||
thinkingLevel: mapThinkingLevel(thinkLevel),
|
||||
tools: builtInTools,
|
||||
tools: sessionToolAllowlist,
|
||||
customTools,
|
||||
sessionManager,
|
||||
settingsManager,
|
||||
|
||||
@@ -5,7 +5,7 @@ export type EmbeddedAgentSessionOptions = {
|
||||
modelRegistry: unknown;
|
||||
model: unknown;
|
||||
thinkingLevel: unknown;
|
||||
tools: readonly unknown[];
|
||||
tools: readonly string[];
|
||||
customTools: readonly unknown[];
|
||||
sessionManager: unknown;
|
||||
settingsManager: unknown;
|
||||
|
||||
@@ -167,7 +167,7 @@ import {
|
||||
createSystemPromptOverride,
|
||||
} from "../system-prompt.js";
|
||||
import { dropThinkingBlocks } from "../thinking.js";
|
||||
import { collectAllowedToolNames } from "../tool-name-allowlist.js";
|
||||
import { collectAllowedToolNames, toSessionToolAllowlist } from "../tool-name-allowlist.js";
|
||||
import {
|
||||
installContextEngineLoopHook,
|
||||
installToolResultContextGuard,
|
||||
@@ -1121,6 +1121,11 @@ export async function runEmbeddedAttempt(
|
||||
: [];
|
||||
|
||||
const allCustomTools = [...customTools, ...clientToolDefs];
|
||||
// Pi's `tools` option is a name allowlist, not the tool definitions.
|
||||
// OpenClaw registers local tools through `customTools`, so passing the
|
||||
// same names here keeps custom tools executable instead of silently
|
||||
// filtering them out with an empty allowlist.
|
||||
const sessionToolAllowlist = toSessionToolAllowlist(allowedToolNames);
|
||||
|
||||
({ session } = await createEmbeddedAgentSessionWithResourceLoader({
|
||||
createAgentSession: async (options) =>
|
||||
@@ -1132,7 +1137,7 @@ export async function runEmbeddedAttempt(
|
||||
modelRegistry: params.modelRegistry,
|
||||
model: params.model,
|
||||
thinkingLevel: mapThinkingLevel(params.thinkLevel),
|
||||
tools: builtInTools,
|
||||
tools: sessionToolAllowlist,
|
||||
customTools: allCustomTools,
|
||||
sessionManager,
|
||||
settingsManager,
|
||||
|
||||
29
src/agents/pi-embedded-runner/tool-name-allowlist.test.ts
Normal file
29
src/agents/pi-embedded-runner/tool-name-allowlist.test.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createStubTool } from "../test-helpers/pi-tool-stubs.js";
|
||||
import { collectAllowedToolNames, toSessionToolAllowlist } from "./tool-name-allowlist.js";
|
||||
|
||||
describe("tool name allowlists", () => {
|
||||
it("collects local and client tool names", () => {
|
||||
const names = collectAllowedToolNames({
|
||||
tools: [createStubTool("read"), createStubTool("memory_search")],
|
||||
clientTools: [
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "image_generate",
|
||||
description: "Generate an image",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect([...names]).toEqual(["read", "memory_search", "image_generate"]);
|
||||
});
|
||||
|
||||
it("builds a stable Pi session allowlist from custom tool names", () => {
|
||||
const allowlist = toSessionToolAllowlist(new Set(["write", "read", "read", "edit"]));
|
||||
|
||||
expect(allowlist).toEqual(["edit", "read", "write"]);
|
||||
});
|
||||
});
|
||||
@@ -24,3 +24,7 @@ export function collectAllowedToolNames(params: {
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
export function toSessionToolAllowlist(allowedToolNames: Iterable<string>): string[] {
|
||||
return [...new Set(allowedToolNames)].toSorted((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user