mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 17:14:33 +00:00
fix: dispatch before_tool_call and after_tool_call hooks from both tool execution paths (openclaw#15012) thanks @Patrick-Barletta
Verified: - pnpm check Co-authored-by: Patrick-Barletta <67929313+Patrick-Barletta@users.noreply.github.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import type {
|
||||
import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
|
||||
import type { ClientToolDefinition } from "./pi-embedded-runner/run/params.js";
|
||||
import { logDebug, logError } from "../logger.js";
|
||||
import { getGlobalHookRunner } from "../plugins/hook-runner-global.js";
|
||||
import { isPlainObject } from "../utils.js";
|
||||
import { runBeforeToolCallHook } from "./pi-tools.before-tool-call.js";
|
||||
import { normalizeToolName } from "./tool-policy.js";
|
||||
@@ -90,7 +91,38 @@ export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] {
|
||||
execute: async (...args: ToolExecuteArgs): Promise<AgentToolResult<unknown>> => {
|
||||
const { toolCallId, params, onUpdate, signal } = splitToolExecuteArgs(args);
|
||||
try {
|
||||
return await tool.execute(toolCallId, params, signal, onUpdate);
|
||||
// Call before_tool_call hook
|
||||
const hookOutcome = await runBeforeToolCallHook({
|
||||
toolName: name,
|
||||
params,
|
||||
toolCallId,
|
||||
});
|
||||
if (hookOutcome.blocked) {
|
||||
throw new Error(hookOutcome.reason);
|
||||
}
|
||||
const adjustedParams = hookOutcome.params;
|
||||
const result = await tool.execute(toolCallId, adjustedParams, signal, onUpdate);
|
||||
|
||||
// Call after_tool_call hook
|
||||
const hookRunner = getGlobalHookRunner();
|
||||
if (hookRunner?.hasHooks("after_tool_call")) {
|
||||
try {
|
||||
await hookRunner.runAfterToolCall(
|
||||
{
|
||||
toolName: name,
|
||||
params: isPlainObject(adjustedParams) ? adjustedParams : {},
|
||||
result,
|
||||
},
|
||||
{ toolName: name },
|
||||
);
|
||||
} catch (hookErr) {
|
||||
logDebug(
|
||||
`after_tool_call hook failed: tool=${normalizedName} error=${String(hookErr)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (signal?.aborted) {
|
||||
throw err;
|
||||
@@ -107,11 +139,33 @@ export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] {
|
||||
logDebug(`tools: ${normalizedName} failed stack:\n${described.stack}`);
|
||||
}
|
||||
logError(`[tools] ${normalizedName} failed: ${described.message}`);
|
||||
return jsonResult({
|
||||
|
||||
const errorResult = jsonResult({
|
||||
status: "error",
|
||||
tool: normalizedName,
|
||||
error: described.message,
|
||||
});
|
||||
|
||||
// Call after_tool_call hook for errors too
|
||||
const hookRunner = getGlobalHookRunner();
|
||||
if (hookRunner?.hasHooks("after_tool_call")) {
|
||||
try {
|
||||
await hookRunner.runAfterToolCall(
|
||||
{
|
||||
toolName: normalizedName,
|
||||
params: isPlainObject(params) ? params : {},
|
||||
error: described.message,
|
||||
},
|
||||
{ toolName: normalizedName },
|
||||
);
|
||||
} catch (hookErr) {
|
||||
logDebug(
|
||||
`after_tool_call hook failed: tool=${normalizedName} error=${String(hookErr)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return errorResult;
|
||||
}
|
||||
},
|
||||
} satisfies ToolDefinition;
|
||||
|
||||
Reference in New Issue
Block a user