Skip to content
Draft
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
7 changes: 7 additions & 0 deletions docs-site/src/content/docs/fr/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,13 @@ URL de base modifiée ressemblant à l'original n'est jamais sondée. Les crédi
gratuits restants sont affichés sous forme de fenêtre en USD lorsque Command Code signale également les
dépenses de la période.

Lors de la connexion à OrcaRouter par navigateur (`ocx login orcarouter-oauth`), le corps d’une
réponse réussie à l’échange de clé doit être un JSON UTF-8 valide d’au plus 64 KiB. Le délai existant
de 30 secondes pour cette requête couvre les en-têtes et la réception complète du corps ; tout corps
trop volumineux ou mal formé est rejeté avant l’enregistrement de la clé. Ces limites concernent
uniquement l’échange de clé à la connexion, pas les données des requêtes d’inférence. La validation
de `scope` reste inchangée : son absence est autorisée, mais une valeur explicitement invalide est rejetée.

**Découverte SambaNova Cloud.** Le préréglage lit la liste publique `/v1/models` de SambaNova Cloud depuis
l'hôte API fixe, préserve les identifiants natifs du fournisseur et limite la découverte à 128 KiB et 128
lignes brutes. Le catalogue n'étant pas authentifié, le parcours de connexion de la CLI signale que la clé ne
Expand Down
7 changes: 7 additions & 0 deletions docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,13 @@ Both modes route to `https://api.orcarouter.ai/v1` and discover the public live
whether Codex offers image attachments. Because the catalog itself is public, manual key setup
reports validation as unknown instead of accepting that response as proof that the key works.

During OrcaRouter browser sign-in (`ocx login orcarouter-oauth`), a successful key-exchange
response body must be valid UTF-8 JSON no larger than 64 KiB. The request's existing 30-second
budget covers both the response headers and the full body; oversized or malformed bodies are
rejected before the key is saved. These limits apply only to the login key exchange, not inference
request payloads. Scope validation is unchanged: an omitted `scope` is allowed, while an explicitly
invalid `scope` is rejected.

For a one-origin self-hosted deployment, set the shared origin before the first PKCE login; the saved
inference URL is derived from the same origin:

Expand Down
7 changes: 7 additions & 0 deletions docs-site/src/content/docs/ja/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,13 @@ discovery エンドポイントから取得します。チャットリクエス

**Command Code の quota:** ダッシュボードと `ocx account refresh` は、正規ホスト `https://api.commandcode.ai` 上の `/alpha/billing/credits` ウィンドウ(5時間と週次)を照会します。OAuth プリセット (`command-code`) は保存済みアカウント bearer を使い、Provider-API キープリセット (`commandcode`) は設定済みの有効キーを使います。ユーザーが編集した類似ホストは照会しません。期間支出が返る場合は、残りの monthly / purchased / free credits を USD ウィンドウとして表示します。

OrcaRouter のブラウザーログイン(`ocx login orcarouter-oauth`)では、キー交換の成功応答本文は
64 KiB 以下の有効な UTF-8 JSON である必要があります。このキー交換リクエストの既存の
30 秒制限には、応答ヘッダーと本文全体の受信が含まれ、サイズ超過または不正な本文はキーの
保存前に拒否されます。この制限はログイン時のキー交換にのみ適用され、推論リクエストの
ペイロードを制限するものではありません。`scope` の検証規則は変わらず、省略は許可され、
明示された不正な値は拒否されます。

**SambaNova Cloud の discovery:** preset は固定 API ホスト上の SambaNova Cloud の公開 `/v1/models` 一覧を読み、
プロバイダー固有の ID を保持し、discovery を 128 KiB と raw 128 行に制限します。カタログは認証不要のため、
CLI の login flow は公開レスポンスをキーの有効性の証拠にせず、キーを検証不能として報告します。chat リクエストは
Expand Down
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/ko/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,12 @@ CLI 사용자는 `~/.commandcode/auth.json`의 로컬 CLI 자격 증명을 가

**Command Code 할당량:** 대시보드와 `ocx account refresh`는 정규 호스트 `https://api.commandcode.ai`에서 `/alpha/billing/credits` 창(5시간 및 주간)을 조회합니다. OAuth 프리셋(`command-code`)은 저장된 계정 bearer를 사용하고, Provider-API 키 프리셋(`commandcode`)은 현재 설정된 활성 키를 사용합니다. 사용자가 바꾼 유사 base URL은 조회하지 않습니다. Command Code가 기간 사용량을 함께 반환하면 남은 monthly / purchased / free credits가 USD 창으로 표시됩니다.

OrcaRouter 브라우저 로그인(`ocx login orcarouter-oauth`)의 키 교환 성공 응답 본문은 64 KiB 이하의
유효한 UTF-8 JSON이어야 합니다. 해당 키 교환 요청의 기존 30초 제한은 응답 헤더와 전체 본문 수신을
포함하며, 크기를 초과하거나 형식이 잘못된 본문은 키를 저장하기 전에 거부합니다. 이 제한은 로그인
키 교환에만 적용되며 추론 요청 본문의 제한이 아닙니다. `scope` 검사는 그대로 유지되어 생략은
허용하고 명시적으로 잘못된 값은 거부합니다.

**SambaNova Cloud 검색:** 프리셋은 고정 API 호스트의 SambaNova Cloud 공개 `/v1/models` 목록을 읽고, 프로바이더
네이티브 ID를 보존하며 discovery를 128 KiB와 raw 행 128개로 제한합니다. 카탈로그에는 인증이 필요하지 않으므로
CLI 로그인 흐름은 공개 응답을 키 유효성의 증거로 사용하지 않고 키를 검증할 수 없는 것으로 보고합니다. chat 요청은
Expand Down
7 changes: 7 additions & 0 deletions docs-site/src/content/docs/ru/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,13 @@ Service token Nscale создаётся в [Nscale Console](https://console.nsca

**Квота Command Code.** Дашборд и `ocx account refresh` опрашивают окна `/alpha/billing/credits` (5 часов и неделя) на каноническом хосте `https://api.commandcode.ai`. OAuth-пресет (`command-code`) использует сохранённый bearer аккаунта; пресет Provider-API ключа (`commandcode`) — активный настроенный ключ. Пользовательски изменённый похожий base URL не опрашивается. Если Command Code также сообщает расход за период, оставшиеся monthly / purchased / free credits показываются как USD-окно.

При входе в OrcaRouter через браузер (`ocx login orcarouter-oauth`) тело успешного ответа при обмене
кода на ключ должно быть корректным JSON в UTF-8 размером не более 64 KiB. Действующий 30-секундный
лимит этого запроса охватывает получение заголовков и всего тела ответа; слишком большое или
некорректное тело отклоняется до сохранения ключа. Эти ограничения относятся только к обмену кода
на ключ при входе, а не к содержимому запросов инференса. Проверка `scope` не меняется: отсутствие
поля допускается, а явно недопустимое значение отклоняется.

**Discovery для SambaNova Cloud.** Пресет читает общедоступный список SambaNova Cloud `/v1/models` на
фиксированном API-хосте, сохраняет нативные id провайдера и ограничивает discovery размером 128 KiB
и 128 исходными строками. Каталог не требует аутентификации, поэтому процедура входа CLI сообщает, что
Expand Down
7 changes: 7 additions & 0 deletions docs-site/src/content/docs/tr/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,13 @@ anahtarını kullanır. [Command Code Studio](https://commandcode.ai/studio/)

**Command Code kotası.** Pano ve `ocx account refresh`, kanonik `https://api.commandcode.ai` ana bilgisayarında `/alpha/billing/credits` pencerelerini (5 saat ve haftalık) sorgular. OAuth önayarı (`command-code`) kayıtlı hesap bearer'ını kullanır; Provider-API anahtar önayarı (`commandcode`) etkin yapılandırılmış anahtarı kullanır. Kullanıcının değiştirdiği benzer bir temel URL asla sorgulanmaz. Command Code dönem harcamasını da bildirirse kalan monthly / purchased / free credits USD penceresi olarak gösterilir.

OrcaRouter tarayıcı oturum açma akışında (`ocx login orcarouter-oauth`), anahtar değişimi isteğinin
başarılı yanıt gövdesi en fazla 64 KiB boyutunda geçerli UTF-8 JSON olmalıdır. Bu isteğin mevcut
30 saniyelik süresi, yanıt başlıkları ile gövdenin tamamının alınmasını kapsar; sınırı aşan veya bozuk
gövdeler anahtar kaydedilmeden önce reddedilir. Bu sınırlar yalnızca oturum açma sırasındaki anahtar
değişimine uygulanır, çıkarım isteği yüklerine uygulanmaz. `scope` doğrulaması değişmez: alanın
bulunmamasına izin verilir, açıkça geçersiz bir değer ise reddedilir.

**SambaNova Cloud keşfi.** Önayar, sabit API ana bilgisayarından SambaNova
Cloud'un genel `/v1/models` listesini okur, sağlayıcı yerel kimliklerini korur
ve keşfi 128 KiB ve 128 ham satırla sınırlar. Katalog kimlik doğrulamasız
Expand Down
5 changes: 5 additions & 0 deletions docs-site/src/content/docs/zh-cn/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ inference key 可从 [Vultr Console](https://my.vultr.com) 的订阅概览复制
由于模型目录本身是公开的,手填 key 时会诚实显示“无法验证”,不会把公开目录的 200 响应误当成
密钥有效证明。

OrcaRouter 浏览器登录(`ocx login orcarouter-oauth`)的密钥交换成功响应正文必须是不超过
64 KiB 的有效 UTF-8 JSON。该交换请求现有的 30 秒时限覆盖响应头和完整正文的接收;超大或
格式错误的正文会在保存密钥前被拒绝。这些限制仅适用于登录密钥交换,不是推理请求负载的
限制。`scope` 校验规则保持不变:允许省略,明确无效的值仍会被拒绝。

单域名自托管环境可在第一次 PKCE 登录前设置统一 origin;推理地址会从同一个 origin 派生:

```bash
Expand Down
5 changes: 5 additions & 0 deletions docs-site/src/content/docs/zh-tw/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ endpoint 取得。Chat request 使用設定的 Bearer key。可在

**Command Code 配額。** 儀表板與 `ocx account refresh` 會在正規主機 `https://api.commandcode.ai` 探測 `/alpha/billing/credits` 視窗(5 小時與每週)。OAuth preset (`command-code`) 使用已儲存的帳號 bearer;Provider-API key preset (`commandcode`) 使用目前設定的有效 key。使用者改寫過的仿冒 base URL 不會被探測。當 Command Code 同時回報週期消耗時,剩餘的 monthly / purchased / free credits 會顯示為 USD 視窗。

OrcaRouter 瀏覽器登入(`ocx login orcarouter-oauth`)的金鑰交換成功回應本文必須是不超過
64 KiB 的有效 UTF-8 JSON。此交換請求原有的 30 秒時限涵蓋回應標頭與完整本文的接收;過大或
格式錯誤的本文會在儲存金鑰前被拒絕。這些限制只適用於登入時的金鑰交換,不是推論請求酬載的
限制。`scope` 驗證規則維持不變:允許省略,明確無效的值仍會被拒絕。

**SambaNova Cloud 探索。** preset 從固定 API host 讀取 SambaNova Cloud 公開的 `/v1/models` 列表,保留
provider-native id,並把 discovery 限制在 128 KiB/128 個 raw row。因 catalog 不需要認證,CLI login
流程會把 key 回報為 unverifiable,而不會把公開 response 當成有效 key 的證明。Chat request 仍使用
Expand Down
6 changes: 4 additions & 2 deletions src/lib/bounded-body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,11 @@ export async function readBoundedResponseBytes(
options: BoundedBytesOptions,
): Promise<BoundedBytesResult> {
const signal = options.signal;
if (signal?.aborted) throw signal.reason;

const body = response.body;
if (signal?.aborted) {
if (body) cancelBodyWithoutWaiting(body, signal.reason);
throw signal.reason;
}
if (!body) return { bytes: new Uint8Array(0), oversized: false };

const reader = body.getReader();
Expand Down
17 changes: 15 additions & 2 deletions src/oauth/orcarouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { OAuthCallbackFlow, type OAuthCallbackFlowOptions } from "./callback-server";
import { generatePKCE } from "./pkce";
import type { OAuthController, OAuthCredentials } from "./types";
import { BOUNDED_BODY_MAX_BYTES, readBoundedResponseBytes } from "../lib/bounded-body";
Comment thread
luvs01 marked this conversation as resolved.

export const ORCAROUTER_DEFAULT_API_BASE_URL = "https://api.orcarouter.ai";
export const ORCAROUTER_DEFAULT_AUTH_BASE_URL = "https://www.orcarouter.ai";
Expand Down Expand Up @@ -147,6 +148,7 @@ export class OrcaRouterOAuthFlow extends OAuthCallbackFlow {

async exchangeToken(code: string, _state: string, _redirectUri: string): Promise<OAuthCredentials> {
if (!this.#verifier) throw new Error("OrcaRouter PKCE verifier was not initialized");
const signal = requestSignal(this.ctrl.signal);
let response: Response;
try {
response = await fetch(new URL("/api/v1/auth/keys", this.#authBaseUrl), {
Expand All @@ -158,7 +160,7 @@ export class OrcaRouterOAuthFlow extends OAuthCallbackFlow {
code_challenge_method: "S256",
}),
redirect: "error",
signal: requestSignal(this.ctrl.signal),
signal,
});
} catch (error) {
if (this.ctrl.signal?.aborted) {
Expand All @@ -171,9 +173,20 @@ export class OrcaRouterOAuthFlow extends OAuthCallbackFlow {
// never turn a code, verifier, or accidentally returned key into console output.
throw new Error(`OrcaRouter key exchange failed with HTTP ${response.status}`);
}
const { bytes, oversized } = await readBoundedResponseBytes(response, {
maxBytes: BOUNDED_BODY_MAX_BYTES,
signal,
}).catch(() => {
if (signal.aborted) throw signal.reason;
// Preserve the existing non-reflective error for response-body failures.
throw new Error("OrcaRouter key exchange returned invalid JSON");
});
if (oversized) {
throw new Error(`OrcaRouter key exchange response exceeded the ${BOUNDED_BODY_MAX_BYTES}-byte limit`);
}
let payload: unknown;
try {
payload = await response.json();
payload = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
} catch {
throw new Error("OrcaRouter key exchange returned invalid JSON");
}
Expand Down
5 changes: 5 additions & 0 deletions structure/clients/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ third-party client's existing config without taking ownership of the rest of tha
promise is reversibility: apply snapshots first, writes atomically, records exactly what it owns,
and refuses refresh, disable, or restore when the current file cannot be classified safely.

Shared response support has a separate [bounded ingestion contract](../transports/inventory.md#bounded-response-ingestion-and-orcarouter-login):
raw-byte callers own their byte and deadline budgets and inherit best-effort cancellation.
The OrcaRouter login ceiling applies to its key exchange; client configuration files retain the
parsing and ownership rules below.

## Module Responsibilities

| Module | Responsibility |
Expand Down
2 changes: 1 addition & 1 deletion structure/gui-and-management-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ be treated as implemented:
`src/server/index.ts` authenticates and routes `/api/*`, then delegates to
`src/server/management-api.ts`, which composes the route modules under `src/server/management/`.
Codex account routes live in `src/codex/auth-api/routes.ts` because they own the credential store, not
because they are a different plane.
because they are a different plane. Upstream account response reads and OrcaRouter key exchange follow the [bounded ingestion contract](transports/inventory.md#bounded-response-ingestion-and-orcarouter-login).

The registered route set is larger than the areas described below; the code is the route SOT. What
this document owns is which module holds which area and what invariant that area must not break.
Expand Down
5 changes: 5 additions & 0 deletions structure/ops/docs-and-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ sharing a model-name fragment remain distinct from current Codex-native support.
The Remote Hub guide distinguishes selected-runtime readiness from general runtime diagnostics;
`tests/cli/cli-connect-readiness.test.ts` exercises that boundary and general status's single discovery pass with isolated executable fixtures.

The provider guide's OrcaRouter login section in English and all seven translated sources follows
the [bounded ingestion contract](../transports/inventory.md#bounded-response-ingestion-and-orcarouter-login):
64 KiB of valid UTF-8 JSON and one 30-second deadline covering headers and body. These are login
limits, so the public guide does not apply them to inference payloads.

## GitHub Pages

`.github/workflows/deploy-docs.yml` publishes the docs to:
Expand Down
4 changes: 4 additions & 0 deletions structure/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ opencodex state root does not undo those writes. Putting native Codex back is th
| `$CODEX_HOME/models_cache.json` | Codex, invalidated by opencodex | Cache invalidated after model/catalog changes. |
| `dist/`, `gui/dist/`, `node_modules/` | generated | Build output/dependencies. |

OrcaRouter login returns credentials for storage only after bounded response ingestion and payload
validation. The shared reader's cancellation contract and the login-specific byte/deadline limits
are defined in [bounded response ingestion](transports/inventory.md#bounded-response-ingestion-and-orcarouter-login).

## Non-negotiable invariants

Each invariant carries a stable id. A bound invariant names one test, and that test names the id
Expand Down
3 changes: 3 additions & 0 deletions structure/providers/xai-grok.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ The shared Responses path follows the [bounded multipart recovery contract](../s
on a per-provider FIXED loopback port, so every response it sends closes its connection. A
retired flow that kept a pooled socket would capture the NEXT login's callback and reject it
as a state mismatch; see `src/oauth/callback-server.ts`.
Provider token-body budgets are separate from this shared callback lifetime. The
[OrcaRouter bounded key-exchange contract](../transports/inventory.md#bounded-response-ingestion-and-orcarouter-login)
is owned by its login consumer and does not impose that budget on Grok token grants.
- **Two-lock refresh transaction:** per-provider+account intent lock held across the IdP
exchange plus a short global store-write lock + async mutation funnel around every
`auth.json` load-merge-persist (`src/oauth/store.ts`); generation-guarded persist
Expand Down
4 changes: 4 additions & 0 deletions structure/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ The server exposes `POST /api/stop` which restores native Codex config, stops an

## Providers and adapters

OrcaRouter key exchange uses the shared raw-byte reader before returning a durable key. Its
64 KiB response ceiling, single 30-second header/body deadline, and cancellation behavior follow
the [bounded ingestion contract](transports/inventory.md#bounded-response-ingestion-and-orcarouter-login).

| Path | Responsibility |
| --- | --- |
| `src/providers/registry.ts` | Compatibility facade; canonical provider presets for CLI, dashboard, OAuth, key providers, and metadata live in `src/providers/registry/entries-core.ts` and `entries-extended.ts`, with model seeds in `model-seeds.ts`. |
Expand Down
3 changes: 3 additions & 0 deletions structure/transports/byte-accounting.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ These optimizations do not add request queues, retry policies, or RSS-based admi
Translated audio/file admission follows the [final-adapter input contract](../adapters/registry.md#untranslated-input-media); native raw passthrough remains separate.
Canonical Responses identity sanitation and narrowly scoped pre-output combo recovery follow [request-local target compatibility](../runtime.md#request-local-target-compatibility); other adapter contracts remain unchanged.

Retaining whole response bodies is the separate concern of `src/lib/bounded-body.ts`, whose cap,
deadline, and cancellation rules are specified in the [bounded ingestion contract](inventory.md#bounded-response-ingestion-and-orcarouter-login).

Upstream API-key usage follows the [physical-attempt account attribution contract](../gui-and-management-api.md#upstream-key-account-attribution), independently of subscription quota observations.
Loading
Loading