Skip to content

Commit 8ff1d3e

Browse files
committed
fix(harness): surface returned tool errors
1 parent 49a9032 commit 8ff1d3e

3 files changed

Lines changed: 16 additions & 5 deletions

File tree

extensions/copilot/src/tool-bridge.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1314,24 +1314,33 @@ describe("convertOpenClawToolToSdkTool", () => {
13141314
);
13151315
});
13161316

1317-
it("reports returned OpenClaw error results as observer failures", async () => {
1317+
it("reports returned OpenClaw error results to both tool observers", async () => {
13181318
const onAgentToolResult = vi.fn();
1319+
const onToolCompleted = vi.fn();
13191320
const sourceResult = {
13201321
content: [{ text: '{"status":"error","error":"backend unavailable"}', type: "text" }],
13211322
details: { status: "error", error: "backend unavailable" },
13221323
};
13231324
const sdkTool = convertOpenClawToolToSdkTool(makeTool({}, sourceResult), {
13241325
onAgentToolResult,
1326+
onToolCompleted,
13251327
});
13261328

13271329
const result = await runSdkTool(sdkTool, {});
1330+
await flushAsync();
13281331

13291332
expect(result).toMatchObject({ resultType: "success" });
13301333
expect(onAgentToolResult).toHaveBeenCalledWith({
13311334
toolName: "tool-a",
13321335
result: sourceResult,
13331336
isError: true,
13341337
});
1338+
expect(onToolCompleted).toHaveBeenCalledWith(
1339+
expect.objectContaining({
1340+
error: "backend unavailable",
1341+
result: sourceResult,
1342+
}),
1343+
);
13351344
});
13361345

13371346
it("joins multiple text blocks with newlines", async () => {

extensions/copilot/src/tool-bridge.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
import {
99
applyEmbeddedAttemptToolsAllow,
1010
buildEmbeddedAttemptToolRunContext,
11+
extractToolErrorMessage,
1112
getPluginToolMeta,
1213
isSubagentSessionKey,
1314
isToolResultError,
@@ -515,15 +516,15 @@ export function convertOpenClawToolToSdkTool(
515516

516517
const sdkResult = agentToolResultToSdk(result);
517518
const sanitizedResult = sanitizeToolResult(result);
518-
notifyToolResult(
519-
sanitizedResult,
520-
sdkResult.resultType === "failure" || isToolResultError(sanitizedResult),
521-
);
519+
const resultIsError = sdkResult.resultType === "failure" || isToolResultError(sanitizedResult);
520+
const resultError = resultIsError ? extractToolErrorMessage(sanitizedResult) : undefined;
521+
notifyToolResult(sanitizedResult, resultIsError);
522522
notifyToolCompleted({
523523
toolName: sourceTool.name,
524524
toolCallId: invocation.toolCallId,
525525
args: toToolStartArgs(preparedArgs),
526526
result: sanitizedResult,
527+
...(resultError ? { error: resultError } : {}),
527528
startedAt,
528529
});
529530
return sdkResult;

src/plugin-sdk/agent-harness-runtime.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ export { isMessagingTool, isMessagingToolSendAction } from "../agents/embedded-a
131131
export {
132132
extractMessagingToolSend,
133133
extractMessagingToolSendResult,
134+
extractToolErrorMessage,
134135
extractToolResultMediaArtifact,
135136
filterToolResultMediaUrls,
136137
isToolResultError,

0 commit comments

Comments
 (0)