Skip to content
Closed
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/fr/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ Le proxy traduit chaque requête Anthropic Messages API au format Codex Response
| Texte assistant | `output_text` |
| Assistant `tool_use` | `function_call` (`input` → JSON-stringifié `arguments`) |
| Utilisateur `tool_result` | `function_call_output` (`is_error` → préfixe `[tool error]`) |
| Relecture de `thinking` / `redacted_thinking` | Ignorée |
| Relecture de `thinking` / `redacted_thinking` | Éléments `reasoning` avec enveloppes `ocxr1` bornées pour les signatures et les contenus masqués |
| Outils fonctionnels | `{type: "function"}` (`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`, `none`→`none`, `any`→`required`, fonction nommée→`{type:"function",name}`, hébergée WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -516,7 +516,8 @@ Le proxy traduit chaque requête Anthropic Messages API au format Codex Response
| `response.created` | `message_start` + `ping` |
| Battement de coeur | `ping` |
| Deltas de texte | `content_block_start` → `content_block_delta` (texte) → `content_block_stop` |
| Résumé ou texte de raisonnement | Bloc `thinking` avec signature synthétique |
| Résumé ou texte de raisonnement | Bloc `thinking` avec la signature relue, ou une enveloppe de secours `ocxr1` bornée |
| Raisonnement expurgé | Blocs `redacted_thinking` relus depuis l'enveloppe de raisonnement |
| Trames d'appel de fonction | Bloc `tool_use` avec `input_json_delta` |
| Événement terminal | `message_delta` → `message_stop` |
| EOF avant la borne | style 502 `api_error` |
Expand Down
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ The proxy translates every Anthropic Messages API request into the Codex Respons
| Assistant text | `output_text` |
| Assistant `tool_use` | `function_call` (`input` → JSON-stringified `arguments`) |
| User `tool_result` | `function_call_output` (`is_error` → `[tool error]` prefix) |
| `thinking` / `redacted_thinking` replay | Dropped |
| `thinking` / `redacted_thinking` replay | `reasoning` items with bounded `ocxr1` envelopes for signatures and redacted payloads |
| Function tools | `{type: "function"}` (`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`, `none`→`none`, `any`→`required`, named function→`{type:"function",name}`, hosted WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -530,7 +530,8 @@ name.
| `response.created` | `message_start` + `ping` |
| Heartbeat | `ping` |
| Text deltas | `content_block_start` → `content_block_delta` (text) → `content_block_stop` |
| Reasoning summary/text | `thinking` block with synthetic signature |
| Reasoning summary/text | `thinking` block with the replayed signature, or a bounded `ocxr1` fallback envelope |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
| Redacted reasoning | `redacted_thinking` blocks replayed from the reasoning envelope |
| Function-call frames | `tool_use` block with `input_json_delta` |
| Terminal event | `message_delta` → `message_stop` |
| EOF before terminal | 502-style `api_error` |
Expand Down
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/ja/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ Claude Code の `/effort` 設定はアダプターでも維持されます。
| Assistant テキスト | `output_text` |
| Assistant `tool_use` | `function_call`(`input` → JSON 文字列に変換した `arguments`) |
| ユーザー `tool_result` | `function_call_output`(`is_error` → `[tool error]` 接頭辞) |
| `thinking` / `redacted_thinking` 再生 | 破棄 |
| `thinking` / `redacted_thinking` 再生 | シグネチャと秘匿ペイロードを境界付き `ocxr1` エンベロープに保持した `reasoning` 項目 |
| Function ツール | `{type: "function"}`(`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`、`none`→`none`、`any`→`required`、名前指定関数→`{type:"function",name}`、ホスト型 WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -384,7 +384,8 @@ role、`tool_use_id` のない `tool_result`、id/name のない `tool_use`、na
| `response.created` | `message_start` + `ping` |
| Heartbeat | `ping` |
| テキスト delta | `content_block_start` → `content_block_delta`(text) → `content_block_stop` |
| 推論要約/テキスト | 合成シグネチャ付きの `thinking` ブロック |
| 推論要約/テキスト | 再生されたシグネチャ、または境界付き `ocxr1` フォールバックを持つ `thinking` ブロック |
| 秘匿化された推論 | 推論エンベロープから再生される `redacted_thinking` ブロック |
| Function-call フレーム | `input_json_delta` を持つ `tool_use` ブロック |
| 終了イベント | `message_delta` → `message_stop` |
| 終了前に EOF | 502 形式 `api_error` |
Expand Down
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/ko/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ Claude Code의 `/effort` 설정은 어댑터에서도 유지돼요.
| Assistant 텍스트 | `output_text` |
| Assistant `tool_use` | `function_call`(`input` → JSON 문자열로 변환한 `arguments`) |
| 사용자 `tool_result` | `function_call_output`(`is_error` → `[tool error]` 접두사) |
| `thinking` / `redacted_thinking` 재생 | 버려요 |
| `thinking` / `redacted_thinking` 재생 | 서명과 비공개 페이로드를 제한된 `ocxr1` 봉투에 담은 `reasoning` 항목 |
| Function 도구 | `{type: "function"}`(`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`, `none`→`none`, `any`→`required`, 이름 지정 함수→`{type:"function",name}`, 호스팅 WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -422,7 +422,8 @@ role, `tool_use_id` 없는 `tool_result`, id/name 없는 `tool_use`, name 없는
| `response.created` | `message_start` + `ping` |
| Heartbeat | `ping` |
| 텍스트 delta | `content_block_start` → `content_block_delta`(text) → `content_block_stop` |
| 추론 요약/텍스트 | 합성 signature가 있는 `thinking` 블록 |
| 추론 요약/텍스트 | 재생된 서명 또는 제한된 `ocxr1` 폴백이 있는 `thinking` 블록 |
| 비공개 추론 | 추론 봉투에서 재생되는 `redacted_thinking` 블록 |
| Function-call 프레임 | `input_json_delta`가 있는 `tool_use` 블록 |
| 종료 이벤트 | `message_delta` → `message_stop` |
| 종료 전에 EOF | 502 형식 `api_error` |
Expand Down
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/ru/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ Claude Code — это лишь учётные данные для доступ
| Текст ассистента | `output_text` |
| `tool_use` ассистента | `function_call` (`input` → `arguments` в виде JSON-строки) |
| `tool_result` пользователя | `function_call_output` (`is_error` → префикс `[tool error]`) |
| Повтор `thinking` / `redacted_thinking` | Отбрасывается |
| Повтор `thinking` / `redacted_thinking` | Элементы `reasoning` с ограниченными конвертами `ocxr1` для подписей и скрытых данных |
| Function-инструменты | `{type: "function"}` (`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`, `none`→`none`, `any`→`required`, именованная функция→`{type:"function",name}`, размещённый WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -410,7 +410,8 @@ id/name; именованный `tool_choice` без имени.
| `response.created` | `message_start` + `ping` |
| Heartbeat | `ping` |
| Текстовые дельты | `content_block_start` → `content_block_delta` (text) → `content_block_stop` |
| Резюме/текст рассуждений | Блок `thinking` с синтетической подписью |
| Резюме/текст рассуждений | Блок `thinking` с повторно переданной подписью или ограниченным резервным конвертом `ocxr1` |
| Скрытое рассуждение | Блоки `redacted_thinking`, воспроизведённые из конверта рассуждений |
| Кадры function-call | Блок `tool_use` с `input_json_delta` |
| Завершающее событие | `message_delta` → `message_stop` |
| EOF до завершающего события | `api_error` в стиле 502 |
Expand Down
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/tr/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ dönüştürür:
| Asistan metni | `output_text` |
| Asistan `tool_use` | `function_call` (`input` → JSON dizgeleştirilmiş `arguments`) |
| Kullanıcı `tool_result` | `function_call_output` (`is_error` → `[tool error]` öneki) |
| `thinking` / `redacted_thinking` tekrarı | Bırakılır |
| `thinking` / `redacted_thinking` tekrarı | İmzaları ve gizli yükleri sınırlı `ocxr1` zarflarında taşıyan `reasoning` öğeleri |
| Fonksiyon araçları | `{type: "function"}` (`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`, `none`→`none`, `any`→`required`, adlandırılmış fonksiyon→`{type:"function",name}`, barındırılan WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -599,7 +599,8 @@ kimlik/ad içermeyen `tool_use`; ad içermeyen adlandırılmış `tool_choice`.
| `response.created` | `message_start` + `ping` |
| Kalp atışı (Heartbeat) | `ping` |
| Metin farkları | `content_block_start` → `content_block_delta` (metin) → `content_block_stop` |
| Akıl yürütme özeti/metni | Sentetik imzalı `thinking` bloğu |
| Akıl yürütme özeti/metni | Tekrarlanan imzayı veya sınırlı bir `ocxr1` yedeğini taşıyan `thinking` bloğu |
| Gizli akıl yürütme | Akıl yürütme zarfından yeniden oynatılan `redacted_thinking` blokları |
| Fonksiyon çağrısı çerçeveleri | `input_json_delta` ile `tool_use` bloğu |
| Terminal olayı | `message_delta` → `message_stop` |
| Terminalden önce EOF | 502 tarzı `api_error` |
Expand Down
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/zh-cn/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ Claude Code 的 `/effort` 设置会完整保留并传递给适配器:
| Assistant 文本 | `output_text` |
| Assistant `tool_use` | `function_call`(`input` → JSON 字符串化的 `arguments`) |
| 用户 `tool_result` | `function_call_output`(`is_error` → `[tool error]` 前缀) |
| 重放 `thinking` / `redacted_thinking` | 丢弃 |
| 重放 `thinking` / `redacted_thinking` | `reasoning` 项;签名和脱敏载荷保存在有界 `ocxr1` 信封中 |
| Function 工具 | `{type: "function"}`(`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`,`none`→`none`,`any`→`required`,指定函数→`{type:"function",name}`,托管 WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -361,7 +361,8 @@ role;`tool_result` 缺少 `tool_use_id`;`tool_use` 缺少 id/name;指定
| `response.created` | `message_start` + `ping` |
| 心跳 | `ping` |
| 文本增量 | `content_block_start` → `content_block_delta`(文本)→ `content_block_stop` |
| 推理摘要/文本 | 带合成签名的 `thinking` 块 |
| 推理摘要/文本 | 带重放签名或有界 `ocxr1` 回退信封的 `thinking` 块 |
| 脱敏推理 | 从推理信封重放的 `redacted_thinking` 块 |
| Function-call 帧 | 带 `input_json_delta` 的 `tool_use` 块 |
| 终止事件 | `message_delta` → `message_stop` |
| 在终止事件前 EOF | 502 风格的 `api_error` |
Expand Down
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/zh-tw/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ Claude Code 的 `/effort` 設定會完整保留並傳遞給適配器:
| Assistant 文字 | `output_text` |
| Assistant `tool_use` | `function_call`(`input` → JSON 字串化的 `arguments`) |
| 使用者 `tool_result` | `function_call_output`(`is_error` → `[tool error]` 字首) |
| 重放 `thinking` / `redacted_thinking` | 丟棄 |
| 重放 `thinking` / `redacted_thinking` | `reasoning` 項目;簽名與遮蔽載荷保存在有界 `ocxr1` 信封中 |
| Function 工具 | `{type: "function"}`(`web_search*` → `{type: "web_search"}`) |
| `tool_choice` | `auto`→`auto`,`none`→`none`,`any`→`required`,指定名稱 function→`{type:"function",name}`,hosted WebSearch/web_search→`{type:"web_search"}` |
| `max_tokens` | `max_output_tokens` |
Expand All @@ -437,7 +437,8 @@ role;`tool_result` 缺少 `tool_use_id`;`tool_use` 缺少 id/name;指定
| `response.created` | `message_start` + `ping` |
| 心跳 | `ping` |
| 文字增量 | `content_block_start` → `content_block_delta`(文字)→ `content_block_stop` |
| 推理摘要/文字 | 帶合成簽名的 `thinking` 塊 |
| 推理摘要/文字 | 帶重播簽名或有界 `ocxr1` 備援信封的 `thinking` 塊 |
| 遮蔽推理 | 從推理信封重播的 `redacted_thinking` 塊 |
| Function-call 幀 | 帶 `input_json_delta` 的 `tool_use` 塊 |
| 終止事件 | `message_delta` → `message_stop` |
| 在終止事件前 EOF | 502 風格的 `api_error` |
Expand Down
2 changes: 2 additions & 0 deletions scripts/test-layout/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@
"claude-outbound.test.ts": "claude-integration",
"claude-shell-hook.test.ts": "claude-integration",
"claude-sidecar-override.test.ts": "claude-integration",
"claude-source-envelope.test.ts": "claude-integration",
"claude-system-env-auto.test.ts": "claude-integration",
"cleanup-orphaned-workflows.test.ts": "ci-workflows",
"clearable-deadline.test.ts": "lib",
Expand Down Expand Up @@ -999,6 +1000,7 @@
"rate-limit-reset-credits.test.ts": "gui",
"rate-limit-retry.test.ts": "providers",
"reasoning-effort.test.ts": "codex-integration",
"reasoning-envelope.test.ts": "responses",
"reasoning-replay-identity.test.ts": "adapters",
"reasoning-replay-robustness.test.ts": "adapters",
"reasoning-replay-scope-source.test.ts": "lib",
Expand Down
28 changes: 23 additions & 5 deletions src/claude/inbound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* Design (devlog/260711_claude_inbound/010, 003_evidence.md):
* - translate-and-replay: the produced body MUST pass the real responsesRequestSchema
* parse so routing/OAuth/pool/failover are inherited unchanged.
* - thinking/redacted_thinking blocks on replay are DROPPED (v1 policy) — routed
* providers carry reasoning in Responses items/ocxr1 envelopes instead.
* - thinking/redacted_thinking replay is preserved in Responses reasoning items;
* signatures and redacted payloads travel in bounded ocxr1 envelopes.
* - thinking.budget_tokens is NEVER forwarded raw; it maps to an effort tier.
* - top_k is accepted and silently dropped (no Responses equivalent, CCR parity).
*/
Expand All @@ -17,6 +17,7 @@ export { resolveInboundModel, effortForThinkingBudget, effortFromOutputConfig, e
import { AnthropicRequestError, isRec, type Rec } from "./inbound-records";
import { resolveInboundModel, effortForThinkingBudget, effortFromOutputConfig, formatFromOutputConfig } from "./inbound-model-options";
import { systemToInstructions, toolsToResponses, toolChoiceToResponses } from "./inbound-content-options";
import { decodeReasoningEnvelope, encodeReasoningEnvelope, OCX_REASONING_PREFIX } from "../responses/reasoning-envelope";



Expand Down Expand Up @@ -234,9 +235,26 @@ function assistantMessageToItems(content: unknown, input: Rec[]): void {
input.push({ type: "function_call", call_id: raw.id, name: raw.name, arguments: JSON.stringify(raw.input ?? {}) });
break;
}
case "thinking":
case "redacted_thinking":
break; // v1 policy: dropped on replay (003 evidence — safe for routed providers)
case "thinking": {
flush();
const thinking = typeof raw.thinking === "string" ? raw.thinking : "";
const signature = typeof raw.signature === "string" ? raw.signature : "";
if (signature.startsWith(OCX_REASONING_PREFIX)) {
const owned = decodeReasoningEnvelope(signature);
if (!owned) throw new AnthropicRequestError("malformed ocxr1 reasoning signature");
if (Object.hasOwn(owned, "sig")) throw new AnthropicRequestError("OpenCodex reasoning continuity cannot be replayed as an Anthropic signature");
}
const encrypted = signature.length === 0 ? undefined : signature.startsWith(OCX_REASONING_PREFIX) ? signature : encodeReasoningEnvelope({ sig: signature });
if (thinking.length === 0 && !encrypted) break;
input.push({ type: "reasoning", id: `rs_${crypto.randomUUID().replace(/-/g, "")}`, summary: thinking.length > 0 ? [{ type: "summary_text", text: thinking }] : [], ...(encrypted ? { encrypted_content: encrypted } : {}) });
break;
}
case "redacted_thinking": {
flush();
const data = typeof raw.data === "string" ? raw.data : "";
if (data.length > 0) input.push({ type: "reasoning", id: `rs_${crypto.randomUUID().replace(/-/g, "")}`, summary: [], encrypted_content: encodeReasoningEnvelope({ red: [data] }) });
break;
}
default:
break;
}
Expand Down
Loading
Loading