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: 4 additions & 0 deletions docs-site/src/content/docs/fr/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ Trois états de configuration :
La valeur de compactage est réglable dans **Connexion → Claude**. **Avertissement :** une valeur supérieure à la fenêtre réelle d'un modèle
rend ce modèle inutilisable : les tours échouent avant que le résumé puisse se déclencher.

La normalisation des erreurs de dépassement de contexte utilise uniquement les 65 536 premières unités de code UTF-16 du message du fournisseur.
Les diagnostics ou nombres de jetons situés après cette limite peuvent disparaître sans marqueur de troncature.
Consultez le [guide anglais](/guides/claude-code/#auto-context-big-context-models-without-the-200k-ceiling) pour les limites exactes et les conditions de reprise des nombres de jetons.

Les modèles Anthropic natifs dont le contexte est inférieur à 1M ne sont jamais marqués automatiquement. Une fenêtre de compactage que vous exportez vous-même
reste prioritaire pour le marquage des variables de lancement ; le proxy s'appuie sur votre valeur pour déterminer les modèles qui peuvent recevoir le marqueur sans risque.
Les lignes de découverte ignorent cet export et conservent le plancher fixe.
Expand Down
23 changes: 19 additions & 4 deletions docs-site/src/content/docs/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,11 +675,26 @@ window breaks that model — the chat errors out before the summary can fire.
A model's advertised context window does not guarantee that a tool-heavy request fits the
upstream input limit. A classified input-limit rejection reaches Claude Code as
`invalid_request_error` with `context_length_exceeded`, worded the way Anthropic words it
(`prompt is too long: …`, with token counts when the provider states them), so Claude Code
(`prompt is too long: …`), so Claude Code
compacts the conversation and retries on its own; a non-streaming response uses HTTP 400 instead
of a retryable 502. Providers on the native Messages lane get the same wording. A throughput
limit that only mentions tokens (for example "too many tokens per minute") keeps its text and is
not treated as an overflow. If compaction itself still exceeds the limit, preserve the original
of a retryable 502. Providers on the native Messages lane get the same wording.

Overflow normalization uses only the first **65,536 UTF-16 code units** of the provider's error
message, including messages that already use Anthropic's wording. This is a string-length limit,
not a byte or token limit. Text beyond it is discarded without an ellipsis or truncation marker,
so diagnostic details and token counts near the end may be absent from the error Claude Code
receives. The added `prompt is too long:` prefix, followed by a space, can make the final message
longer than this retained portion.

Within that portion, recognized Anthropic wording is kept; otherwise OpenCodex emits
`prompt is too long: <requested> tokens > <limit> maximum` only when it finds
`maximum context length is <limit> tokens` followed by `resulted in <requested> tokens` or
`you requested <requested> tokens`. It uses the first stated limit and the first matching request
count after it. If that pair is missing, reversed, or cut off, it prefixes the retained text with
`prompt is too long:` followed by a space, without inventing counts. A throughput limit that only mentions tokens
(for example "too many tokens per minute") keeps its text and is not treated as an overflow.

If compaction itself still exceeds the limit, preserve the original
history and try compacting a fork with fewer enabled tool or MCP schemas, if your client supports
that workflow. A `[1m]` marker or larger client accounting setting does not raise the upstream
limit, and OpenCodex does not silently remove history or tools to make it fit.
Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/ja/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ Claude Code は未知モデルのコンテキストを 200k トークンとし
**接続 → Claude** で圧縮値を調整できます。**警告:** モデルの実際のコンテキストウィンドウより大きく上げると
要約を開始する前にチャットエラーが発生します。

コンテキスト超過エラーの正規化では、プロバイダーのエラーメッセージの先頭 65,536 UTF-16 コード単位だけを使います。
末尾の診断情報やトークン数は、省略を示す印なしで失われることがあります。
詳しい制限とトークン数の扱いは[英語ガイド](/guides/claude-code/#auto-context-big-context-models-without-the-200k-ceiling)を参照してください。

1M 未満のネイティブ Anthropic モデルには自動で標識を付けません。自分で export した圧縮値は起動スロットの標識に優先し、プロキシは**ユーザーが指定した**値を基準にどのモデルに安全に標識を付けるか決定します。ディスカバリー行はその export を無視し、固定の下限を保ちます。
直接編集した設定値が不正な場合は 829,800 に戻ります。

Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/ko/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,10 @@ Claude Code는 알 수 없는 모델의 컨텍스트를 200k 토큰으로 계산
**연결 → Claude**에서 압축 값을 조절할 수 있어요. **경고:** 모델의 실제 컨텍스트 창보다 크게 올리면
요약을 시작하기 전에 채팅 오류가 발생해요.

컨텍스트 초과 오류를 정규화할 때는 제공자 오류 메시지의 첫 65,536 UTF-16 코드 단위만 사용해요.
뒤쪽 진단 내용이나 토큰 수는 별도 잘림 표시 없이 빠질 수 있어요.
자세한 제한과 토큰 수 처리 조건은 [영문 가이드](/guides/claude-code/#auto-context-big-context-models-without-the-200k-ceiling)를 참고하세요.

1M 미만인 네이티브 Anthropic 모델에는 자동으로 표식을 붙이지 않아요. 직접 내보낸 압축 값은 실행 슬롯 표식에서 항상
우선하며, 프록시는 **사용자가 지정한** 값을 기준으로 어떤 모델에 안전하게 표식을 붙일지 결정해요.
디스커버리 행은 그 값을 무시하고 고정 하한을 유지해요.
Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/ru/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@ Anthropic сохраняют канонические id в обоих инте
реального окна модели, эта модель ломается — чат завершится ошибкой раньше, чем успеет сработать
резюмирование.

При нормализации ошибок переполнения контекста используются только первые 65 536 единиц кода UTF-16 сообщения провайдера.
Диагностические сведения и числа токенов за этой границей могут исчезнуть без отметки об усечении.
Точные ограничения и условия переноса чисел токенов описаны в [английском руководстве](/guides/claude-code/#auto-context-big-context-models-without-the-200k-ceiling).

Нативные модели Anthropic с окном меньше 1M никогда не помечаются автоматически. Экспортированное
вами окно сжатия имеет приоритет при пометке слотов запуска (прокси использует ВАШЕ значение, чтобы решить, какие модели
можно безопасно пометить). Строки обнаружения игнорируют этот экспорт и сохраняют фиксированный пол. Некорректные значения, внесённые в конфигурацию вручную, откатываются
Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/tr/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,10 @@ Sıkıştırma değeri Claude sayfasında ayarlanabilir. **Uyarı:** bir modelin
penceresinin üzerine çıkarmak o modeli bozar — sohbet özetleme tetiklenmeden
önce hata verir.

Bağlam taşması hataları normalleştirilirken sağlayıcının hata mesajının yalnızca ilk 65.536 UTF-16 kod birimi kullanılır.
Bu sınırdan sonraki tanılama ayrıntıları veya token sayıları, kesilme işareti eklenmeden kaybolabilir.
Kesin sınırlar ve token sayılarının aktarılma koşulları için [İngilizce kılavuza](/guides/claude-code/#auto-context-big-context-models-without-the-200k-ceiling) bakın.

1M altı yerel Anthropic modelleri hiçbir zaman otomatik olarak işaretlenmez.
Kendi dışa aktardığınız sıkıştırma penceresi, başlatma yuvası işaretlemesinde her zaman kazanır (proxy hangi modellerin
işaretlenmesinin güvenli olduğuna karar vermek için SİZİN değerinizi kullanır).
Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/zh-cn/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ v1 别名按字面解码(历史上 model ID 中包含的两字符序列 `~s` /
可以在 Claude 页面调整压缩值。**警告:**如果将其提高到超过模型的实际窗口,该模型将无法正常
工作——聊天会在触发摘要之前报错。

规范化上下文超限错误时,只使用提供方错误消息的前 65,536 个 UTF-16 代码单元。
后面的诊断信息或 token 数可能被丢弃,且不会添加截断标记。
详细限制和 token 数处理条件见[英文指南](/guides/claude-code/#auto-context-big-context-models-without-the-200k-ceiling)。

低于 1M 的原生 Anthropic 模型绝不会被自动标记。你自行导出的压缩值在启动槽位标记上始终优先(代理会使用**你的**
值来判断哪些模型可以安全标记)。发现列表忽略该导出值并保持固定下限。手动编辑配置时填入的无效值会回退到 829,800。

Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/zh-tw/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,10 @@ v1 別名按字面解碼(歷史上 model ID 中包含的兩字元序列 `~s` /
可以在 Claude 頁面調整壓縮值。**警告:**如果將其提高到超過模型的實際視窗,該模型將無法正常
工作——聊天會在觸發摘要之前報錯。

正規化上下文超限錯誤時,只使用提供方錯誤訊息的前 65,536 個 UTF-16 程式碼單元。
後面的診斷資訊或 token 數可能被捨棄,且不會新增截斷標記。
詳細限制和 token 數處理條件請參閱[英文指南](/guides/claude-code/#auto-context-big-context-models-without-the-200k-ceiling)。

低於 1M 的原生 Anthropic 模型絕不會被自動標記。你自行匯出的壓縮值在啟動槽位標記上始終優先(代理會使用**你的**
值來判斷哪些模型可以安全標記)。探索列表忽略該匯出值並保持固定下限。手動編輯設定時填入的無效值會回退到 829,800。

Expand Down
10 changes: 7 additions & 3 deletions src/claude/outbound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,16 @@ export function anthropicErrorType(status: number): string {
* (devlog/_plan/261009_claude_1m_default/010).
*/
const CLAUDE_PROMPT_TOO_LONG_RE = /prompt is too long|input is too long for requested model/i;
const STATED_CONTEXT_COUNTS_RE = /maximum context length is (\d+) tokens[\s\S]*?(?:resulted in|you requested) (\d+) tokens/i;
const MAX_OVERFLOW_MESSAGE_CHARS = 64 * 1024;
const STATED_CONTEXT_LIMIT_RE = /maximum context length is (\d+) tokens/i;
const STATED_REQUEST_COUNT_RE = /(?:resulted in|you requested) (\d+) tokens/i;

export function claudePromptTooLongMessage(message: string): string {
message = message.slice(0, MAX_OVERFLOW_MESSAGE_CHARS);
Comment thread
lidge-jun marked this conversation as resolved.
if (CLAUDE_PROMPT_TOO_LONG_RE.test(message)) return message;
const counts = STATED_CONTEXT_COUNTS_RE.exec(message);
if (counts) return `prompt is too long: ${counts[2]} tokens > ${counts[1]} maximum`;
const limit = STATED_CONTEXT_LIMIT_RE.exec(message);
const requested = limit && STATED_REQUEST_COUNT_RE.exec(message.slice(limit.index + limit[0].length));
if (limit && requested) return `prompt is too long: ${requested[1]} tokens > ${limit[1]} maximum`;
return `prompt is too long: ${message}`;
}

Expand Down
11 changes: 7 additions & 4 deletions src/server/responses/core-replay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,13 @@ export function bindRouteReasoningReplayScope(args: {
if (owner) parsed._nativeReasoningBoundOwner = owner;
else delete parsed._nativeReasoningBoundOwner;
if (parsed._nativeReasoningReplay?.size) {
const rejected = new Set<string>();
for (const [blob, tag] of parsed._nativeReasoningReplay) {
if (!nativeReasoningTagMatches(nativeReasoningTag(owner, blob), tag)) {
stripNativeReasoningBlob(parsed, blob);
rejected.add(blob);
}
}
if (rejected.size) stripNativeReasoningBlobs(parsed, rejected);
}
const continuationDestinationIdentity = providerContinuationDestinationIdentity(parsed, provider);
const continuationOwner = providerContinuationOwnerFromReplayIdentity(
Expand Down Expand Up @@ -169,11 +171,11 @@ export function bindRouteReasoningReplayScope(args: {
bindProviderContinuationForRoute(parsed, continuationOwner);
}

function stripNativeReasoningBlob(parsed: OcxParsedRequest, blob: string): void {
function stripNativeReasoningBlobs(parsed: OcxParsedRequest, rejected: ReadonlySet<string>): void {
const input = (parsed._rawBody as { input?: unknown } | undefined)?.input;
if (Array.isArray(input)) {
for (const item of input) {
if (item && typeof item === "object" && item.type === "reasoning" && item.encrypted_content === blob) {
if (item && typeof item === "object" && item.type === "reasoning" && rejected.has(item.encrypted_content)) {
delete item.encrypted_content;
delete item.id;
}
Expand All @@ -187,7 +189,8 @@ function stripNativeReasoningBlob(parsed: OcxParsedRequest, blob: string): void
const item: unknown = JSON.parse(part.signature);
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
const reasoning = item as Record<string, unknown>;
if (reasoning.type !== "reasoning" || reasoning.encrypted_content !== blob) continue;
if (reasoning.type !== "reasoning" || typeof reasoning.encrypted_content !== "string"
|| !rejected.has(reasoning.encrypted_content)) continue;
delete reasoning.encrypted_content;
delete reasoning.id;
part.signature = JSON.stringify(reasoning);
Expand Down
2 changes: 1 addition & 1 deletion structure/runtime.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Runtime

The minute sweep checks persisted activation deadlines locally; only missing deadlines trigger metadata discovery. See the [quota activation contract](providers/openai-tiers.md#public-provider-contract). Codex control-plane ids are defined in the dependency-free `src/codex/control-plane-models.ts`; `src/router.ts` routes these exact ids unchanged to canonical OpenAI, retaining the existing error when no OpenAI provider is enabled. They do not widen the public native roster. Catalog requests and scheduled source refreshes follow the [nonblocking catalog observation contract](catalog.md#shared-catalog). Async runtime persistence rejects observed selection/epoch changes and returns detached frozen results; bounded exec rejects promptly and releases output readers on deadline or abort, independently awaits actual child exit, and escalates SIGTERM to SIGKILL after the shared 2-second grace (Windows termination is forceful).
The minute sweep checks persisted activation deadlines locally; only missing deadlines trigger metadata discovery. See the [quota activation contract](providers/openai-tiers.md#public-provider-contract). Codex control-plane ids are defined in the dependency-free `src/codex/control-plane-models.ts`; `src/router.ts` routes these exact ids unchanged to canonical OpenAI, retaining the existing error when no OpenAI provider is enabled. They do not widen the public native roster. Catalog requests and scheduled source refreshes follow the [nonblocking catalog observation contract](catalog.md#shared-catalog). Async runtime persistence rejects observed selection/epoch changes and returns detached frozen results; bounded exec rejects promptly and releases output readers on deadline or abort, independently awaits actual child exit, and escalates SIGTERM to SIGKILL after the shared 2-second grace (Windows termination is forceful). Claude overflow normalization examines at most 64 Ki characters, extracts stated context/request counts in separate forward scans, retains the bounded rewritten prefix, and leaves other error classifications intact; the managed native Messages SSE route follows the same contract (`tests/claude-integration/claude-prompt-too-long.test.ts`).

## Bun runtime and test runner

Expand Down
2 changes: 1 addition & 1 deletion structure/transports/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ again held its entry for the life of the process.
A replayed compaction item carries an `encrypted_content` blob only its minting backend can decode, and the client replays it on every later turn. The proxy's own `ocx1:` envelopes are transparent base64, so they always lower to plain user messages. A
native blob is relayed only when there is no known serving-identity mismatch and the destination is known to decode native blobs — the canonical ChatGPT forward surface, the official OpenAI API, or a provider with the explicit
`decodesNativeCompactionBlobs` capability. The destination gate alone is insufficient because more than one backend, including OpenAI and xAI, mints native blobs: a destination can decode its own blob without being able to decode the previous backend's.
The same serving-identity mismatch signal therefore strips reasoning `encrypted_content` and degrades native compaction blobs through the existing opaque-note path. Claude-native reasoning adds a per-blob tag check at every route binding: only the
The same serving-identity mismatch signal therefore strips reasoning `encrypted_content` and degrades native compaction blobs through the existing opaque-note path. Claude-native reasoning batches rejected blob tags into one scrub pass: only the
matching durable endpoint and generation-bearing credential retain raw and parsed carriers. Without recorded thread identity, the destination gate remains. Noncanonical forward providers receive no caller credentials and may point at any backend. On any
other routed destination the blob also degrades to the same opaque note the bridged parser uses, because forwarding it there fails the turn and the item outlives the failure in the client transcript, repeating on every later turn including the compaction
turn the proxy itself drives. With `store: false`, request sanitization strips ids from every input item, including compact-wire items, matching codex-rs (`core/src/client.rs:918-925`). Compact-wire items remain exempt from response-side field backfill.
Expand Down
Loading
Loading