mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-21 22:32:22 +03:00
Fixes #12831. When the Codex upstream model produces string values in tool arguments that contain double-escaped tabs (\t inside the JSON string instead of \t), the parser outputs literal backslash-t characters. This breaks editor patches that rely on proper indentation. This commit adds a fixDoubleEscapedTabs sanitization step before parsing to restore them to single tabs. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
91 lines
2.4 KiB
TypeScript
91 lines
2.4 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { openaiToOpenAIResponsesResponse } from "../../open-sse/translator/response/openai-responses.ts";
|
|
|
|
test("Issue #12831: fixes double-escaped tabs in Codex JSON tool call arguments", () => {
|
|
const events = [];
|
|
const emit = (_name, payload) => events.push(payload);
|
|
const state = {
|
|
responseId: "res_123",
|
|
funcCallIds: {},
|
|
funcNames: {},
|
|
funcArgsBuf: {},
|
|
funcArgsDone: {},
|
|
funcItemAdded: {},
|
|
funcItemDone: {},
|
|
msgItemAdded: {},
|
|
msgContentAdded: {},
|
|
msgTextBuf: {},
|
|
msgItemDone: {},
|
|
};
|
|
|
|
const chunk1 = {
|
|
choices: [
|
|
{
|
|
index: 0,
|
|
delta: {
|
|
tool_calls: [
|
|
{
|
|
index: 0,
|
|
id: "call_123",
|
|
function: {
|
|
name: "_edit",
|
|
// gpt-5.6-luna-xhigh emits literally \ followed by t in the JSON string
|
|
// to represent a tab, instead of a JSON escape for tab or a raw tab.
|
|
// Wait, in JSON, a tab in a string is encoded as "\t" (two characters: \ and t).
|
|
// If it's double-escaped, it emits "\t" (four characters: \, \, t in JSON string? No, two backslashes and a t: "\t")
|
|
// Let's assume the string is: {"input": "some code\twith tabs"}
|
|
arguments: '{\n "input": "some code\\twith tabs"',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
const chunk2 = {
|
|
choices: [
|
|
{
|
|
index: 0,
|
|
delta: {
|
|
tool_calls: [
|
|
{
|
|
index: 0,
|
|
function: {
|
|
arguments: "\n}",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
finish_reason: "tool_calls",
|
|
},
|
|
],
|
|
};
|
|
|
|
const chunk3 = {
|
|
usage: { prompt_tokens: 10, completion_tokens: 10 },
|
|
};
|
|
|
|
function processChunk(chunk) {
|
|
const chunkEvents = openaiToOpenAIResponsesResponse(chunk, state);
|
|
for (const ev of chunkEvents) {
|
|
emit(ev.event, ev.data);
|
|
}
|
|
}
|
|
|
|
processChunk(chunk1);
|
|
processChunk(chunk2);
|
|
processChunk(chunk3);
|
|
|
|
const doneEvent = events.find((e) => e.type === "response.function_call_arguments.done");
|
|
|
|
// Try parsing the arguments
|
|
const parsed = JSON.parse(doneEvent.arguments);
|
|
assert.strictEqual(
|
|
parsed.input,
|
|
"some code\twith tabs",
|
|
"The double-escaped tab should be unescaped to a single tab character"
|
|
);
|
|
});
|