mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(agents): expose CLI tool summaries in terminal results (#115797)
* fix(agents): preserve CLI tool summaries * fix(agents): cover Codex collaboration tools
This commit is contained in:
committed by
GitHub
parent
6dc55fa65e
commit
1f537c36c6
@@ -14,6 +14,7 @@ import type {
|
||||
MessagingToolSend,
|
||||
MessagingToolSourceReplyPayload,
|
||||
} from "./embedded-agent-messaging.types.js";
|
||||
import type { ToolSummaryTrace } from "./embedded-agent-runner/types.js";
|
||||
|
||||
export type CliUsage = {
|
||||
input?: number;
|
||||
@@ -51,6 +52,7 @@ export type CliOutput = {
|
||||
usage?: CliUsage;
|
||||
/** Terminal cumulative turn usage for diagnostics; reply accounting keeps using `usage`. */
|
||||
diagnosticUsage?: CliUsage;
|
||||
toolSummary?: ToolSummaryTrace;
|
||||
errorText?: string;
|
||||
terminalFailure?: CliTerminalFailure;
|
||||
diagnostics?: {
|
||||
@@ -154,6 +156,11 @@ function isGeminiCliProvider(providerId: string): boolean {
|
||||
return normalizeLowercaseStringOrEmpty(providerId) === "google-gemini-cli";
|
||||
}
|
||||
|
||||
function isCodexExecJsonlProvider(providerId: string): boolean {
|
||||
const normalized = normalizeLowercaseStringOrEmpty(providerId);
|
||||
return normalized === "codex" || normalized === "codex-cli";
|
||||
}
|
||||
|
||||
function isGeminiStreamJsonDialect(params: {
|
||||
backend: CliBackendConfig;
|
||||
providerId: string;
|
||||
@@ -1167,6 +1174,128 @@ function dispatchGeminiCliStreamingToolEvent(params: {
|
||||
}
|
||||
}
|
||||
|
||||
type CodexToolEvent = {
|
||||
toolCallId: string;
|
||||
name: string;
|
||||
kind: CliToolUseStartDelta["kind"];
|
||||
args: Record<string, unknown>;
|
||||
result?: unknown;
|
||||
isError: boolean;
|
||||
};
|
||||
|
||||
function readCodexToolEvent(item: Record<string, unknown>): CodexToolEvent | null {
|
||||
const toolCallId = typeof item.id === "string" ? item.id.trim() : "";
|
||||
if (!toolCallId) {
|
||||
return null;
|
||||
}
|
||||
const type = normalizeLowercaseStringOrEmpty(item.type);
|
||||
if (type === "command_execution") {
|
||||
return {
|
||||
toolCallId,
|
||||
name: "bash",
|
||||
kind: "tool_use",
|
||||
args: typeof item.command === "string" ? { command: item.command } : {},
|
||||
result: item.aggregated_output,
|
||||
isError: item.status === "failed" || item.status === "declined",
|
||||
};
|
||||
}
|
||||
if (type === "file_change") {
|
||||
return {
|
||||
toolCallId,
|
||||
name: "apply_patch",
|
||||
kind: "tool_use",
|
||||
args: Array.isArray(item.changes) ? { changes: item.changes } : {},
|
||||
result: item.changes,
|
||||
isError: item.status === "failed",
|
||||
};
|
||||
}
|
||||
if (type === "web_search") {
|
||||
return {
|
||||
toolCallId,
|
||||
name: "web_search",
|
||||
kind: "server_tool_use",
|
||||
args: typeof item.query === "string" ? { query: item.query } : {},
|
||||
result: item.query,
|
||||
isError: false,
|
||||
};
|
||||
}
|
||||
if (type !== "mcp_tool_call") {
|
||||
if (type !== "collab_tool_call") {
|
||||
return null;
|
||||
}
|
||||
const tool = typeof item.tool === "string" ? item.tool.trim() : "";
|
||||
if (!tool) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
toolCallId,
|
||||
name: `collab.${tool}`,
|
||||
kind: "server_tool_use",
|
||||
args: {
|
||||
...(typeof item.sender_thread_id === "string"
|
||||
? { sender_thread_id: item.sender_thread_id }
|
||||
: {}),
|
||||
...(Array.isArray(item.receiver_thread_ids)
|
||||
? { receiver_thread_ids: item.receiver_thread_ids }
|
||||
: {}),
|
||||
...(typeof item.prompt === "string" ? { prompt: item.prompt } : {}),
|
||||
},
|
||||
result: item.agents_states,
|
||||
isError: item.status === "failed",
|
||||
};
|
||||
}
|
||||
const server = typeof item.server === "string" ? item.server.trim() : "";
|
||||
const tool = typeof item.tool === "string" ? item.tool.trim() : "";
|
||||
if (!tool) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
toolCallId,
|
||||
name: server ? `${server}.${tool}` : tool,
|
||||
kind: "mcp_tool_use",
|
||||
args: isRecord(item.arguments) ? item.arguments : {},
|
||||
result: item.status === "failed" ? item.error : item.result,
|
||||
isError: item.status === "failed",
|
||||
};
|
||||
}
|
||||
|
||||
function dispatchCodexCliStreamingToolEvent(params: {
|
||||
providerId: string;
|
||||
parsed: Record<string, unknown>;
|
||||
tracker: ToolUseTracker;
|
||||
onToolUseStart?: (delta: CliToolUseStartDelta) => void;
|
||||
onToolResult?: (delta: CliToolResultDelta) => void;
|
||||
}): void {
|
||||
if (
|
||||
!isCodexExecJsonlProvider(params.providerId) ||
|
||||
(params.parsed.type !== "item.started" && params.parsed.type !== "item.completed") ||
|
||||
!isRecord(params.parsed.item)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const event = readCodexToolEvent(params.parsed.item);
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
emitToolStartOnce(
|
||||
params.tracker,
|
||||
event.toolCallId,
|
||||
event.name,
|
||||
event.kind,
|
||||
event.args,
|
||||
params.onToolUseStart,
|
||||
);
|
||||
if (params.parsed.type === "item.completed") {
|
||||
emitToolResultOnce(
|
||||
params.tracker,
|
||||
event.toolCallId,
|
||||
event.isError,
|
||||
event.result,
|
||||
params.onToolResult,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const GEMINI_CLI_ERROR_EVENT_FALLBACK = "Gemini CLI emitted an error event.";
|
||||
const GEMINI_CLI_RESULT_ERROR_FALLBACK = "Gemini CLI result status was error.";
|
||||
|
||||
@@ -1398,6 +1527,13 @@ export function createCliJsonlStreamingParser(params: {
|
||||
}
|
||||
|
||||
if (params.onToolUseStart || params.onToolResult) {
|
||||
dispatchCodexCliStreamingToolEvent({
|
||||
providerId: params.providerId,
|
||||
parsed,
|
||||
tracker: toolTracker,
|
||||
onToolUseStart: params.onToolUseStart,
|
||||
onToolResult: params.onToolResult,
|
||||
});
|
||||
dispatchGeminiCliStreamingToolEvent({
|
||||
backend: params.backend,
|
||||
providerId: params.providerId,
|
||||
|
||||
@@ -217,6 +217,21 @@ describe("runCliAgent before_agent_reply seam", () => {
|
||||
expect(executePreparedCliRunMock).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("projects CLI tool summaries onto terminal run metadata", async () => {
|
||||
executePreparedCliRunMock.mockResolvedValue({
|
||||
text: "done",
|
||||
toolSummary: { calls: 1, tools: ["github.search"], failures: 0 },
|
||||
});
|
||||
|
||||
const result = await runCliAgent(baseRunParams);
|
||||
|
||||
expect(result.meta.toolSummary).toEqual({
|
||||
calls: 1,
|
||||
tools: ["github.search"],
|
||||
failures: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves the send phase when execution fails before successful cleanup", async () => {
|
||||
executePreparedCliRunMock.mockRejectedValueOnce(new Error("CLI process failed"));
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/** Tests Codex exec JSONL tool-summary projection through the CLI process boundary. */
|
||||
import { readFileSync } from "node:fs";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildPreparedCliRunContext,
|
||||
type PreparedCliRunContextOverrides,
|
||||
} from "./cli-runner.test-helpers.js";
|
||||
import { createManagedRun, supervisorSpawnMock } from "./cli-runner.test-support.js";
|
||||
import { executePreparedCliRun } from "./cli-runner/execute.js";
|
||||
|
||||
const CODEX_BACKEND: PreparedCliRunContextOverrides["backend"] = {
|
||||
output: "jsonl",
|
||||
sessionIdFields: ["thread_id"],
|
||||
systemPromptFileConfigArg: undefined,
|
||||
};
|
||||
|
||||
function queueCodexFixture(name: string) {
|
||||
supervisorSpawnMock.mockResolvedValueOnce(
|
||||
createManagedRun({
|
||||
reason: "exit",
|
||||
exitCode: 0,
|
||||
exitSignal: null,
|
||||
durationMs: 10,
|
||||
stdout: readFileSync(`test/fixtures/cli/${name}.jsonl`, "utf8"),
|
||||
stderr: "",
|
||||
timedOut: false,
|
||||
noOutputTimedOut: false,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async function runCodexFixture(name: string) {
|
||||
queueCodexFixture(name);
|
||||
return await executePreparedCliRun(
|
||||
buildPreparedCliRunContext({
|
||||
provider: "codex-cli",
|
||||
model: "gpt-5.5",
|
||||
backend: CODEX_BACKEND,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
supervisorSpawnMock.mockReset();
|
||||
});
|
||||
|
||||
describe("Codex CLI tool summaries", () => {
|
||||
it("emits an explicit empty summary for a successful zero-tool turn", async () => {
|
||||
const output = await runCodexFixture("codex-tool-summary-zero");
|
||||
|
||||
expect(output.toolSummary).toEqual({ calls: 0, tools: [], failures: 0 });
|
||||
});
|
||||
|
||||
it("counts paired MCP lifecycle events once", async () => {
|
||||
const output = await runCodexFixture("codex-tool-summary-paired-mcp");
|
||||
|
||||
expect(output.toolSummary).toEqual({ calls: 1, tools: ["github.search"], failures: 0 });
|
||||
});
|
||||
|
||||
it("projects terminal-only MCP and native items in first-observed order", async () => {
|
||||
const output = await runCodexFixture("codex-tool-summary-terminal-only");
|
||||
|
||||
expect(output.toolSummary).toEqual({
|
||||
calls: 4,
|
||||
tools: ["lookup", "bash", "apply_patch", "web_search"],
|
||||
failures: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("counts a typed failed terminal MCP item", async () => {
|
||||
const output = await runCodexFixture("codex-tool-summary-failed-mcp");
|
||||
|
||||
expect(output.toolSummary).toEqual({ calls: 1, tools: ["docs.read"], failures: 1 });
|
||||
});
|
||||
|
||||
it("counts a declined command terminal as a failure", async () => {
|
||||
const output = await runCodexFixture("codex-tool-summary-declined-command");
|
||||
|
||||
expect(output.toolSummary).toEqual({ calls: 1, tools: ["bash"], failures: 1 });
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
fixture: "codex-tool-summary-collab-paired",
|
||||
tool: "collab.spawn_agent",
|
||||
failures: 0,
|
||||
},
|
||||
{
|
||||
fixture: "codex-tool-summary-collab-terminal-only",
|
||||
tool: "collab.wait",
|
||||
failures: 0,
|
||||
},
|
||||
{
|
||||
fixture: "codex-tool-summary-collab-failed",
|
||||
tool: "collab.send_input",
|
||||
failures: 1,
|
||||
},
|
||||
{
|
||||
fixture: "codex-tool-summary-collab-close-agent",
|
||||
tool: "collab.close_agent",
|
||||
failures: 0,
|
||||
},
|
||||
])("projects $fixture lifecycle metadata", async ({ fixture, tool, failures }) => {
|
||||
const output = await runCodexFixture(fixture);
|
||||
|
||||
expect(output.toolSummary).toEqual({ calls: 1, tools: [tool], failures });
|
||||
});
|
||||
});
|
||||
@@ -1209,6 +1209,9 @@ export async function runPreparedCliAgent(
|
||||
stopReason,
|
||||
refusal: false,
|
||||
},
|
||||
...(resultParams.output.toolSummary
|
||||
? { toolSummary: resultParams.output.toolSummary }
|
||||
: {}),
|
||||
agentMeta: {
|
||||
sessionId: agentSessionId,
|
||||
provider: params.provider,
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
CliThinkingProgress,
|
||||
CliToolUseStartDelta,
|
||||
} from "../cli-output.js";
|
||||
import type { ToolSummaryTrace } from "../embedded-agent-runner/types.js";
|
||||
import { sanitizeToolArgs, sanitizeToolResult } from "../embedded-agent-subscribe.tools.js";
|
||||
import { applyPluginTextReplacements } from "../plugin-text-transforms.js";
|
||||
import { resolveCliToolTerminalReason } from "../run-termination.js";
|
||||
@@ -20,6 +21,10 @@ type CliToolResult = {
|
||||
result?: unknown;
|
||||
};
|
||||
|
||||
function resolveCliToolSource(name: string, kind?: CliToolUseStartDelta["kind"]): "core" | "mcp" {
|
||||
return kind === "mcp_tool_use" || name.startsWith("mcp__") ? "mcp" : "core";
|
||||
}
|
||||
|
||||
export function createCliEventHandlers(params: {
|
||||
context: PreparedCliRunContext;
|
||||
toolTracking: CliToolTracking;
|
||||
@@ -32,12 +37,49 @@ export function createCliEventHandlers(params: {
|
||||
let signaledToolExecutionStarted = false;
|
||||
let signaledAssistantOutputStarted = false;
|
||||
let commentaryCounter = 0;
|
||||
const toolSummaryById = new Map<string, { name: string; failed: boolean }>();
|
||||
const toolSummaryNames: string[] = [];
|
||||
const toolSummaryNameSet = new Set<string>();
|
||||
const activeParsedTools = new Map<
|
||||
string,
|
||||
{ startedAt: number; toolName: string; kind: CliToolUseStartDelta["kind"] }
|
||||
>();
|
||||
const rememberToolName = (name: string) => {
|
||||
if (!name || toolSummaryNameSet.has(name)) {
|
||||
return;
|
||||
}
|
||||
toolSummaryNameSet.add(name);
|
||||
toolSummaryNames.push(name);
|
||||
};
|
||||
const recordToolStart = (event: CliToolUseStartDelta) => {
|
||||
const current = toolSummaryById.get(event.toolCallId);
|
||||
if (!current) {
|
||||
toolSummaryById.set(event.toolCallId, { name: event.name, failed: false });
|
||||
} else if (!current.name && event.name) {
|
||||
current.name = event.name;
|
||||
}
|
||||
rememberToolName(event.name);
|
||||
};
|
||||
const recordToolResult = (event: CliToolResult) => {
|
||||
const current = toolSummaryById.get(event.toolCallId);
|
||||
if (current) {
|
||||
current.failed ||= event.isError;
|
||||
if (!current.name && event.name) {
|
||||
current.name = event.name;
|
||||
}
|
||||
} else {
|
||||
toolSummaryById.set(event.toolCallId, { name: event.name, failed: event.isError });
|
||||
}
|
||||
rememberToolName(event.name);
|
||||
};
|
||||
const getToolSummary = (): ToolSummaryTrace => ({
|
||||
calls: toolSummaryById.size,
|
||||
tools: toolSummaryNames.slice(),
|
||||
failures: Array.from(toolSummaryById.values()).filter((entry) => entry.failed).length,
|
||||
});
|
||||
const emitCliToolUseStart = (event: CliToolUseStartDelta) => {
|
||||
observedCliActivity = true;
|
||||
recordToolStart(event);
|
||||
if (!signaledToolExecutionStarted) {
|
||||
signaledToolExecutionStarted = true;
|
||||
runParams.onExecutionPhase?.({
|
||||
@@ -63,6 +105,7 @@ export function createCliEventHandlers(params: {
|
||||
};
|
||||
const emitCliToolResult = (event: CliToolResult) => {
|
||||
observedCliActivity = true;
|
||||
recordToolResult(event);
|
||||
params.toolTracking.handleCliToolResult(event);
|
||||
if (emitLiveEvents) {
|
||||
emitAgentEvent({
|
||||
@@ -92,7 +135,7 @@ export function createCliEventHandlers(params: {
|
||||
...(runParams.sessionKey ? { sessionKey: runParams.sessionKey } : {}),
|
||||
...(runParams.agentId ? { agentId: runParams.agentId } : {}),
|
||||
toolName: event.name,
|
||||
toolSource: event.name.startsWith("mcp__") ? "mcp" : "core",
|
||||
toolSource: resolveCliToolSource(event.name, event.kind),
|
||||
toolOwner: "cli-runner",
|
||||
toolCallId: event.toolCallId,
|
||||
});
|
||||
@@ -136,7 +179,7 @@ export function createCliEventHandlers(params: {
|
||||
...(runParams.sessionKey ? { sessionKey: runParams.sessionKey } : {}),
|
||||
...(runParams.agentId ? { agentId: runParams.agentId } : {}),
|
||||
toolName,
|
||||
toolSource: toolName.startsWith("mcp__") ? ("mcp" as const) : ("core" as const),
|
||||
toolSource: resolveCliToolSource(toolName, activeTool?.kind),
|
||||
toolOwner: "cli-runner",
|
||||
toolCallId: event.toolCallId,
|
||||
durationMs: Math.max(0, now - (activeTool?.startedAt ?? now)),
|
||||
@@ -294,6 +337,7 @@ export function createCliEventHandlers(params: {
|
||||
emitCliPlanUpdate,
|
||||
hasObservedCliActivity: () => observedCliActivity,
|
||||
activeParsedToolCount: () => activeParsedTools.size,
|
||||
getToolSummary,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -515,7 +515,10 @@ export async function executePreparedCliRun(
|
||||
if (!runOutput) {
|
||||
throw new Error("CLI run completed without output");
|
||||
}
|
||||
return toolTracking.withExecutionEvidence(runOutput);
|
||||
return toolTracking.withExecutionEvidence({
|
||||
...runOutput,
|
||||
toolSummary: events.getToolSummary(),
|
||||
});
|
||||
};
|
||||
try {
|
||||
completedOutput = await enqueueCliRun(queueKey, async () => {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{"type":"thread.started","thread_id":"thread-collab-close"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.started","item":{"id":"collab-close","type":"collab_tool_call","tool":"close_agent","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":null,"agents_states":{"thread-child":{"status":"running","message":null}},"status":"in_progress"}}
|
||||
{"type":"item.completed","item":{"id":"collab-close","type":"collab_tool_call","tool":"close_agent","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":null,"agents_states":{"thread-child":{"status":"shutdown","message":null}},"status":"completed"}}
|
||||
{"type":"item.completed","item":{"id":"message-collab-close","type":"agent_message","text":"collab closed"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
|
||||
@@ -0,0 +1,5 @@
|
||||
{"type":"thread.started","thread_id":"thread-collab-failed"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.completed","item":{"id":"collab-failed","type":"collab_tool_call","tool":"send_input","sender_thread_id":"thread-parent","receiver_thread_ids":["missing-thread"],"prompt":"continue","agents_states":{"missing-thread":{"status":"not_found","message":"agent not found"}},"status":"failed"}}
|
||||
{"type":"item.completed","item":{"id":"message-collab-failed","type":"agent_message","text":"collab failed"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{"type":"thread.started","thread_id":"thread-collab-paired"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.started","item":{"id":"collab-paired","type":"collab_tool_call","tool":"spawn_agent","sender_thread_id":"thread-parent","receiver_thread_ids":[],"prompt":"draft a plan","agents_states":{},"status":"in_progress"}}
|
||||
{"type":"item.completed","item":{"id":"collab-paired","type":"collab_tool_call","tool":"spawn_agent","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":"draft a plan","agents_states":{"thread-child":{"status":"running","message":null}},"status":"completed"}}
|
||||
{"type":"item.completed","item":{"id":"message-collab-paired","type":"agent_message","text":"collab paired"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":5,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":3,"reasoning_output_tokens":0}}
|
||||
@@ -0,0 +1,5 @@
|
||||
{"type":"thread.started","thread_id":"thread-collab-terminal"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.completed","item":{"id":"collab-terminal","type":"collab_tool_call","tool":"wait","sender_thread_id":"thread-parent","receiver_thread_ids":["thread-child"],"prompt":null,"agents_states":{"thread-child":{"status":"completed","message":"done"}},"status":"completed"}}
|
||||
{"type":"item.completed","item":{"id":"message-collab-terminal","type":"agent_message","text":"collab terminal"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{"type":"thread.started","thread_id":"thread-declined"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.started","item":{"id":"command-declined","type":"command_execution","command":"rm protected.txt","aggregated_output":"","status":"in_progress"}}
|
||||
{"type":"item.completed","item":{"id":"command-declined","type":"command_execution","command":"rm protected.txt","aggregated_output":"","status":"declined"}}
|
||||
{"type":"item.completed","item":{"id":"message-declined","type":"agent_message","text":"command declined"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":4,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
|
||||
@@ -0,0 +1,5 @@
|
||||
{"type":"thread.started","thread_id":"thread-failed"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.completed","item":{"id":"mcp-failed","type":"mcp_tool_call","server":"docs","tool":"read","arguments":{"path":"missing"},"error":{"message":"not found"},"status":"failed"}}
|
||||
{"type":"item.completed","item":{"id":"message-failed","type":"agent_message","text":"handled failure"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":6,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":3,"reasoning_output_tokens":0}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{"type":"thread.started","thread_id":"thread-paired"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.started","item":{"id":"mcp-paired","type":"mcp_tool_call","server":"github","tool":"search","arguments":{"query":"openclaw"},"status":"in_progress"}}
|
||||
{"type":"item.completed","item":{"id":"mcp-paired","type":"mcp_tool_call","server":"github","tool":"search","arguments":{"query":"openclaw"},"result":{"content":[],"structured_content":{}},"status":"completed"}}
|
||||
{"type":"item.completed","item":{"id":"message-paired","type":"agent_message","text":"paired mcp"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":5,"cached_input_tokens":1,"cache_write_input_tokens":0,"output_tokens":3,"reasoning_output_tokens":0}}
|
||||
@@ -0,0 +1,8 @@
|
||||
{"type":"thread.started","thread_id":"thread-terminal-only"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.completed","item":{"id":"mcp-terminal","type":"mcp_tool_call","server":"","tool":"lookup","arguments":{"id":"42"},"result":{"content":[],"structured_content":{}},"status":"completed"}}
|
||||
{"type":"item.completed","item":{"id":"command-terminal","type":"command_execution","command":"pwd","aggregated_output":"/workspace\n","exit_code":0,"status":"completed"}}
|
||||
{"type":"item.completed","item":{"id":"patch-terminal","type":"file_change","changes":[{"path":"README.md","kind":"update"}],"status":"completed"}}
|
||||
{"type":"item.completed","item":{"id":"search-terminal","type":"web_search","query":"OpenClaw"}}
|
||||
{"type":"item.completed","item":{"id":"message-terminal","type":"agent_message","text":"terminal only"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":8,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":4,"reasoning_output_tokens":1}}
|
||||
@@ -0,0 +1,4 @@
|
||||
{"type":"thread.started","thread_id":"thread-zero"}
|
||||
{"type":"turn.started"}
|
||||
{"type":"item.completed","item":{"id":"message-zero","type":"agent_message","text":"zero tools"}}
|
||||
{"type":"turn.completed","usage":{"input_tokens":3,"cached_input_tokens":0,"cache_write_input_tokens":0,"output_tokens":2,"reasoning_output_tokens":0}}
|
||||
Reference in New Issue
Block a user