diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 42b5f6da5..e842a6d8c 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -4,6 +4,8 @@ ### Fixed +- Fixed OpenAI Codex OAuth reasoning effort mapping for `gpt-5.5` by clamping unsupported `minimal` requests to `low`, matching other GPT-5.2+ Codex models. + - Fixed CI type-check failures from test files referencing model IDs no longer returned by upstream `/models` endpoints. `models.generated.ts` is regenerated each CI run, so tests hardcoding stale IDs (`gpt-4o` on github-copilot, `qwen-3-235b-a22b-instruct-2507` on cerebras, `google/gemini-2.0-flash-001` on openrouter) failed `getModel`'s typed lookup. Swapped to currently-served siblings (`gpt-4.1`, `llama3.1-8b`, `google/gemini-2.5-flash`). - Fixed Anthropic adaptive-thinking rejection on `claude-opus-4-7` (and the `opus-4-6` family more generally): the request builder now consults a per-(provider, model) capability table and emits the adaptive `thinking.type=adaptive` + `output_config.effort` shape for any model that requires it, instead of the legacy `thinking.type=enabled` + `budget_tokens` shape ([#11](https://github.com/JuliusBrussee/caveman-code/issues/11)) - Fixed Anthropic 1M context tier not being opted into for `claude-opus-4-5` on the direct Anthropic API and Bedrock: the provider now sends `anthropic-beta: context-1m-2025-08-07` for that family and the model registry overrides its `contextWindow` to 1_000_000 so the modeline / picker / compaction logic see the real ceiling. The opt-in is provider-scoped: the GitHub Copilot Anthropic relay rejects this beta header and exposes 1M-context Claude models as separate model ids instead, so the beta is not sent on Copilot. Discovery of those Copilot-only model ids is out of scope for this PR; a follow-up runtime-discovery layer will surface them ([#12](https://github.com/JuliusBrussee/caveman-code/issues/12)) diff --git a/packages/ai/src/providers/openai-codex-responses.ts b/packages/ai/src/providers/openai-codex-responses.ts index a544e3d49..1a81910a0 100644 --- a/packages/ai/src/providers/openai-codex-responses.ts +++ b/packages/ai/src/providers/openai-codex-responses.ts @@ -335,7 +335,10 @@ function buildRequestBody( function clampReasoningEffort(modelId: string, effort: string): string { const id = modelId.includes("/") ? modelId.split("/").pop()! : modelId; - if ((id.startsWith("gpt-5.2") || id.startsWith("gpt-5.3") || id.startsWith("gpt-5.4")) && effort === "minimal") + if ( + (id.startsWith("gpt-5.2") || id.startsWith("gpt-5.3") || id.startsWith("gpt-5.4") || id.startsWith("gpt-5.5")) && + effort === "minimal" + ) return "low"; if (id === "gpt-5.1" && effort === "xhigh") return "high"; if (id === "gpt-5.1-codex-mini") return effort === "high" || effort === "xhigh" ? "high" : "medium"; diff --git a/packages/ai/test/openai-codex-stream.test.ts b/packages/ai/test/openai-codex-stream.test.ts index d3db8c298..340c19701 100644 --- a/packages/ai/test/openai-codex-stream.test.ts +++ b/packages/ai/test/openai-codex-stream.test.ts @@ -404,7 +404,7 @@ describe("openai-codex streaming", () => { await streamResult.result(); }); - it.each(["gpt-5.3-codex", "gpt-5.4"])("clamps %s minimal reasoning effort to low", async (modelId) => { + it.each(["gpt-5.3-codex", "gpt-5.4", "gpt-5.5"])("clamps %s minimal reasoning effort to low", async (modelId) => { const tempDir = mkdtempSync(join(tmpdir(), "pi-codex-stream-")); process.env.PI_CODING_AGENT_DIR = tempDir;