Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ ENV OMNIROUTE_USE_TURBOPACK=0
# Raise the V8 heap ceiling for the build. The webpack production optimization
# pass (forced above since Turbopack panics) needs more than V8's default ceiling
# (~2 GB) for a codebase this size; a memory-constrained Docker build otherwise
# dies with "FATAL ERROR: ... JavaScript heap out of memory" at `[builder] npm run
# build` (#4076). NODE_OPTIONS propagates to the spawned `next build` child
# dies with "FATAL ERROR: ... JavaScript heap out of memory" during the builder
# stage (#4076). NODE_OPTIONS propagates to the spawned `next build` child
# (build-next-isolated.mjs → resolveNextBuildEnv spreads process.env). Build-only;
# the runtime heap is set separately on the runner stage (OMNIROUTE_MEMORY_MB).
# Override for hosts with more/less RAM: `--build-arg OMNIROUTE_BUILD_MEMORY_MB=6144`.
Expand Down
3 changes: 2 additions & 1 deletion open-sse/executors/codex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,6 @@ const CODEX_HOSTED_TOOL_TYPES: ReadonlySet<string> = new Set([
"computer_use_preview",
"code_interpreter",
"mcp",
"local_shell",
]);

// #2980: a free-plan Codex account (workspacePlanType === "free", from the OAuth
Expand Down Expand Up @@ -549,6 +548,8 @@ export function normalizeCodexTools(
if (!rawName || !validToolNames.has(rawName)) {
delete body.tool_choice;
}
} else if (toolChoice.type === "local_shell") {
delete body.tool_choice;
}
}
}
Expand Down
19 changes: 13 additions & 6 deletions tests/unit/executor-codex.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
getCodexResetTime,
getCodexUpstreamModel,
isCodexResponsesWebSocketRequired,
normalizeCodexTools,
parseCodexQuotaHeaders,
} from "../../open-sse/executors/codex.ts";
import {
Expand Down Expand Up @@ -824,7 +825,10 @@ test("CodexExecutor.transformRequest passes GPT 5.4 Mini xhigh reasoning through

assert.equal(sanitized.model, "gpt-5.4-mini");
assert.deepEqual(reasoning, { effort: "xhigh", summary: "detailed" });
assert.deepEqual(sanitized.include, ["code_interpreter_call.outputs", "reasoning.encrypted_content"]);
assert.deepEqual(sanitized.include, [
"code_interpreter_call.outputs",
"reasoning.encrypted_content",
]);
assert.equal(sanitized.reasoning_effort, undefined);
});

Expand Down Expand Up @@ -1053,9 +1057,6 @@ test("CodexExecutor.execute skips identity headers for unsafe session ids", asyn
});

test("CodexExecutor.transformRequest preserves namespace MCP tools and hosted tool types", () => {
// Regression: PR #1581 đã vô tình xoá nhánh `namespace` + whitelist hosted tools
// trong normalizeCodexTools, khiến MCP tool group (vd. mcp__atlassian__) bị strip
// trước khi forward lên Codex Responses API. Test này khoá lại hành vi đúng.
const executor = new CodexExecutor();
const result = executor.transformRequest(
"gpt-5.4",
Expand All @@ -1076,6 +1077,7 @@ test("CodexExecutor.transformRequest preserves namespace MCP tools and hosted to
{ type: "image_generation", output_format: "png" },
{ type: "tool_search" },
{ type: "web_search" },
{ type: "local_shell" },
{ type: "unknown_hosted_tool" },
],
tool_choice: { type: "function", name: "jira_get_issue" },
Expand All @@ -1099,9 +1101,14 @@ test("CodexExecutor.transformRequest preserves namespace MCP tools and hosted to
assert.equal((namespaceTool as { name: string }).name, "mcp__atlassian__");
assert.equal(((namespaceTool as { tools: unknown[] }).tools ?? []).length, 2);

// tool_choice trỏ vào sub-tool của namespace phải được giữ nguyên (không bị xoá
// do tên nằm trong namespace.tools[*].name đã được đăng ký vào validToolNames).
assert.deepEqual(result.tool_choice, { type: "function", name: "jira_get_issue" });

const body = {
tools: [{ type: "function", name: "exec_command", parameters: { type: "object" } }],
tool_choice: { type: "local_shell" },
};
normalizeCodexTools(body);
assert.equal(body.tool_choice, undefined);
});

test("CodexExecutor.transformRequest preserves native Codex custom tools", () => {
Expand Down
Loading