mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 21:14:46 +00:00
Normalize Codex dynamic tool transcript shape (#80155)
* Normalize Codex dynamic tool transcript shape * test: align codex transcript aliases
This commit is contained in:
@@ -858,6 +858,7 @@ describe("CodexAppServerEventProjector", () => {
|
||||
id: "cmd-1",
|
||||
name: "bash",
|
||||
arguments: { command: "pnpm test extensions/codex", cwd: "/workspace" },
|
||||
input: { command: "pnpm test extensions/codex", cwd: "/workspace" },
|
||||
});
|
||||
const toolResultMessage = requireRecord(result.messagesSnapshot[2], "tool result message");
|
||||
expect(toolResultMessage.role).toBe("toolResult");
|
||||
@@ -867,6 +868,9 @@ describe("CodexAppServerEventProjector", () => {
|
||||
const toolResultContent = requireArray(toolResultMessage.content, "tool result content");
|
||||
const toolResultContentItem = requireRecord(toolResultContent[0], "tool result content item");
|
||||
expect(toolResultContentItem.type).toBe("toolResult");
|
||||
expect(toolResultContentItem.id).toBe("cmd-1");
|
||||
expect(toolResultContentItem.name).toBe("bash");
|
||||
expect(toolResultContentItem.toolName).toBe("bash");
|
||||
expect(toolResultContentItem.toolCallId).toBe("cmd-1");
|
||||
expect(toolResultContentItem.content).toBe("ok");
|
||||
});
|
||||
@@ -902,6 +906,7 @@ describe("CodexAppServerEventProjector", () => {
|
||||
id: "call-browser-1",
|
||||
name: "browser",
|
||||
arguments: { action: "open", url: "http://127.0.0.1:3000" },
|
||||
input: { action: "open", url: "http://127.0.0.1:3000" },
|
||||
});
|
||||
const toolResultMessage = requireRecord(result.messagesSnapshot[2], "tool result message");
|
||||
expect(toolResultMessage.role).toBe("toolResult");
|
||||
@@ -913,6 +918,9 @@ describe("CodexAppServerEventProjector", () => {
|
||||
"tool result content item",
|
||||
);
|
||||
expect(toolResultContent.type).toBe("toolResult");
|
||||
expect(toolResultContent.id).toBe("call-browser-1");
|
||||
expect(toolResultContent.name).toBe("browser");
|
||||
expect(toolResultContent.toolName).toBe("browser");
|
||||
expect(toolResultContent.toolCallId).toBe("call-browser-1");
|
||||
expect(toolResultContent.content).toBe("opened");
|
||||
});
|
||||
|
||||
@@ -1041,6 +1041,7 @@ export class CodexAppServerEventProjector {
|
||||
}
|
||||
|
||||
private createToolCallMessage(params: ToolTranscriptCallInput): AgentMessage {
|
||||
const args = normalizeToolTranscriptArguments(params.arguments);
|
||||
return {
|
||||
role: "assistant",
|
||||
content: [
|
||||
@@ -1048,7 +1049,8 @@ export class CodexAppServerEventProjector {
|
||||
type: "toolCall",
|
||||
id: params.id,
|
||||
name: params.name,
|
||||
arguments: normalizeToolTranscriptArguments(params.arguments),
|
||||
arguments: args,
|
||||
input: args,
|
||||
},
|
||||
],
|
||||
api: this.params.model.api ?? "openai-codex-responses",
|
||||
@@ -1070,6 +1072,9 @@ export class CodexAppServerEventProjector {
|
||||
content: [
|
||||
{
|
||||
type: "toolResult",
|
||||
id: params.id,
|
||||
name: params.name,
|
||||
toolName: params.name,
|
||||
toolCallId: params.id,
|
||||
toolUseId: params.id,
|
||||
tool_use_id: params.id,
|
||||
|
||||
@@ -734,6 +734,89 @@ describe("runCodexAppServerAttempt", () => {
|
||||
expect(heartbeat?.deferLoading).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps searchable Codex dynamic tools canonical in mirrored transcript snapshots", async () => {
|
||||
__testing.setOpenClawCodingToolsFactoryForTests(() => [
|
||||
createRuntimeDynamicTool("wiki_status"),
|
||||
]);
|
||||
const harness = createStartedThreadHarness();
|
||||
const params = createParams(
|
||||
path.join(tempDir, "session.jsonl"),
|
||||
path.join(tempDir, "workspace"),
|
||||
);
|
||||
params.disableTools = false;
|
||||
params.runtimePlan = createCodexRuntimePlanFixture();
|
||||
params.toolsAllow = ["wiki_status"];
|
||||
|
||||
const run = runCodexAppServerAttempt(params, {
|
||||
pluginConfig: {
|
||||
codexDynamicToolsLoading: "searchable",
|
||||
appServer: { mode: "yolo" },
|
||||
},
|
||||
});
|
||||
await harness.waitForMethod("turn/start", 120_000);
|
||||
|
||||
const toolResult = (await harness.handleServerRequest({
|
||||
id: "request-tool-wiki-status",
|
||||
method: "item/tool/call",
|
||||
params: {
|
||||
threadId: "thread-1",
|
||||
turnId: "turn-1",
|
||||
callId: "call-wiki-status-1",
|
||||
namespace: CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE,
|
||||
tool: "wiki_status",
|
||||
arguments: { topic: "README.md" },
|
||||
},
|
||||
})) as {
|
||||
contentItems?: Array<{ text?: string; type?: string }>;
|
||||
success?: boolean;
|
||||
};
|
||||
expect(toolResult).toEqual({
|
||||
success: true,
|
||||
contentItems: [{ type: "inputText", text: "wiki_status done" }],
|
||||
});
|
||||
|
||||
await harness.completeTurn({ threadId: "thread-1", turnId: "turn-1" });
|
||||
const result = await run;
|
||||
|
||||
expect(result.messagesSnapshot.map((message) => message.role)).toEqual([
|
||||
"user",
|
||||
"assistant",
|
||||
"toolResult",
|
||||
]);
|
||||
expect(result.messagesSnapshot[1]).toMatchObject({
|
||||
role: "assistant",
|
||||
content: [
|
||||
{
|
||||
type: "toolCall",
|
||||
id: "call-wiki-status-1",
|
||||
name: "wiki_status",
|
||||
arguments: { topic: "README.md" },
|
||||
input: { topic: "README.md" },
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(result.messagesSnapshot[2]).toMatchObject({
|
||||
role: "toolResult",
|
||||
toolCallId: "call-wiki-status-1",
|
||||
toolName: "wiki_status",
|
||||
isError: false,
|
||||
content: [
|
||||
expect.objectContaining({
|
||||
type: "toolResult",
|
||||
id: "call-wiki-status-1",
|
||||
name: "wiki_status",
|
||||
toolName: "wiki_status",
|
||||
toolCallId: "call-wiki-status-1",
|
||||
toolUseId: "call-wiki-status-1",
|
||||
tool_use_id: "call-wiki-status-1",
|
||||
content: "wiki_status done",
|
||||
}),
|
||||
],
|
||||
});
|
||||
expect(JSON.stringify(result.messagesSnapshot)).not.toContain("tool_search");
|
||||
expect(JSON.stringify(result.messagesSnapshot)).not.toContain("function_call_output");
|
||||
});
|
||||
|
||||
it("passes the live run session key to Codex dynamic tools when sandbox policy uses another key", () => {
|
||||
const workspaceDir = path.join(tempDir, "workspace");
|
||||
const params = createParams(path.join(tempDir, "session.jsonl"), workspaceDir);
|
||||
|
||||
Reference in New Issue
Block a user