Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ GITHUB_OAUTH_CLIENT_ID=Iv1.b507a08c87ecfe98
# Used by: open-sse/executors/base.ts — buildHeaders() dynamic lookup.
# Update these when providers release new CLI versions to avoid blocks.

CLAUDE_USER_AGENT="claude-cli/2.1.219 (external, cli)"
CLAUDE_USER_AGENT="claude-cli/2.1.258 (external, cli)"

# Disable the deterministic tool-name cloak applied on both Anthropic-bound paths
# (executors/base.ts native OAuth + executors/cliproxyapi.ts CLIProxyAPI) —
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### ✨ New Features

- **feat(providers):** add Claude Fable 5.1 (`claude-fable-5-1`) — wires the new flagship model across the full first-party pipeline: `cc`/`claude`, `claude-web`, `anthropic`, `vertex`, `vertex-partner`, `ghe-copilot`, and `github` registries (1M context, adaptive thinking, vision, tools), pricing constants (native `$15/$75`, cc OAuth `$10/$50`), model spec (adaptive-only, rejects `thinking.type:"disabled"` per #3554), 1M-context beta header, fast mode, fallback chain (`claude-fable-5-1 → claude-fable-5 → claude-opus-4-8 → claude-opus-4-7 → claude-sonnet-5`), and cost data. Fable 5.1 becomes the default resolved Fable tier (`ANTHROPIC_DEFAULT_FABLE_MODEL`); Kiro stays excluded (its upstream serves no Fable tier). Also bumps the pinned Claude Code wire identity from `2.1.220` to `2.1.258` (captured from the signed CLI: `claude-cli/2.1.258`, billing `cc_version=2.1.258.1e2`, Stainless SDK `0.112.1`) — Anthropic gates `claude-fable-5-1` behind Claude Code ≥ 2.1.251 and rejected the old fingerprint with `400 Claude Code 2.1.220 does not support this model; version 2.1.251 or newer is required`. The dashboard routing preset now imports the shared build revision instead of hardcoding it.
- **feat(sse): STRICT_ZERO_COST** — opt-in, off-by-default `freeAccessPolicy: "strict"` setting
that hard-verifies every auto-combo candidate against live quota state and per-connection
economic safety before it can be dispatched, going beyond `hidePaidModels`'s static catalog
Expand Down Expand Up @@ -89,6 +90,10 @@
- **feat(cli):** run `omniroute serve --tray` as a detached desktop process after server and tray readiness, with graphical login auto-start support.
- **feat(routing):** add client-, provider-, and model-neutral exclusive managed session connection leases with API-key-bound generation fencing, durable SQLite ownership, explicit allowlist policy, and bounded 429 capacity retry semantics.

### 📝 Maintenance

- **chore(docker):** bump the Devin Claude bridge's real Claude Code install from `2.1.220` to `2.1.258` (`docker/devin-bridge/Dockerfile` default + `compose.yml` build arg) — the same CLI generation OmniRoute's Claude identity now impersonates, and the first line that knows the Fable 5.1 tier natively. The pin only affects the containerized CLI: OmniRoute rewrites the `User-Agent` and the billing line on the Claude OAuth path, so Anthropic's `2.1.251+` gate never sees the bridge's own CLI version. Validated on the pinned base image (`node:26.0.0-bookworm-slim`, arm64): the install layer builds and `claude --version` reports `2.1.258`; the bridge unit suite, `compose config` and the static isolation proof pass. The offline mock e2e and the three-scenario live suite were not re-run on the new pin (the image build needs more than an 8 GB Docker VM) — see the status note in `docs/DEVIN_CLAUDE_BRIDGE.md`.

## [3.8.51] — TBD

_Living section — cycle opened at the v3.8.50 freeze (parallel-cycle model). Bullets are aggregated from `changelog.d/` fragments at each `/generate-release` phase._
Expand Down
2 changes: 1 addition & 1 deletion docker/devin-bridge/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM node:26.0.0-bookworm-slim

ARG CLAUDE_CODE_VERSION=2.1.220
ARG CLAUDE_CODE_VERSION=2.1.258
ARG DEVIN_CLI_VERSION=3000.2.17
ARG TARGETARCH

Expand Down
2 changes: 1 addition & 1 deletion docker/devin-bridge/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ x-runtime: &runtime
context: ../..
dockerfile: docker/devin-bridge/Dockerfile
args:
CLAUDE_CODE_VERSION: 2.1.220
CLAUDE_CODE_VERSION: 2.1.258
DEVIN_CLI_VERSION: 3000.2.17
user: "10001:10001"
read_only: true
Expand Down
18 changes: 12 additions & 6 deletions docs/DEVIN_CLAUDE_BRIDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@
Messages endpoint while the official Devin CLI supplies model responses over ACP stdio. It
does not modify the existing Anthropic, Claude OAuth, Claude Web, or `devin-cli` providers.

> **Current status: offline and live validated.** The pinned Claude Code `2.1.220` completed
> three isolated scenarios through Devin CLI `3000.2.17` and model
> `swe-1-7-lightning`. The final live run proved client-owned `Read`, `Edit`, and `Bash`
> turns, successful `npm test` results, project command and skill discovery, Devin-only
> routing, and zero Claude egress.
> **Current status: pinned Claude Code `2.1.258`; offline and live validation last recorded
> on `2.1.220`.** The `2.1.220` pin completed three isolated scenarios through Devin CLI
> `3000.2.17` and model `swe-1-7-lightning`; that final live run proved client-owned `Read`,
> `Edit`, and `Bash` turns, successful `npm test` results, project command and skill
> discovery, Devin-only routing, and zero Claude egress. The pin was then raised to `2.1.258`
> (the CLI generation OmniRoute's Claude identity impersonates, and the first line that ships
> the Fable 5.1 tier natively). On the new pin the install layer and `claude --version` were
> verified on the pinned base image, and the bridge unit suite, `compose config` and the
> static isolation proof pass — but the offline mock scenario and the live three-scenario
> suite have not been re-run yet. Re-run them (see "Updating pinned tools") before relying on
> the bridge with this pin.

## Architecture

```text
Claude Code 2.1.220 (isolated non-root Linux container)
Claude Code 2.1.258 (isolated non-root Linux container)
-> http://omniroute:20128/v1/messages
-> devin-cli-agentic (Claude-format, no-auth provider)
-> devin acp --agent-type summarizer (official ACP stdio, no Devin tools)
Expand Down
2 changes: 1 addition & 1 deletion docs/providers/AGENTROUTER.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ request (see `open-sse/services/claudeCodeCompatible.ts`):
| Header | Value |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `Authorization` | `Bearer <api-key>` |
| `User-Agent` | `claude-cli/2.1.219 (external, sdk-cli)` |
| `User-Agent` | `claude-cli/2.1.258 (external, sdk-cli)` |
| `anthropic-version` | `2023-06-01` |
| `anthropic-beta` | `claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24` |
| Per-connection redact-thinking beta toggle | Adds `redact-thinking-2026-02-12` for upstreams that specifically require redacted thinking streams |
Expand Down
3 changes: 2 additions & 1 deletion docs/providers/CLAUDE_WEB.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ strictly translates the upstream SSE response. The orchestration is in

### Model catalog

The provider registry currently exposes exactly these seven static model IDs
The provider registry currently exposes these static model IDs
(`open-sse/config/providers/registry/claude/web/index.ts:11`):

| Model ID | Display name |
| --------------------------- | ----------------------- |
| `claude-fable-5-1` | Claude Fable 5.1 (web) |
| `claude-fable-5` | Claude Fable 5 (web) |
| `claude-opus-4-8` | Claude Opus 4.8 (web) |
| `claude-sonnet-5` | Claude Sonnet 5 (web) |
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/ENVIRONMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ process.env[`${PROVIDER_ID}_USER_AGENT`]

| Variable | Default Value | When to Update |
| -------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.258 (external, cli)` | When Anthropic releases a new CLI version |
| `CLAUDE_DISABLE_TOOL_NAME_CLOAK` | `false` | `executors/base.ts` + `executors/cliproxyapi.ts` | Set to `1`/`true` to forward third-party harness tool names verbatim to Anthropic on both Anthropic-bound paths (native OAuth and CLIProxyAPI). By default the executor deterministically aliases non-Claude-Code tool names (Claude Code canonical mapping where one exists, otherwise PascalCase) and reverses them on the response via `_toolNameMap`, so harnesses with snake_case tools are not refused as fingerprinted third-party clients. Debugging only. |
| `CODEX_USER_AGENT` | `codex-cli/0.142.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
Expand Down
6 changes: 3 additions & 3 deletions docs/security/STEALTH_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ Applied to: `system` blocks, all `messages[].content`, and `tools[].description`

For third-party Anthropic relays that only accept "real Claude Code" traffic:

- `CLAUDE_CODE_COMPATIBLE_USER_AGENT = "claude-cli/2.1.220 (external, sdk-cli)"`
- `CLAUDE_CODE_COMPATIBLE_STAINLESS_PACKAGE_VERSION = "0.94.0"`
- `CLAUDE_CODE_COMPATIBLE_USER_AGENT = "claude-cli/2.1.258 (external, sdk-cli)"`
- `CLAUDE_CODE_COMPATIBLE_STAINLESS_PACKAGE_VERSION = "0.112.1"`
- `CLAUDE_CODE_COMPATIBLE_STAINLESS_RUNTIME_VERSION = "v26.3.0"`
- `anthropic-beta = "claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24"` by default
- The per-connection "Enable redact-thinking beta" toggle adds `redact-thinking-2026-02-12` when a CC Compatible upstream specifically requires redacted thinking streams
Expand Down Expand Up @@ -198,7 +198,7 @@ All MITM endpoints require management auth (`requireCliToolsAuth`). The sudo pas

| Variable | Default |
| ------------------------ | --------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.220 (external, cli)` |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.258 (external, cli)` |
| `CODEX_USER_AGENT` | `codex-cli/0.149.0 (Windows 10.0.26200; x64)` |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.54.0` |
| `ANTIGRAVITY_USER_AGENT` | `antigravity/2.0.1 linux/arm64 google-api-nodejs-client/10.3.0` |
Expand Down
3 changes: 2 additions & 1 deletion open-sse/config/context1m.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* without importing each other.
*/
export const CONTEXT_1M_SUPPORTED_MODELS = [
"claude-fable-5-1",
"claude-fable-5",
"claude-sonnet-5",
"claude-sonnet-4-6",
Expand All @@ -36,4 +37,4 @@ export function modelSupportsContext1mBeta(model: string | null | undefined): bo
return CONTEXT_1M_SUPPORTED_MODELS.some(
(supported) => normalizedModel === supported || normalizedModel.startsWith(`${supported}-`)
);
}
}
6 changes: 6 additions & 0 deletions open-sse/config/providers/registry/anthropic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ export const anthropicProvider: RegistryEntry = {
"Anthropic-Beta": ANTHROPIC_BETA_API_KEY,
},
models: [
{
id: "claude-fable-5-1",
name: "Claude Fable 5.1",
contextLength: 1048576,
unsupportedParams: ["temperature", "top_p", "top_k"],
},
{
id: "claude-fable-5",
name: "Claude Fable 5",
Expand Down
9 changes: 9 additions & 0 deletions open-sse/config/providers/registry/claude/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ export const claudeProvider: RegistryEntry = {
tokenUrl: "https://api.anthropic.com/v1/oauth/token",
},
models: [
{
id: "claude-fable-5-1",
name: "Claude Fable 5.1",
contextLength: 1000000,
maxOutputTokens: 128000,
// Opus 4.7+/Fable 5.x reject non-default temperature/top_p/top_k with a 400 (sampling
// is fixed; reasoning is steered by output_config.effort). Strip them before dispatch.
unsupportedParams: ["temperature", "top_p", "top_k"],
},
{
id: "claude-fable-5",
name: "Claude Fable 5",
Expand Down
1 change: 1 addition & 0 deletions open-sse/config/providers/registry/claude/web/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const claude_webProvider: RegistryEntry = {
authType: "apikey",
authHeader: "cookie",
models: [
{ id: "claude-fable-5-1", name: "Claude Fable 5.1 (web)", toolCalling: false },
{ id: "claude-fable-5", name: "Claude Fable 5 (web)", toolCalling: false },
{
id: "claude-opus-5",
Expand Down
6 changes: 6 additions & 0 deletions open-sse/config/providers/registry/ghe-copilot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ export const gheCopilotProvider: RegistryEntry = {
defaultContextLength: 128000,
headers: getGitHubCopilotChatHeaders(),
models: [
{
id: "claude-fable-5-1",
name: "Claude Fable 5.1",
contextLength: 1000000,
maxOutputTokens: 64000,
},
{
id: "claude-fable-5",
name: "Claude Fable 5",
Expand Down
7 changes: 7 additions & 0 deletions open-sse/config/providers/registry/github/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ export const githubProvider: RegistryEntry = {
// messagesUrl (/v1/messages) instead of /chat/completions. Port of
// decolua/9router#2608 (author: yidecode) — see executors/github.ts.
models: [
{
id: "claude-fable-5-1",
name: "Claude Fable 5.1",
targetFormat: "claude",
contextLength: 1000000,
maxOutputTokens: 64000,
},
{
id: "claude-fable-5",
name: "Claude Fable 5",
Expand Down
1 change: 1 addition & 0 deletions open-sse/config/providers/registry/vertex/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const vertexProvider: RegistryEntry = {
{ id: "DeepSeek-V4-Pro", name: "DeepSeek V4 Pro (Vertex Partner)" },
{ id: "Qwen3.6-35B-A3B", name: "Qwen3.6 35B A3B (Vertex Partner)" },
{ id: "GLM-5.1-FP8", name: "GLM-5.1 (Vertex Partner)" },
{ id: "claude-fable-5-1", name: "Claude Fable 5.1 (Vertex)", targetFormat: "claude" },
{ id: "claude-fable-5", name: "Claude Fable 5 (Vertex)", targetFormat: "claude" },
{ id: "claude-opus-5", name: "Claude Opus 5 (Vertex)", targetFormat: "claude" },
{ id: "claude-sonnet-5", name: "Claude Sonnet 5 (Vertex)", targetFormat: "claude" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const vertex_partnerProvider: RegistryEntry = {
{ id: "DeepSeek-V4-Pro", name: "DeepSeek V4 Pro" },
{ id: "Qwen3.6-35B-A3B", name: "Qwen 3.6 35B A3B" },
{ id: "GLM-5.1-FP8", name: "GLM 5.1" },
{ id: "claude-fable-5-1", name: "Claude Fable 5.1", targetFormat: "claude" },
{ id: "claude-fable-5", name: "Claude Fable 5", targetFormat: "claude" },
{ id: "claude-opus-5", name: "Claude Opus 5", targetFormat: "claude" },
{ id: "claude-sonnet-5", name: "Claude Sonnet 5", targetFormat: "claude" },
Expand Down
4 changes: 4 additions & 0 deletions open-sse/services/modelFamilyFallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ const FAMILY_FALLBACK_TEMPLATES: Record<string, readonly string[]> = {
"gemini-2.5-pro": ["gemini-2.5-pro-preview-06-05", "gemini-2.5-pro-exp-03-25"],
"gemini-2.5-pro-preview-06-05": ["gemini-2.5-pro", "gemini-2.5-pro-exp-03-25"],

// Claude Mythos family (Fable 5.1) — newest flagship; degrades to Fable 5
// first, then the next-best Opus tiers before the cheaper Sonnet.
"claude-fable-5-1": ["claude-fable-5", "claude-opus-4-8", "claude-opus-4-7", "claude-sonnet-5"],

// Claude Mythos family (Fable 5) — flagship falls to the next-best Opus
// tiers before the cheaper Sonnet, matching the Opus family ordering.
"claude-fable-5": ["claude-opus-4-8", "claude-opus-4-7", "claude-sonnet-5"],
Expand Down
1 change: 1 addition & 0 deletions open-sse/services/providerCostData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface ModelPricing {
export const KNOWN_MODEL_PRICING: Record<string, ModelPricing> = {
"gpt-4o": { inputCostPer1M: 2.5, outputCostPer1M: 10.0, isFree: false },
"gpt-4o-mini": { inputCostPer1M: 0.15, outputCostPer1M: 0.6, isFree: false },
"claude-fable-5-1": { inputCostPer1M: 15.0, outputCostPer1M: 75.0, isFree: false },
"claude-fable-5": { inputCostPer1M: 15.0, outputCostPer1M: 75.0, isFree: false },
"claude-opus-5": { inputCostPer1M: 5.0, outputCostPer1M: 25.0, isFree: false },
"claude-opus-4-8": { inputCostPer1M: 15.0, outputCostPer1M: 75.0, isFree: false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
normalizeCliCompatProviderId,
} from "@/shared/constants/cliCompatProviders";
import { AI_PROVIDERS } from "@/shared/constants/providers";
import { CLAUDE_CODE_CLIENT_BUILD_REVISION } from "@/shared/constants/claudeCodeClient";
import { compareTr } from "@/shared/utils/turkishText";
import { HERMES } from "./systemTransformsHermesDefaults";

Expand Down Expand Up @@ -169,7 +170,7 @@ const DEFAULT_SYSTEM_TRANSFORMS_CLIENT = {
entrypoint: "sdk-cli",
versionFormat: "ex-machina",
cchAlgo: "sha256-first-user",
buildRevision: "1f2",
buildRevision: CLAUDE_CODE_CLIENT_BUILD_REVISION,
},
],
},
Expand Down
1 change: 1 addition & 0 deletions src/lib/db/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export async function getSettings() {
claudeFastMode: {
enabled: false,
supportedModels: [
"claude-fable-5-1",
"claude-fable-5",
"claude-opus-5",
"claude-opus-4-8",
Expand Down
1 change: 1 addition & 0 deletions src/lib/providers/claudeFastMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type JsonRecord = Record<string, unknown>;
* observed in claude-code v2.1.145 (KT() check).
*/
export const CLAUDE_FAST_MODE_DEFAULT_MODELS = [
"claude-fable-5-1",
"claude-fable-5",
"claude-opus-5",
"claude-opus-4-8",
Expand Down
1 change: 1 addition & 0 deletions src/lib/providers/staticModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const STATIC_MODEL_PROVIDERS: Record<string, () => Array<{ id: string; name: str
],
antigravity: () => ANTIGRAVITY_PUBLIC_MODELS.map((model) => ({ ...model })),
claude: () => [
{ id: "claude-fable-5-1", name: "Claude Fable 5.1" },
{ id: "claude-fable-5", name: "Claude Fable 5" },
{ id: "claude-opus-5", name: "Claude Opus 5" },
{ id: "claude-opus-4-8", name: "Claude Opus 4.8" },
Expand Down
6 changes: 3 additions & 3 deletions src/shared/constants/claudeCodeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* Keep this leaf dependency-free so server executors, compatibility bridges,
* and client-facing identity presets can share one source of truth.
*/
export const CLAUDE_CODE_CLIENT_VERSION = "2.1.220";
export const CLAUDE_CODE_CLIENT_BUILD_REVISION = "1f2";
export const CLAUDE_CODE_CLIENT_VERSION = "2.1.258";
export const CLAUDE_CODE_CLIENT_BUILD_REVISION = "1e2";
export const CLAUDE_CODE_CLIENT_BILLING_VERSION = `${CLAUDE_CODE_CLIENT_VERSION}.${CLAUDE_CODE_CLIENT_BUILD_REVISION}`;
export const CLAUDE_CODE_SDK_PACKAGE_VERSION = "0.94.0";
export const CLAUDE_CODE_SDK_PACKAGE_VERSION = "0.112.1";
export const CLAUDE_CODE_RUNTIME_VERSION = "v26.3.0";

export type ClaudeCodeEntrypoint = "cli" | "sdk-cli";
Expand Down
16 changes: 16 additions & 0 deletions src/shared/constants/modelSpecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,22 @@ export const MODEL_SPECS: Record<string, ModelSpec> = {
aliases: BEDROCK_CLAUDE_ALIASES("claude-opus-4-7", "claude-opus-4.7"),
},

// ── Claude Fable 5.1 ────────────────────────────────────────────
"claude-fable-5-1": {
maxOutputTokens: 128000,
contextWindow: 1000000,
defaultThinkingBudget: 32000,
thinkingBudgetCap: 120000,
supportsThinking: true,
supportsTools: true,
supportsVision: true,
// Fable 5.1 defaults to adaptive thinking and rejects `thinking.type:"disabled"` (#3554).
rejectsThinkingDisabled: true,
// …and, like Opus 4.7+, rejects manual budgets/`type:"enabled"` (adaptive-only).
adaptiveThinkingOnly: true,
aliases: BEDROCK_CLAUDE_ALIASES("claude-fable-5-1"),
},

// ── Claude Fable 5 ──────────────────────────────────────────────
"claude-fable-5": {
maxOutputTokens: 128000,
Expand Down
Loading
Loading