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
16 changes: 11 additions & 5 deletions src/providers/proxies/codex-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,21 @@ export const transformCodexBodyJson = (
...nextBody
} = bodyJson;

// OpenCode injects instructions internally in its Codex/OAuth path:
// https://github.com/anomalyco/opencode/blob/d848c9b6a32f408e8b9bf6448b83af05629454d0/packages/opencode/src/session/llm.ts#L110-L112
// Non-Codex clients won't, so we fall back to OpenCode's default instructions for Codex.
// https://github.com/anomalyco/opencode/blob/d848c9b6a32f408e8b9bf6448b83af05629454d0/packages/opencode/src/session/prompt/codex_header.txt
const incomingInstructions = trimString(nextBody.instructions);
const input = Array.isArray(nextBody.input) ? nextBody.input : [];
const firstInput = input[0];
const promotedInstructions =
!incomingInstructions &&
isObjectRecord(firstInput) &&
(firstInput.role === "system" || firstInput.role === "developer")
? trimString(firstInput.content)
: "";
const instructions =
trimString(nextBody.instructions) || CODEX_DEFAULT_INSTRUCTIONS;
incomingInstructions || promotedInstructions || CODEX_DEFAULT_INSTRUCTIONS;

return {
...nextBody,
...(promotedInstructions ? { input: input.slice(1) } : {}),
instructions,
store: false,
...(sessionId ? { prompt_cache_key: sessionId } : {}),
Expand Down
33 changes: 33 additions & 0 deletions tests/providers/proxy-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,39 @@ describe("proxy contract: codex", () => {
);
});

test("promotes OpenCode developer input instead of adding fallback instructions", () => {
const headers = new Headers();
const bodyJson = {
model: "gpt-5.6-sol",
input: [
{
role: "developer",
content: "Current OpenCode GPT instructions",
},
{
role: "user",
content: [{ type: "input_text", text: "hello" }],
},
],
};

const result = prepareCodexProxyRequest({
headers,
accessToken: "codex-access",
accountId: "acct-fallback",
metadata: null,
bodyText: JSON.stringify(bodyJson),
bodyJson,
});

expect(JSON.parse(result.bodyText)).toEqual({
model: "gpt-5.6-sol",
input: [bodyJson.input[1]],
instructions: "Current OpenCode GPT instructions",
store: false,
});
});

test("uses derived session headers and prompt cache key for codex requests", () => {
const headers = new Headers({
session_id: "raw-session-underscore",
Expand Down