





























@@ -734,6 +734,89 @@ describe("runCodexAppServerAttempt", () => {
734734expect(heartbeat?.deferLoading).toBe(true);
735735});
736736737+it("keeps searchable Codex dynamic tools canonical in mirrored transcript snapshots", async () => {
738+__testing.setOpenClawCodingToolsFactoryForTests(() => [
739+createRuntimeDynamicTool("wiki_status"),
740+]);
741+const harness = createStartedThreadHarness();
742+const params = createParams(
743+path.join(tempDir, "session.jsonl"),
744+path.join(tempDir, "workspace"),
745+);
746+params.disableTools = false;
747+params.runtimePlan = createCodexRuntimePlanFixture();
748+params.toolsAllow = ["wiki_status"];
749+750+const run = runCodexAppServerAttempt(params, {
751+pluginConfig: {
752+codexDynamicToolsLoading: "searchable",
753+appServer: { mode: "yolo" },
754+},
755+});
756+await harness.waitForMethod("turn/start", 120_000);
757+758+const toolResult = (await harness.handleServerRequest({
759+id: "request-tool-wiki-status",
760+method: "item/tool/call",
761+params: {
762+threadId: "thread-1",
763+turnId: "turn-1",
764+callId: "call-wiki-status-1",
765+namespace: CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE,
766+tool: "wiki_status",
767+arguments: { topic: "README.md" },
768+},
769+})) as {
770+contentItems?: Array<{ text?: string; type?: string }>;
771+success?: boolean;
772+};
773+expect(toolResult).toEqual({
774+success: true,
775+contentItems: [{ type: "inputText", text: "wiki_status done" }],
776+});
777+778+await harness.completeTurn({ threadId: "thread-1", turnId: "turn-1" });
779+const result = await run;
780+781+expect(result.messagesSnapshot.map((message) => message.role)).toEqual([
782+"user",
783+"assistant",
784+"toolResult",
785+]);
786+expect(result.messagesSnapshot[1]).toMatchObject({
787+role: "assistant",
788+content: [
789+{
790+type: "toolCall",
791+id: "call-wiki-status-1",
792+name: "wiki_status",
793+arguments: { topic: "README.md" },
794+input: { topic: "README.md" },
795+},
796+],
797+});
798+expect(result.messagesSnapshot[2]).toMatchObject({
799+role: "toolResult",
800+toolCallId: "call-wiki-status-1",
801+toolName: "wiki_status",
802+isError: false,
803+content: [
804+expect.objectContaining({
805+type: "toolResult",
806+id: "call-wiki-status-1",
807+name: "wiki_status",
808+toolName: "wiki_status",
809+toolCallId: "call-wiki-status-1",
810+toolUseId: "call-wiki-status-1",
811+tool_use_id: "call-wiki-status-1",
812+content: "wiki_status done",
813+}),
814+],
815+});
816+expect(JSON.stringify(result.messagesSnapshot)).not.toContain("tool_search");
817+expect(JSON.stringify(result.messagesSnapshot)).not.toContain("function_call_output");
818+});
819+737820it("passes the live run session key to Codex dynamic tools when sandbox policy uses another key", () => {
738821const workspaceDir = path.join(tempDir, "workspace");
739822const params = createParams(path.join(tempDir, "session.jsonl"), workspaceDir);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。