mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:10:43 +00:00
fix(agents): honor explicit cron tool allowlists
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
buildAfterTurnRuntimeContextFromUsage,
|
||||
composeSystemPromptWithHookContext,
|
||||
decodeHtmlEntitiesInObject,
|
||||
applyEmbeddedAttemptToolsAllow,
|
||||
isPrimaryBootstrapRun,
|
||||
mergeOrphanedTrailingUserPrompt,
|
||||
prependSystemPromptAddition,
|
||||
@@ -61,6 +62,16 @@ async function invokeWrappedTestStream(
|
||||
return await Promise.resolve(wrappedFn({} as never, {} as never, {} as never));
|
||||
}
|
||||
|
||||
describe("applyEmbeddedAttemptToolsAllow", () => {
|
||||
it("keeps explicit toolsAllow authoritative after force-added tools are built", () => {
|
||||
const tools = [{ name: "exec" }, { name: "read" }, { name: "message" }];
|
||||
|
||||
expect(
|
||||
applyEmbeddedAttemptToolsAllow(tools, ["exec", "read"]).map((tool) => tool.name),
|
||||
).toEqual(["exec", "read"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolvePromptBuildHookResult", () => {
|
||||
function createLegacyOnlyHookRunner() {
|
||||
return {
|
||||
|
||||
@@ -403,6 +403,17 @@ function summarizeSessionContext(messages: AgentMessage[]): {
|
||||
};
|
||||
}
|
||||
|
||||
export function applyEmbeddedAttemptToolsAllow<T extends { name: string }>(
|
||||
tools: T[],
|
||||
toolsAllow?: string[],
|
||||
): T[] {
|
||||
if (!toolsAllow || toolsAllow.length === 0) {
|
||||
return tools;
|
||||
}
|
||||
const allowSet = new Set(toolsAllow);
|
||||
return tools.filter((tool) => allowSet.has(tool.name));
|
||||
}
|
||||
|
||||
export async function runEmbeddedAttempt(
|
||||
params: EmbeddedRunAttemptParams,
|
||||
): Promise<EmbeddedRunAttemptResult> {
|
||||
@@ -536,14 +547,7 @@ export async function runEmbeddedAttempt(
|
||||
abortSessionForYield?.();
|
||||
},
|
||||
});
|
||||
if (params.toolsAllow && params.toolsAllow.length > 0) {
|
||||
const allowSet = new Set(params.toolsAllow);
|
||||
if (params.forceMessageTool) {
|
||||
allowSet.add("message");
|
||||
}
|
||||
return allTools.filter((tool) => allowSet.has(tool.name));
|
||||
}
|
||||
return allTools;
|
||||
return applyEmbeddedAttemptToolsAllow(allTools, params.toolsAllow);
|
||||
})();
|
||||
const toolsEnabled = supportsModelTools(params.model);
|
||||
const bootstrapHasFileAccess = toolsEnabled && toolsRaw.some((tool) => tool.name === "read");
|
||||
|
||||
@@ -279,6 +279,23 @@ describe("createOpenClawCodingTools", () => {
|
||||
expect(cronTools.some((tool) => tool.name === "message")).toBe(true);
|
||||
});
|
||||
|
||||
it("can keep message available when a cron route needs it under a provider coding profile", () => {
|
||||
const providerProfileTools = createOpenClawCodingTools({
|
||||
config: { tools: { byProvider: { openai: { profile: "coding" } } } },
|
||||
modelProvider: "openai",
|
||||
modelId: "gpt-5.4",
|
||||
});
|
||||
expect(providerProfileTools.some((tool) => tool.name === "message")).toBe(false);
|
||||
|
||||
const cronTools = createOpenClawCodingTools({
|
||||
config: { tools: { byProvider: { openai: { profile: "coding" } } } },
|
||||
modelProvider: "openai",
|
||||
modelId: "gpt-5.4",
|
||||
forceMessageTool: true,
|
||||
});
|
||||
expect(cronTools.some((tool) => tool.name === "message")).toBe(true);
|
||||
});
|
||||
|
||||
it("expands group shorthands in global tool policy", () => {
|
||||
const tools = createOpenClawCodingTools({
|
||||
config: { tools: { allow: ["group:fs"] } },
|
||||
|
||||
@@ -387,10 +387,10 @@ export function createOpenClawCodingTools(options?: {
|
||||
...(profileAlsoAllow ?? []),
|
||||
...runtimeProfileAlsoAllow,
|
||||
]);
|
||||
const providerProfilePolicyWithAlsoAllow = mergeAlsoAllowPolicy(
|
||||
providerProfilePolicy,
|
||||
providerProfileAlsoAllow,
|
||||
);
|
||||
const providerProfilePolicyWithAlsoAllow = mergeAlsoAllowPolicy(providerProfilePolicy, [
|
||||
...(providerProfileAlsoAllow ?? []),
|
||||
...runtimeProfileAlsoAllow,
|
||||
]);
|
||||
// Prefer sessionKey for process isolation scope to prevent cross-session process visibility/killing.
|
||||
// Fallback to agentId if no sessionKey is available (e.g. legacy or global contexts).
|
||||
const scopeKey =
|
||||
|
||||
Reference in New Issue
Block a user