const test = require("node:test"); const assert = require("node:assert/strict"); const { responsesToChat } = require("../electron/lib/translate"); test("chat projection keeps completed custom tool results without forwarding tool protocol", () => { const result = responsesToChat({ model: "codex-model", stream: true, tool_choice: "auto", input: [ { type: "additional_tools", role: "system", tools: [{ name: "exec_command" }] }, { type: "message", role: "user", content: [{ type: "input_text", text: "识别这张图" }] }, { type: "custom_tool_call", call_id: "call_1", name: "exec_command", input: "tesseract image.png" }, { type: "custom_tool_call_output", call_id: "call_1", output: [{ type: "text", text: "识别结果:设置" }] }, { type: "message", role: "user", content: [ { type: "input_image", image_url: "data:image/png;base64,abc" }, { type: "input_text", text: "[TD 多模态识别证据] 设置页面" }, ], }, ], }, "deepseek-chat"); assert.equal(result.model, "deepseek-chat"); assert.equal(result.tools, undefined); assert.equal(result.tool_choice, undefined); assert.match(result.messages[0].content, /不能调用本地工具/); assert.ok(result.messages.some((message) => /工具:exec_command/.test(message.content))); assert.ok(result.messages.some((message) => /识别结果:设置/.test(message.content))); assert.ok(result.messages.some((message) => /TD 多模态识别证据/.test(message.content))); assert.ok(result.messages.every((message) => message.role !== "tool" && !message.tool_calls)); }); test("chat projection forwards native tools only when they are supplied", () => { const withoutTools = responsesToChat({ model: "model", tool_choice: "auto", input: "你好" }); assert.equal(withoutTools.tool_choice, undefined); const withTools = responsesToChat({ model: "model", tool_choice: "auto", tools: [{ type: "function", name: "lookup", parameters: { type: "object" } }], input: "你好", }); assert.equal(withTools.tool_choice, "auto"); assert.equal(withTools.tools[0].function.name, "lookup"); }); test("chat projection forwards Codex additional_tools so coding agents can execute", () => { const result = responsesToChat({ model: "deepseek-chat", tool_choice: "auto", input: [ { type: "additional_tools", role: "developer", tools: [{ type: "function", name: "exec_command", description: "Run a shell command", parameters: { type: "object", properties: { cmd: { type: "string" } }, required: ["cmd"], }, }], }, { type: "message", role: "user", content: "发布热更" }, ], }); assert.equal(result.tool_choice, "auto"); assert.equal(result.tools.length, 1); assert.equal(result.tools[0].function.name, "exec_command"); assert.doesNotMatch(result.messages[0].content, /不能调用本地工具/); }); test("multimodal chat projection removes image reading but keeps coding tools", () => { const result = responsesToChat({ model: "model", tool_choice: "auto", tools: [ { type: "function", name: "exec_command", parameters: { type: "object" } }, { type: "function", name: "view_image", parameters: { type: "object" } }, { type: "web_search_preview" }, ], input: "识别图片", }, undefined, { omitVisualTools: true }); assert.equal(result.tool_choice, "auto"); assert.deepEqual(result.tools.map((tool) => tool.function.name), ["exec_command"]); }); test("chat projection never forwards media Base64 from tool messages", () => { const image = "data:image/png;base64," + "A".repeat(2 * 1024 * 1024); const result = responsesToChat({ model: "deepseek-chat", input: [{ type: "message", role: "tool", content: [{ type: "input_image", image_url: image }], }], }); const content = result.messages.map((message) => String(message.content || "")).join("\n"); assert.match(content, /图像二进制已省略/); assert.doesNotMatch(content, /data:image/); assert.ok(result.messages.every((message) => message.role !== "tool")); assert.ok(content.length < 1000); });