Skip to content

Commit 993d449

Browse files
committed
docs: refresh Opus 5 architecture
1 parent 3cd4a60 commit 993d449

2 files changed

Lines changed: 17 additions & 12 deletions

File tree

ARCHITECTURE.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
**@cortexkit/anthropic-auth-core (Shared Core):**
1717
- Purpose: Reusable OAuth, account, quota, cache, relay, dump, SSE, and request-signing logic
1818
- Location: `packages/core/src/`
19-
- Contains: OAuth authorization/token exchange (`auth.ts`), account storage (`accounts.ts`), PKCE generation (`pkce.ts`), quota management (`quota-manager.ts`, `quotas.ts`), cache control (`cache1h.ts`, `cachekeep.ts`), relay protocol (`relay.ts`), dump capture (`dump.ts`), Claude Code identity and body signing (`claude-code.ts`, `cch.ts`), routing (`routing.ts`, `sticky-routing.ts`), killswitch thresholds (`killswitch.ts`), fast mode (`fast.ts`), model specs (`models.ts`), logging commands and config (`logging.ts`), provider HTTP error contracts (`provider.ts`), account command execution (`commands/account.ts`), shared structured logger (`logger.ts`), and constants (`constants.ts`)
19+
- Contains: OAuth authorization/token exchange (`auth.ts`), profile fetching (`oauth-profile.ts`), account storage (`accounts.ts`), PKCE generation (`pkce.ts`), token fingerprinting (`token-fingerprint.ts`), quota management (`quota-manager.ts`, `quotas.ts`, `quota-headers.ts`), cache control (`cache1h.ts`, `cachekeep.ts`, `cachekeep-registry.ts`), relay protocol (`relay.ts`), dump capture (`dump.ts`), Claude Code identity and body signing (`claude-code.ts`, `cch.ts`), routing (`routing.ts`, `sticky-routing.ts`), killswitch thresholds (`killswitch.ts`), fast mode (`fast.ts`), model specs (`models.ts`), logging commands and config (`logging.ts`), provider HTTP error contracts (`provider.ts`), account command execution (`commands/account.ts`), shared structured logger (`logger.ts`), and constants (`constants.ts`)
2020
- Depends on: `xxhash-wasm` (for cch body signing), Node.js built-ins (`crypto`, `fs`, `os`)
2121
- Used by: Both `@cortexkit/opencode-anthropic-auth` and `@cortexkit/pi-anthropic-auth`
2222

@@ -43,15 +43,15 @@
4343

4444
**OpenCode Request Lifecycle:**
4545

46-
1. **Plugin load** — OpenCode loads `@cortexkit/opencode-anthropic-auth` plugin, which starts background refresh timers, creates `QuotaManager` and `FallbackAccountManager`, initializes RPC server, and registers `auth.loader` + `provider.models` hooks. On boot, the plugin resolves the initial sidebar routing only after the asynchronous account-storage load completes, ensuring a peer's concurrent routing-authoritative publish during the load is not overwritten by a stale pre-load snapshot. — `packages/opencode/src/index.ts`
46+
1. **Plugin load** — OpenCode loads `@cortexkit/opencode-anthropic-auth` plugin, which starts background refresh timers, creates `QuotaManager` and `FallbackAccountManager`, initializes RPC server, and registers `auth.loader` + `provider.models` hooks. The model hook publishes native adaptive `low` through `max` effort variants for Opus 5 instead of legacy manual-thinking budgets. On boot, the plugin resolves the initial sidebar routing only after the asynchronous account-storage load completes, ensuring a peer's concurrent routing-authoritative publish during the load is not overwritten by a stale pre-load snapshot. — `packages/opencode/src/index.ts`
4747
2. **Auth loader** — When OpenCode creates an Anthropic session, the plugin's `auth.loader` runs: captures the OAuth `getAuth` function, starts main token refresh background loop — `packages/opencode/src/index.ts` (AnthropicAuthPlugin → auth.loader)
4848
3. **Command registration** — Plugin registers `/claude-cache`, `/claude-cachekeep`, `/claude-quota`, `/claude-dump`, `/claude-fast`, `/claude-routing`, `/claude-killswitch`, `/claude-account`, `/claude-logging``packages/opencode/src/index.ts` (config hook)
4949
4. **Request interception** — OpenCode's fetch wrapper calls the plugin's hooks — `packages/opencode/src/index.ts` (experimental fetch wrapping)
5050
5. **URL rewrite**`rewriteUrl()` adds `?beta=true` to `/v1/messages` and overrides base URL when `ANTHROPIC_BASE_URL` is set — `packages/opencode/src/transform.ts`
51-
6. **Request body rewrite**`rewriteRequestBody()` strips trailing assistant messages, normalizes Fable/Mythos thinking and Sonnet 5 adaptive thinking, injects billing header, sanitizes system prompt (removes OpenCode identity), prepends Claude Code identity, applies cache strategy (explicit/automatic/hybrid), adds fast mode, prefixes tool names with `mcp_`, creates `cch` over serialized body — `packages/opencode/src/transform.ts`
51+
6. **Request body rewrite**`rewriteRequestBody()` strips trailing assistant messages, normalizes Fable/Mythos, Sonnet 5, and Opus 5 adaptive thinking, injects billing header, sanitizes system prompt (removes OpenCode identity), prepends Claude Code identity, applies cache strategy (explicit/automatic/hybrid), adds fast mode, prefixes tool names with `mcp_`, creates `cch` over serialized body — `packages/opencode/src/transform.ts`
5252
7. **Routing**`shouldFallbackStatus()` checks if response should trigger fallback; `FallbackAccountManager` iterates accounts in ordered modes, while `StickySessionRouter` assigns cold sessions by reset-normalized spendable OAuth quota and weighted initial-prompt deficit, then persists hashed session affinity across processes/restarts. Sticky routes retain transient failures, hold confirmed 5h exhaustion when reset is within 15 minutes, and migrate for longer confirmed exhaustion/permanent account failure. All modes respect model-scoped quotas and killswitch thresholds (including per-model scoped thresholds). If all accounts fail the killswitch policy, a 429 block response is returned immediately; this block is classified as scoped-driven (matching a specific model's weekly limit) or account-level (5h/7d limits) with a model-specific or generic retry hint — `packages/core/src/routing.ts`, `packages/core/src/accounts.ts`, `packages/opencode/src/index.ts`
5353
8. **Relay**`sendViaRelay()` sends full or patched body to Cloudflare Worker, which streams Anthropic response back. HTTP relay responses and WebSocket `response_start` control messages deliver genuine upstream headers to the OpenCode account-bound quota harvester; synthetic optimistic response headers are never harvest input, and relay-to-direct fallback stays owned by the direct path — `packages/core/src/relay.ts`, `packages/opencode/src/index.ts`
54-
9. **SSE stream and Fable recovery** — Response body is wrapped in `createStrippedStream()`, which reverses the tool name prefix and detects Anthropic `refusal` finishes. For selected Fable sessions, a refusal activates a session-local 10-response Opus 4.8 downgrade; every successful downgraded response triggers a zero-output Fable prewarm through `CacheKeepManager` using the OAuth account that served the filtered Fable request. The last successful Opus tail anchor is retained per session and OAuth account; if Fable later refuses after that anchor has moved outside Anthropic's 20-block lookback, the retry spends the system cache slot on an explicit old-Opus-to-current-tail bridge rather than rewriting the intervening Opus cache. Recovery transitions are written per session to the TUI sidebar state; when no matching TUI is connected, OpenCode Desktop receives immediate ignored/no-reply `promptAsync` notices for the switch to Opus and return to Fable. Each notice is assigned a message ID immediately before the active assistant message: Desktop displays it immediately by creation time, while OpenCode's run loop sees it as older than the active assistant and cannot mistake it for pending user work or create an extra provider response — `packages/opencode/src/transform.ts`, `packages/opencode/src/fable-fallback.ts`, `packages/opencode/src/prompt-context.ts`, `packages/opencode/src/index.ts`
54+
9. **SSE stream and content-filter recovery** — Response body is wrapped in `createStrippedStream()`, which reverses the tool name prefix and detects Anthropic `refusal` finishes. For Fable or Opus 5, a refusal activates a 10-response Opus 4.8 downgrade keyed by session and source-model family; switching between Fable and Opus 5 cannot transfer recovery state or wait on the other family's pending cache warm. Every successful downgraded response triggers a zero-output source-model prewarm through `CacheKeepManager` using the OAuth account that served the filtered request. The last successful Opus 4.8 tail anchor is retained per source family and OAuth account; if the source model later refuses after that anchor has moved outside Anthropic's 20-block lookback, the retry spends the system cache slot on an explicit old-Opus-to-current-tail bridge rather than rewriting the intervening cache. Recovery transitions are written per session to the TUI sidebar state; when no matching TUI is connected, OpenCode Desktop receives immediate ignored/no-reply `promptAsync` notices for the switch to Opus 4.8 and return to the selected source model. Each notice is assigned a message ID immediately before the active assistant message: Desktop displays it immediately by creation time, while OpenCode's run loop sees it as older than the active assistant and cannot mistake it for pending user work or create an extra provider response — `packages/opencode/src/transform.ts`, `packages/opencode/src/fable-fallback.ts`, `packages/opencode/src/prompt-context.ts`, `packages/opencode/src/index.ts`
5555
10. **Sidebar update**`writeSidebarState()` writes quota/routing/cache state plus bounded per-session Fable recovery status to a JSON file read by the TUI sidebar widget (separate process via RPC). Routing-authoritative writes (e.g. active routing decisions) are distinguished from display-only/metadata writes (e.g. quota refreshes or command paths). Display-only writes re-read the file and merge state to preserve any live routing session's `activeId` and route. Cross-process writes are synchronized using an atomic `mkdir` directory lock with jittered retries, rename-claim eviction, and lock-budget exhaustion skips. The write is fenced: ownership is verified before and after the rename, triggering one bounded locked repair of routing-authoritative fields on post-rename loss. — `packages/opencode/src/sidebar-state.ts`, `packages/opencode/src/index.ts`
5656

5757
**Pi Request Lifecycle:**
@@ -61,12 +61,14 @@
6161
3. **Stream implementation**`streamCortexKitAnthropic()` in `packages/pi/src/stream.ts` builds the Anthropic request, sends via relay or direct, handles ordered or persistent sticky-balanced routing (including model-scoped quota routing), and cache keepalive
6262
4. **Slash commands**`/claude-*` commands registered in `packages/pi/src/commands.ts` reuse core command execution functions
6363

64-
**Quota Refresh Flow:**
64+
**Quota Refresh & Header Harvest Flow:**
6565
1. Background timer fires at `checkIntervalMinutes` (default 5) — `packages/core/src/quota-manager.ts`
6666
2. `QuotaManager.refreshMain()` fetches `https://api.anthropic.com/api/oauth/usage` (including standard five-hour/seven-day windows and weekly scoped model limits) with the access token
6767
3. On success: persists quota snapshot (including a top-level `checkedAt` freshness timestamp to support merge resolution of windowless empty-scoped quotas) to sidecar state file, updates sidebar state — `packages/opencode/src/index.ts` (onMainQuotaFetched callback)
6868
4. On 429: records backoff with `nextRetryAt` timestamp — prevents further refreshes during backoff — `packages/core/src/accounts.ts`
6969
5. Fallback accounts: `FallbackAccountManager` refreshes per-account quotas in background, persists to state, notifies sidebar — `packages/opencode/src/index.ts`
70+
6. Passive header harvesting: Upstream response headers (`anthropic-ratelimit-unified-*`) on direct fetch and HTTP/WebSocket relay transports are passively harvested (`normalizeQuotaHeaders`), merged into the quota snapshot, and update sidebar state without extra API polling — `packages/core/src/quota-headers.ts`, `packages/opencode/src/index.ts`
71+
7. Account profile metadata: Organization tier metadata (`Max 5x`, `Team · Max 5x`) is fetched from `https://api.anthropic.com/api/oauth/profile` (`fetchOAuthAccountProfile`), bound via SHA-256 token fingerprint, cached with a 7-day TTL, and persisted fire-and-forget without blocking user command execution — `packages/core/src/oauth-profile.ts`, `packages/core/src/token-fingerprint.ts`
7072

7173
**Cache Keepalive Flow:**
7274
1. `CacheKeepManager` tracks recently used hybrid-cache sessions and their associated `oauthAccountId``packages/core/src/cachekeep.ts`
@@ -92,7 +94,7 @@
9294
- Pattern: Cross-process locked atomic registry keyed by SHA-256 session hashes. Candidate weights combine spendable 5h/7d/model-scoped quota, reset horizon, and bytes assigned since the candidate quota snapshot. Assignments survive transient errors, can be cleared for the current session with `/claude-routing reset`, and expire after seven inactive days. Direct Opus allocation first consumes usable accounts with exhausted Fable scope; OpenCode Fable recovery continues on the original sticky account.
9395

9496
**CacheKeepManager:**
95-
- Purpose: Tracks hybrid-cache sessions and sends pre-warm requests before 1-hour TTL expiry; also exposes immediate zero-output prewarming for Fable content-filter recovery
97+
- Purpose: Tracks hybrid-cache sessions and sends pre-warm requests before 1-hour TTL expiry; also exposes immediate zero-output prewarming for Fable/Opus 5 content-filter recovery
9698
- Location: `packages/core/src/cachekeep.ts`
9799
- Pattern: In-memory target tracking with configurable local window or process-lifetime `always` schedule; tracks the associated `oauthAccountId` to pre-warm using the correct credentials; supports up to 32 concurrent sessions per manager and publishes sanitized tracking snapshots on changes/heartbeats
98100

@@ -102,9 +104,9 @@
102104
- Pattern: One atomic JSON lease record per manager under the system temporary directory; records contain only session IDs and cache timing, are separated into OpenCode/Pi scopes, deduplicate by session ID, and are ignored after a three-minute stale lease
103105

104106
**FableFallbackManager:**
105-
- Purpose: Maintains session-local Fable content-filter recovery state, rewriting the next 10 successful model requests to Opus 4.8 before probing Fable again
107+
- Purpose: Maintains Fable and Opus 5 content-filter recovery state, rewriting the next 10 successful source-family requests to Opus 4.8 before probing the selected model again
106108
- Location: `packages/opencode/src/fable-fallback.ts`
107-
- Pattern: Bounded, expiring in-memory session map with cycle IDs so late responses cannot decrement a newer recovery cycle; preserves the OAuth account identity used for Fable cache prewarming and the newest account-bound Opus tail fingerprint for a later model-specific cache bridge
109+
- Pattern: Bounded, expiring in-memory map keyed by session and source-model family, with cycle IDs so late responses cannot decrement a newer recovery cycle; preserves each family's OAuth account identity and newest account-bound Opus 4.8 tail fingerprint for source-model prewarming and later cache bridges
108110

109111
**PromptContextResolver:**
110112
- Purpose: Resolves the active agent, model, variant, and latest message IDs (assistant and user) from the OpenCode session message history

0 commit comments

Comments
 (0)