From 68e5797e48a0bdcbca0d94e07e5e80549194752c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 9 May 2026 13:34:12 +0200 Subject: [PATCH] fix(ai): Codex backend request body matches OpenAI Responses schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After v1.4.9 the OAuth connect went green, but every real insight call still failed with: Codex request failed (400): { "detail": "Input must be a list" } The `chatgpt.com/backend-api/codex/responses` endpoint speaks the OpenAI Responses API shape (`ResponsesApiRequest` in `codex-rs/codex-api/src/common.rs`), where `input` is a list of typed message items rather than a single string. CodexClient was sending the older Chat-Completions-style body (`input: `) which the upstream rejects with the 400 above. The body now mirrors the canonical shape: { "model": "gpt-5.3-codex", "instructions": "", "input": [ { "type": "message", "role": "user", "content": [{ "type": "input_text", "text": "" }] } ], "tools": [], "tool_choice": "auto", "parallel_tool_calls": false, "store": false, "stream": false } The response shape (Output `ResponseItem[]` with `output_text` content) is unchanged, so `parseResponse` still works without modification. Both Settings → KI "Verbindung testen" and the insight generator now complete end-to-end through the ChatGPT subscription. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 17 +++++++++++++++++ package.json | 2 +- src/lib/ai/codex-client.ts | 16 +++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c47c0643..045f96d8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.4.10] — 2026-05-09 + +### Fixed — KI Insights via ChatGPT + +- **Codex-Backend bekommt jetzt das richtige Request-Format.** Nach + dem v1.4.9-Connect war der OAuth durch, aber jeder echte Insight- + Call ist mit `Codex request failed (400) — "Input must be a list"` + gestorben. Der `chatgpt.com/backend-api/codex/responses`-Endpoint + spricht das OpenAI-Responses-API-Schema (`input: ResponseItem[]`) + und nicht das Chat-Completions-Schema mit String-Input. v1.4.10 + baut den Body korrekt — `input` ist eine Liste mit einem + Message-Item, das wiederum eine Liste von `input_text`-Content- + Blöcken trägt — exakt wie die `ResponsesApiRequest`-Struktur im + offiziellen `codex-rs/codex-api/src/common.rs`. Settings → KI + "Verbindung testen" und der Insight-Generator laufen damit jetzt + beide gegen dein ChatGPT-Abo durch. + ## [1.4.9] — 2026-05-09 ### Fixed — Settings · KI diff --git a/package.json b/package.json index ea1037162..93f641fea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "healthlog", - "version": "1.4.9", + "version": "1.4.10", "private": true, "packageManager": "pnpm@10.31.0", "scripts": { diff --git a/src/lib/ai/codex-client.ts b/src/lib/ai/codex-client.ts index eabb7327d..3311759fb 100644 --- a/src/lib/ai/codex-client.ts +++ b/src/lib/ai/codex-client.ts @@ -69,6 +69,10 @@ export class CodexClient implements AIProvider { } private async doRequest(params: CompletionParams): Promise { + // The chatgpt.com/backend-api/codex/responses endpoint expects the + // OpenAI Responses API shape: `input` is an array of typed message + // items, NOT a raw string. The Codex CLI's `ResponsesApiRequest` + // (`codex-rs/codex-api/src/common.rs`) is the canonical definition. return fetch(CODEX_ENDPOINT, { method: "POST", headers: { @@ -78,7 +82,17 @@ export class CodexClient implements AIProvider { body: JSON.stringify({ model: CODEX_MODEL, instructions: params.systemPrompt, - input: params.userPrompt, + input: [ + { + type: "message", + role: "user", + content: [{ type: "input_text", text: params.userPrompt }], + }, + ], + tools: [], + tool_choice: "auto", + parallel_tool_calls: false, + store: false, stream: false, }), });