@mars-sea/dsh-commandcode-provider 0.10.0-alpha.3 → 0.10.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["reject","createNetServer","createHttpServer"],"sources":["../src/accounts.ts","../src/adapter.ts","../src/command-locales.ts","../src/commands.ts","../src/usage-wire.ts","../src/login-wire.ts","../src/usage-remote.ts","../src/login.ts","../src/index.ts"],"sourcesContent":["/**\n * Multi-account pool for the Command Code provider (host side).\n *\n * One Command Code subscription (e.g. the Go plan's 5-hour window) is\n * metered; a user with several subscriptions wants a request that hits one\n * account's limit to continue on the next account without a visible failure.\n * This module owns that rotation:\n *\n * - {@link CommandCodeAccountPool.resolveKey} hands out the first account\n * whose key is not currently marked exhausted — or, when the request's\n * model matches a {@link CommandCodeModelAccountRule} and that account is\n * usable, the routed account — resolving each slot's key lazily (literal\n * config key → credential seam → launch environment → the official CLI\n * auth file for the default slot only).\n * - {@link CommandCodeAccountPool.markRejected} records a 429 (rate limit,\n * window unknown) or 401 (invalid key, disabled until the config changes)\n * against the exact API key, so several slots sharing one key share one\n * state.\n * - When every account is marked, the pool probes each key's\n * `/alpha/billing/credits` window limits (through the injected\n * {@link CommandCodeAccountPoolDeps.probeWindow}): an account whose window\n * no longer reports `exceeded` is revived, otherwise the pool throws a\n * `RATE_LIMIT` error naming the earliest reset time.\n *\n * The pool is deliberately cordis-free (like the adapter): every host fact\n * arrives through injected thunks, so node tests can drive it directly.\n *\n * @module dsh-commandcode-provider/accounts\n */\n\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { CredentialRef } from '@deepseek-ai/dsh-credentials'\n\n/**\n * Upper bound on the retry wait this pool attaches to the all-exhausted\n * `RATE_LIMIT` error. Must equal the `backoff.maxDelayMs` in the adapter's\n * `providerRetryPolicy` (which imports it from here): dsh-llm-retry honors a\n * provider-specified wait verbatim only at or below that cap — in normal mode\n * a LONGER attached wait makes the executor abandon the retry entirely\n * instead of falling back to local backoff, which would turn \"poll until the\n * window opens\" into \"fail now\".\n */\nexport const RETRY_MAX_DELAY_MS = 900_000\n\n/** One extra account's raw configuration (composition config or settings). */\nexport interface CommandCodeAccountConfig {\n /** Display label shown in the usage dashboard and settings page. */\n label?: string\n /** Credential reference (environment-variable style name) holding this account's API key. */\n apiKeyEnv?: string\n /** Literal API key (composition config only; never stored in settings). */\n apiKey?: string\n}\n\n/** One account slot after config normalization. */\nexport interface CommandCodeAccountSlot {\n /** Stable id: `default` for the implicit first account, `account-N` for extras. */\n id: string\n /** Display label (user-provided or generated). */\n label: string\n /** Credential reference resolved through the seam; undefined for literal-only slots. */\n ref?: CredentialRef | undefined\n /** Literal key from composition config. */\n literal?: string | undefined\n /** Whether the official CLI auth file may back this slot (default slot only). */\n allowAuthFile: boolean\n}\n\n/** Why a key stopped serving requests. */\nexport type AccountRejection = 'rate-limit' | 'invalid-credential'\n\n/** One key's rotation state. */\nexport interface CommandCodeAccountState {\n kind:\n /** Marked by a 429; the window's reset time is unknown until probed. */\n | 'unknown'\n /** Probed (or marked with a known reset): unusable until `until` (millis). */\n | 'cooldown'\n /** Marked by a 401: skipped until the stored credential changes. */\n | 'disabled'\n /** Human-readable reason for the mark (e.g. `rate limited (429)`). */\n reason: string\n /** Cooldown end in millis; 0 for the other kinds. */\n until: number\n}\n\n/** A slot paired with its resolved key (both pool-internal and UI-facing). */\nexport interface ResolvedAccount {\n slot: CommandCodeAccountSlot\n key: string\n /** The key's current rotation state; undefined means usable. */\n state: CommandCodeAccountState | undefined\n}\n\n/** Five-hour window facts probed from `/alpha/billing/credits`. */\nexport interface FiveHourWindowProbe {\n exceeded: boolean\n resetAt: number\n}\n\n/** Everything the pool needs from the host; all seams are injected. */\nexport interface CommandCodeAccountPoolDeps {\n /** The current account slots, re-read per resolution so settings changes apply live. */\n slots(): readonly CommandCodeAccountSlot[]\n /** Resolve one credential reference through the credentials service or the launch environment. */\n resolveRef(ref: CredentialRef): Promise<string | undefined>\n /** The official CLI auth-file key (`~/.commandcode/auth.json`); default slot only. */\n authFileKey(): string | undefined\n /** Probe one key's five-hour window; undefined when the probe itself failed. */\n probeWindow(apiKey: string): Promise<FiveHourWindowProbe | undefined>\n /**\n * The manually selected account (a slot id, e.g. `default` or an extra's\n * credential reference), re-read per resolution. The preferred account\n * serves whenever it is usable; an unknown id or an exhausted preferred\n * account falls back to the first usable slot.\n */\n preferredId?(): string | undefined\n /**\n * Model → account routing rules, re-read per resolution so settings changes\n * apply live. Each rule lists catalog model ids (see\n * {@link CommandCodeModelAccountRule}) to an account slot id. When the\n * request's model matches a rule and that account is usable, it serves\n * before the preferred/rotation selection; an unusable routed account falls\n * back to the normal selection (the router is a hint, never a hard gate).\n */\n modelAccountRules?(): readonly CommandCodeModelAccountRule[]\n}\n\n/**\n * One \"route these models to that account\" rule. `models` lists catalog ids\n * (`deepseek/deepseek-v4-pro`, …); `account` is a slot id (`default` or an\n * extra account's credential reference). A request whose model id is in the\n * list routes to that account. The first matching rule in list order wins.\n */\nexport interface CommandCodeModelAccountRule {\n /** Catalog model ids to match against the request's model. */\n models: string[]\n /** Account slot id to prefer for matching models. */\n account: string\n}\n\n/** A labeled, human-readable clock reading for error messages. */\nfunction clockLabel(ms: number): string {\n return new Date(ms).toLocaleString()\n}\n\n/**\n * Whether an account with this rotation state can serve a request right now.\n * `undefined` (never rejected) is usable; a cooldown becomes usable again\n * once its reset time passes; `unknown` (429, reset unprobed) and\n * `disabled` (401) are not.\n */\nexport function accountUsable(state: CommandCodeAccountState | undefined): boolean {\n if (state === undefined) return true\n if (state.kind === 'cooldown') return state.until > 0 && Date.now() >= state.until\n return false\n}\n\n/**\n * Pick the account that should serve now: the manually preferred slot when it\n * is usable, otherwise the first usable account in rotation order; undefined\n * when no account is usable. Shared by the pool (request path) and the plugin\n * entry (the usage view's active badge) so both always agree.\n */\nexport function selectActiveAccount(\n accounts: readonly ResolvedAccount[],\n preferredId: string | undefined,\n): ResolvedAccount | undefined {\n const usable = accounts.filter((account) => accountUsable(account.state))\n if (preferredId !== undefined) {\n const preferred = usable.find((account) => account.slot.id === preferredId)\n if (preferred !== undefined) return preferred\n }\n return usable[0]\n}\n\n/**\n * The first routing rule whose model list contains the request's model id.\n * Undefined when no rule matches.\n */\nexport function matchModelRule(\n model: string,\n rules: readonly CommandCodeModelAccountRule[] | undefined,\n): CommandCodeModelAccountRule | undefined {\n if (model === '' || rules === undefined || rules.length === 0) return undefined\n for (const rule of rules) {\n if (rule.models.includes(model)) return rule\n }\n return undefined\n}\n\n/**\n * The routed account for a request's model: the first usable account whose\n * slot id matches the first matching rule's target. Undefined when no rule\n * matches or the routed account is not usable (the caller then falls back to\n * the normal preferred/rotation selection).\n */\nexport function selectAccountForModel(\n accounts: readonly ResolvedAccount[],\n model: string,\n rules: readonly CommandCodeModelAccountRule[] | undefined,\n): ResolvedAccount | undefined {\n const rule = matchModelRule(model, rules)\n if (rule === undefined) return undefined\n return accounts.find((account) => account.slot.id === rule.account && accountUsable(account.state))\n}\n\n/**\n * The account pool. Rotation state is keyed by API key (never logged), so two\n * slots resolving to the same credential share one mark, and a key changed in\n * the credentials service starts with a clean slate.\n */\nexport class CommandCodeAccountPool {\n /** Rotation state by API key. */\n private readonly states = new Map<string, CommandCodeAccountState>()\n constructor(private readonly deps: CommandCodeAccountPoolDeps) {}\n\n /**\n * Resolve every slot's key, deduplicated by key (first slot wins). Slots\n * without any resolvable key are omitted — they still appear in the\n * settings page as unconfigured, they just cannot serve requests.\n */\n async resolvedAccounts(): Promise<ResolvedAccount[]> {\n const out: ResolvedAccount[] = []\n const seen = new Set<string>()\n for (const slot of this.deps.slots()) {\n const key = await this.resolveSlotKey(slot)\n if (key === undefined || seen.has(key)) continue\n seen.add(key)\n out.push({ slot, key, state: this.states.get(key) })\n }\n return out\n }\n\n /**\n * Every slot paired with its resolved key and rotation state — NOT\n * deduplicated: two slots sharing one credential both appear (the usage\n * view reports them individually), while slots without any resolvable key\n * are omitted. The serving path uses {@link resolvedAccounts} instead.\n */\n async describeAccounts(): Promise<ResolvedAccount[]> {\n const out: ResolvedAccount[] = []\n for (const slot of this.deps.slots()) {\n const key = await this.resolveSlotKey(slot)\n if (key === undefined) continue\n out.push({ slot, key, state: this.states.get(key) })\n }\n return out\n }\n\n /**\n * Hand out the key for a request: the model-routed account when the\n * request's model matches a rule (and that account is usable), else the\n * manually preferred account when usable, else the first usable account in\n * rotation order. Returns `undefined` when no account resolves any key at\n * all (the caller then reports the missing credential). Throws\n * `RATE_LIMIT` — naming the earliest window reset — or\n * `INVALID_CREDENTIAL` when accounts exist but none can serve.\n *\n * `options.model` is the request's model id; routing rules re-read per\n * resolution, so a settings change applies live.\n *\n * `options.exclude` skips one key during the probe-revival pass: the\n * rotation hook excludes the just-rejected key so a probe that clears its\n * window cannot re-offer the same key within the same request (the adapter\n * refuses already-tried keys; the next request picks the revived key up).\n */\n async resolveKey(options?: { exclude?: string; model?: string }): Promise<{ key: string; slot: CommandCodeAccountSlot } | undefined> {\n const accounts = await this.resolvedAccounts()\n if (accounts.length === 0) {\n return undefined\n }\n const routed = selectAccountForModel(accounts, options?.model ?? '', this.deps.modelAccountRules?.())\n if (routed !== undefined) return this.pick(routed)\n const chosen = selectActiveAccount(accounts, this.deps.preferredId?.())\n if (chosen !== undefined) return this.pick(chosen)\n\n // Every key is marked: probe the real windows before giving up. Disabled\n // (401) keys are not probed — an invalid key stays invalid.\n await Promise.all(accounts.map(async (account) => {\n if (account.state?.kind === 'disabled') return\n if (options?.exclude !== undefined && account.key === options.exclude) return\n const probe = await this.deps.probeWindow(account.key)\n if (probe === undefined) return\n if (!probe.exceeded) {\n this.states.delete(account.key)\n } else {\n this.states.set(account.key, {\n kind: 'cooldown',\n reason: account.state?.reason ?? 'rate limited (429)',\n until: probe.resetAt,\n })\n }\n }))\n\n const revived = selectActiveAccount(await this.resolvedAccounts(), this.deps.preferredId?.())\n if (revived !== undefined) return this.pick(revived)\n\n const latest = await this.resolvedAccounts()\n const disabled = latest.filter((account) => account.state?.kind === 'disabled')\n if (disabled.length === latest.length) {\n // Bilingual: the harness UI renders this message verbatim inside its\n // (already localized) retry/turn-error chrome, so both languages ride\n // in one string — English first, then the Chinese reading.\n throw new LlmError(\n `llm-commandcode: every configured Command Code account (${latest.length}) was rejected with 401`\n + ' — check the stored API keys (Models page / settings) or the auth file'\n + `;已配置的 ${latest.length} 个 Command Code 账户密钥均被拒绝(401)`\n + '——请在设置页检查存储的 API 密钥,或重新运行 command-code login',\n 'INVALID_CREDENTIAL',\n )\n }\n const resets = latest\n .map((account) => account.state)\n .filter((state): state is CommandCodeAccountState => state !== undefined && state.kind === 'cooldown' && state.until > 0)\n .map((state) => state.until)\n const earliest = resets.length > 0 ? Math.min(...resets) : 0\n // Hand dsh-llm-retry the exact wait until the earliest known reset so the\n // retry policy sleeps through the window instead of polling at its\n // backoff cadence. Capped at RETRY_MAX_DELAY_MS: the executor honors a\n // provider wait verbatim only at or below the policy's maxDelayMs — a\n // LONGER attached wait makes it abandon the retry entirely (normal mode),\n // which would turn \"poll until the window opens\" into \"fail now\". Longer\n // resets simply ride the capped local backoff and the probe revival.\n const wait = earliest > 0 ? Math.max(1000, earliest - Date.now()) : 0\n throw new LlmError(\n `llm-commandcode: all ${latest.length} Command Code account(s) have exhausted their usage window`\n + (earliest > 0 ? `; the earliest window resets at ${clockLabel(earliest)}` : '')\n + ' — requests will succeed again after the reset (or add another account)'\n + `;已用尽全部 ${latest.length} 个 Command Code 账户的用量窗口`\n + (earliest > 0 ? `,最早的重置时间为 ${clockLabel(earliest)}` : '')\n + '——窗口重置后请求会自动恢复(也可以添加更多账户)',\n 'RATE_LIMIT',\n wait > 0 && wait <= RETRY_MAX_DELAY_MS ? { providerRetryAfterMs: wait } : undefined,\n )\n }\n\n /**\n * Record a rejection against one key. `rate-limit` (429) marks the key\n * exhausted with an unknown reset (probed lazily at the next resolution\n * once every account is marked); `invalid-credential` (401) disables the\n * key until the stored credential changes.\n */\n markRejected(apiKey: string, rejection: AccountRejection): void {\n if (rejection === 'invalid-credential') {\n this.states.set(apiKey, { kind: 'disabled', reason: 'invalid API key (401)', until: 0 })\n } else {\n this.states.set(apiKey, { kind: 'unknown', reason: 'rate limited (429)', until: 0 })\n }\n }\n\n /** One account's key: literal → credential seam → auth file (default slot). */\n private async resolveSlotKey(slot: CommandCodeAccountSlot): Promise<string | undefined> {\n if (slot.literal !== undefined && slot.literal !== '') return slot.literal\n if (slot.ref !== undefined) {\n const hit = await this.deps.resolveRef(slot.ref)\n if (hit !== undefined && hit !== '') return hit\n }\n if (slot.allowAuthFile) {\n const fromFile = this.deps.authFileKey()\n if (fromFile !== undefined && fromFile !== '') return fromFile\n }\n return undefined\n }\n\n /** Hand out the chosen account's key. */\n private pick(account: ResolvedAccount): { key: string; slot: CommandCodeAccountSlot } {\n return { key: account.key, slot: account.slot }\n }\n}\n","/**\n * DeepSeek Harness LLM adapter for the Command Code Provider API.\n *\n * Ported from pi-commandcode-provider@0.5.1 (MIT). This is an unofficial,\n * community-maintained integration; you need your own Command Code account\n * and API key or subscription, and Command Code's terms apply.\n *\n * Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;\n * re-verified against command-code@1.39.2 — endpoints, request shape, and\n * stream events unchanged):\n * POST {apiBase}/alpha/generate\n * body: { config, memory, taste, skills, params: { model, messages, tools,\n * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }\n * SSE-ish JSONL events: text-delta | reasoning-start/delta/end | tool-call\n * | tool-result | finish | error\n * Model catalog: GET {apiBase}/provider/v1/models -> { object: 'list', data: [...] }\n *\n * The adapter is deliberately free of cordis/schemastery: it receives a\n * per-request options thunk and an API-key resolver from the plugin entry\n * (src/index.ts), so a settings change reaches the very next request.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { randomUUID } from 'node:crypto'\n\nimport type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\n\nimport {\n attributionHeaders,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\n ToolCallId,\n errorChain,\n resolveRetryPolicy,\n type ResolvedRetryPolicy,\n type ContentBlock,\n type FinishReason,\n type GenerateOptions,\n type LlmModelInfo,\n type LlmProviderInfo,\n type LlmResolvedModelInfo,\n type Message,\n type StreamChunk,\n type TokenUsage,\n} from '@deepseek-ai/dsh-llm'\nimport { RETRY_MAX_DELAY_MS } from './accounts.ts'\n\n// ---------------------------------------------------------------------------\n// Static capability snapshot (from the official command-code@1.39.2 bundled\n// model catalog, dist/cli.mjs). The Provider API does not expose reasoning\n// metadata; models omitted here let Command Code choose their reasoning\n// depth, matching the official CLI.\n// ---------------------------------------------------------------------------\n\nexport const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>> = {\n // Re-verified against the authoritative command-code@1.39.2 bundled model\n // table (dist/cli.mjs, the provider effort map): exactly these models carry\n // selectable efforts. Models marked 'reasoning:!0' without efforts\n // (e.g. Kimi K3, MiniMax M3, Muse Spark 1.1, Tencent Hy3, GLM-5/5.1/5.2-Fast)\n // think automatically and are absent here - the CLI omits\n // 'reasoning_effort' for them, so the picker must not offer a selector. Do\n // NOT add entries from the OAuth provider tables (anthropic/openai) - only\n // the Provider-API table is authoritative for this plugin's route.\n // `stealth/ox-alpha` (['low', 'high', 'max']) was removed in\n // command-code@1.34.0 when its preview ended; its successor,\n // `z-ai/glm-5.3-flash`, ships the same effort set.\n // `tencent/hy4-preview` gained ['low', 'medium', 'high'] in\n // command-code@1.38.0 (it previously thought automatically with no\n // selectable levels).\n 'Qwen/Qwen3.8-Max': ['low', 'medium', 'xhigh'],\n 'Qwen/Qwen3.8-27B': ['low', 'medium', 'xhigh'],\n 'Qwen/Qwen3.8-Flash': ['low', 'medium', 'xhigh'],\n 'claude-fable-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-7': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-8': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-4-6': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n // `deepseek/deepseek-v4-flash-fast` joined in command-code@1.39.0\n // (\"Add DeepSeek V4 Flash Fast\"); 1.39.1 dropped `medium` for it, and\n // the 1.39.2 table ships ['low', 'high', 'max'].\n 'deepseek/deepseek-v4-flash-fast': ['low', 'high', 'max'],\n 'deepseek/deepseek-v4-flash': ['high', 'max'],\n 'deepseek/deepseek-v4-flash-vision-exp': ['high', 'max'],\n 'deepseek/deepseek-v4-pro': ['high', 'max'],\n 'google/gemini-3.1-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.6-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.7-flash': ['low', 'medium', 'high'],\n 'gpt-5.3-codex': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4-mini': ['low', 'medium', 'high'],\n 'gpt-5.5': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.6-luna': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-sol': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-terra': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'sakana/fugu-ultra': ['high', 'xhigh'],\n 'tencent/hy4-preview': ['low', 'medium', 'high'],\n 'xai/grok-4.5': ['low', 'medium', 'high'],\n 'xai/grok-4.6': ['low', 'medium', 'high', 'xhigh'],\n 'z-ai/glm-5.3-flash': ['low', 'high', 'max'],\n 'zai-org/GLM-5.2': ['high', 'max'],\n 'zai-org/GLM-5.3': ['low', 'high', 'max'],\n}\n\n/**\n * Models whose Capabilities include Vision, per the official Command Code\n * model registry (`https://commandcode.ai/docs/reference/cli/models`, generated\n * from the same registry as `cmd --list-models` / the `/model` picker).\n *\n * The Provider API does not expose modality metadata, so this snapshot is the\n * source of truth for image-input gating. Command Code's own CLI falls back to\n * a client-side VISION side-call for text-only models; this adapter does not\n * reproduce that interactive feature, so images sent to a model outside this\n * list are refused loudly (`UNSUPPORTED_CONTENT`) instead of being dropped or\n * sent to a model that cannot read them.\n *\n * Keep in sync with the official registry when new models ship (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_IMAGE_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Plus',\n 'Qwen/Qwen3.8-27B',\n 'Qwen/Qwen3.8-Flash',\n 'Qwen/Qwen3.8-Max',\n 'claude-fable-5',\n 'claude-haiku-4-5-20251001',\n 'claude-opus-4-7',\n 'claude-opus-4-8',\n 'claude-opus-5',\n 'claude-sonnet-4-6',\n 'claude-sonnet-5',\n 'deepseek/deepseek-v4-flash-vision-exp',\n 'google/gemini-3.1-flash-lite',\n 'google/gemini-3.5-flash',\n 'google/gemini-3.5-flash-lite',\n 'google/gemini-3.6-flash',\n 'google/gemini-3.7-flash',\n 'gpt-5.3-codex',\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.5',\n 'gpt-5.6-luna',\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n 'minimax/minimax-m3-free',\n 'moonshotai/Kimi-K2.5',\n 'moonshotai/Kimi-K2.6',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'moonshotai/Kimi-K3',\n 'sakana/fugu-ultra',\n 'stepfun/Step-3.7-Flash',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'xai/grok-4.5',\n 'xiaomi/mimo-v2.5',\n 'z-ai/glm-5.3-flash',\n])\n\n/**\n * Models the official CLI's model table (command-code@1.39.2) marks\n * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they\n * think automatically, with Command Code driving the depth. This is the\n * authoritative \"thinks, effort not adjustable\" set: `KNOWN_EFFORTS` (which\n * mirrors the CLI's effort map exactly) stays the sole source for selectable\n * effort levels, and this snapshot is not surfaced in the picker's compact\n * description — it exists for programmatic consumers.\n *\n * Source: the command-code@1.39.2 bundled model table (dist/cli.mjs),\n * cross-checked with https://commandcode.ai/docs/reference/cli/models.\n * (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it\n * selectable `['low', 'high', 'max']` efforts; the preview then ended in\n * 1.34.0, removing the model from the catalog entirely. `tencent/hy4-preview`\n * joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M\n * context, routed through OpenRouter — then gained selectable\n * `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to\n * `KNOWN_EFFORTS`.)\n * Keep in sync via the dsh-commandcode-upstream skill.\n */\nexport const KNOWN_THINKING_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Max-Preview',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Max',\n 'Qwen/Qwen3.7-Plus',\n 'minimax/minimax-m3-free',\n 'moonshotai/Kimi-K3',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'stepfun/Step-3.5-Flash',\n 'stepfun/Step-3.7-Flash',\n 'tencent/hy3-paid',\n 'nvidia/nemotron-3-ultra-550b-a55b',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'poolside/laguna-s-2.1-free',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n])\n\n/**\n * The minimum subscription plan a model is included in, per the official plan\n * pages (`/docs/plans/go`, `/docs/plans/goat`, `/docs/plans/pro`, `/docs/plans/max`\n * and `/docs/resources/pricing-limits`). Each plan's model list is a superset of\n * the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max. Models absent from every\n * plan list (Claude Opus/Fable, Fugu Ultra) are Provider-tier.\n *\n * The Provider API exposes no plan metadata, so this snapshot is the source of\n * truth for the picker's plan annotation — it answers \"which plan do I need to\n * actually use this model?\" at a glance. Plan labels use the official tier\n * names (`Go`, `GOAT`, `Pro`, `Provider`), with `Max` implying Provider.\n *\n * Keep in sync with the official plan pages when they change (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_PLANS: Readonly<Record<string, string>> = {\n // --- Go (42) ---\n 'MiniMaxAI/MiniMax-M2.5': 'go',\n 'MiniMaxAI/MiniMax-M2.7': 'go',\n 'MiniMaxAI/MiniMax-M3': 'go',\n 'Qwen/Qwen3.6-Max-Preview': 'go',\n 'Qwen/Qwen3.6-Plus': 'go',\n 'Qwen/Qwen3.7-Flash': 'go',\n 'Qwen/Qwen3.7-Max': 'go',\n 'Qwen/Qwen3.7-Plus': 'go',\n 'Qwen/Qwen3.8-27B': 'go',\n 'Qwen/Qwen3.8-Flash': 'go',\n 'Qwen/Qwen3.8-Max': 'go',\n // command-code@1.39.0 added DeepSeek V4 Flash Fast; it is a Go-tier model\n // alongside the rest of the DeepSeek V4 family.\n 'deepseek/deepseek-v4-flash-fast': 'go',\n 'deepseek/deepseek-v4-flash': 'go',\n 'deepseek/deepseek-v4-flash-vision-exp': 'go',\n 'deepseek/deepseek-v4-pro': 'go',\n 'gpt-5.6-luna': 'go',\n 'inclusionai/ling-3.0-flash-free': 'go',\n 'meta/muse-spark-1.2-contributor': 'go',\n 'minimax/minimax-m2.7-free': 'go',\n 'minimax/minimax-m3-free': 'go',\n 'moonshotai/Kimi-K2.5': 'go',\n 'moonshotai/Kimi-K2.6': 'go',\n 'moonshotai/Kimi-K2.7-Code': 'go',\n 'moonshotai/Kimi-K2.7-Code-Highspeed': 'go',\n 'moonshotai/Kimi-K3': 'go',\n 'nvidia/nemotron-3-ultra-550b-a55b': 'go',\n 'poolside/laguna-s-2.1-free': 'go',\n 'stepfun/Step-3.5-Flash': 'go',\n 'stepfun/Step-3.7-Flash': 'go',\n 'tencent/Hy3': 'go',\n 'tencent/hy3-paid': 'go',\n 'tencent/hy4-preview': 'go',\n 'thinkingmachines/inkling': 'go',\n 'thinkingmachines/inkling-small': 'go',\n 'xai/grok-4.5': 'go',\n 'xiaomi/mimo-v2.5': 'go',\n 'xiaomi/mimo-v2.5-pro': 'go',\n 'z-ai/glm-5.3-flash': 'go',\n 'zai-org/GLM-5': 'go',\n 'zai-org/GLM-5.1': 'go',\n 'zai-org/GLM-5.2': 'go',\n 'zai-org/GLM-5.2-Fast': 'go',\n 'zai-org/GLM-5.3': 'go',\n // --- GOAT (4 more) ---\n 'google/gemini-3.7-flash': 'goat',\n 'gpt-5.6-sol': 'goat',\n 'meta/muse-spark-1.2': 'goat',\n 'xai/grok-4.6': 'goat',\n // --- Pro (13 more) ---\n 'claude-haiku-4-5-20251001': 'pro',\n 'claude-sonnet-4-6': 'pro',\n 'claude-sonnet-5': 'pro',\n 'google/gemini-3.1-flash-lite': 'pro',\n 'google/gemini-3.5-flash': 'pro',\n 'google/gemini-3.5-flash-lite': 'pro',\n 'google/gemini-3.6-flash': 'pro',\n 'gpt-5.3-codex': 'pro',\n 'gpt-5.4': 'pro',\n 'gpt-5.4-mini': 'pro',\n 'gpt-5.5': 'pro',\n 'gpt-5.6-terra': 'pro',\n 'meta/muse-spark-1.1': 'pro',\n // --- Provider / Max (5) ---\n 'claude-fable-5': 'provider',\n 'claude-opus-4-7': 'provider',\n 'claude-opus-4-8': 'provider',\n 'claude-opus-5': 'provider',\n 'sakana/fugu-ultra': 'provider',\n}\n\n/** Official display labels for each plan tier. */\nexport const PLAN_LABELS: Readonly<Record<string, string>> = {\n go: 'Go',\n goat: 'GOAT',\n pro: 'Pro',\n provider: 'Provider',\n max: 'Max',\n}\n\n/**\n * Plan-tier sort weights, low to high. Models outside the snapshot (unknown\n * plans) sort after every known tier, keeping known models predictable.\n */\nexport const PLAN_ORDER: Readonly<Record<string, number>> = {\n go: 0,\n goat: 1,\n pro: 2,\n provider: 3,\n max: 4,\n}\n\n/**\n * Whether a model is free (requests cost no credits), per the pricing page's\n * deals (`KNOWN_DEALS` `free: true`). Free models lead the picker regardless\n * of tier — they are usable by every account, so they are the best default\n * candidates.\n */\nexport function isFreeModel(modelId: string): boolean {\n return KNOWN_DEALS[modelId]?.free === true\n}\n\n/**\n * Comparator for the model picker: free models first (zero credit cost, usable\n * by every account), then by plan tier (lowest first), then by model name,\n * then by id as a tiebreak. Models with no known plan sort last.\n */\nexport function compareByPlan(\n a: { id: string; name: string },\n b: { id: string; name: string },\n): number {\n const freeDelta = Number(isFreeModel(b.id)) - Number(isFreeModel(a.id))\n if (freeDelta !== 0) return freeDelta\n const pa = PLAN_ORDER[KNOWN_PLANS[a.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n const pb = PLAN_ORDER[KNOWN_PLANS[b.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n if (pa !== pb) return pa - pb\n const nameDiff = a.name.localeCompare(b.name)\n if (nameDiff !== 0) return nameDiff\n return a.id.localeCompare(b.id)\n}\n\n/**\n * Subscription plan table, synced from the official CLI bundle's plan maps\n * (`Nn`/`$n` in command-code@1.31.0 `dist/cli.mjs`, re-verified unchanged\n * against 1.32.2 where they appear as `Zn`/`er`): subscription `planId`\n * prefix → display name and the plan's monthly credit total. This is the\n * account's own subscription (from `/alpha/billing/subscriptions`) — distinct\n * from {@link KNOWN_PLANS}, which maps catalog models to their minimum tier.\n *\n * `tierWeight` is plugin-added (not from the CLI maps): the plan's rank on\n * the {@link PLAN_ORDER} scale, used by the picker's plan filter\n * ({@link modelVisibleInPlan}) to hide models above the account's tier.\n */\nexport const KNOWN_SUBSCRIPTION_PLANS: Readonly<Record<string, { name: string; monthlyCredits: number; tierWeight: number }>> = {\n 'individual-go': { name: 'Go', monthlyCredits: 10, tierWeight: 0 },\n 'individual-goat': { name: 'GOAT', monthlyCredits: 70, tierWeight: 1 },\n 'individual-pro': { name: 'Pro', monthlyCredits: 30, tierWeight: 2 },\n 'individual-pro-v1': { name: 'Pro', monthlyCredits: 80, tierWeight: 2 },\n 'individual-provider': { name: 'Provider', monthlyCredits: 15, tierWeight: 3 },\n 'individual-max': { name: 'Max', monthlyCredits: 150, tierWeight: 4 },\n 'individual-ultra': { name: 'Ultra', monthlyCredits: 300, tierWeight: 4 },\n 'teams-pro': { name: 'Teams Pro', monthlyCredits: 40, tierWeight: 2 },\n}\n\n/** Plan-id prefixes, longest first — the CLI's prefix-match order. */\nconst SUBSCRIPTION_PLAN_PREFIXES = Object.keys(KNOWN_SUBSCRIPTION_PLANS).sort((a, b) => b.length - a.length)\n\n/**\n * Resolve a subscription `planId` (e.g. `individual-pro-v1`) to its display\n * name and monthly credit total, mirroring the CLI's `getPlanInfo`:\n * normalize (lowercase, `_` → `-`), then longest-prefix match so\n * `individual-pro-v1` wins over `individual-pro`. Unknown ids return\n * `undefined`.\n */\nexport function subscriptionPlanInfo(planId: string): { name: string; monthlyCredits: number; tierWeight: number } | undefined {\n const normalized = planId.toLowerCase().replace(/_/g, '-')\n const prefix = SUBSCRIPTION_PLAN_PREFIXES.find((candidate) => normalized.startsWith(candidate))\n return prefix === undefined ? undefined : KNOWN_SUBSCRIPTION_PLANS[prefix]\n}\n\n/**\n * The billing facts the picker's plan filter needs, fetched by mirroring the\n * CLI's `createBilling` flow (whoami → orgId, then `/alpha/billing/subscriptions`\n * for the plan id and `/alpha/billing/credits` for the on-demand balances).\n */\nexport interface CommandCodeBillingAccess {\n /** Account plan tier weight on the {@link PLAN_ORDER} scale; undefined when the plan is unknown. */\n tierWeight: number | undefined\n /**\n * Purchased + free on-demand credit balance. The official access model\n * (`evaluateModelAccess` in the CLI) allows every model when the account\n * holds any on-demand credits — the plan gate only applies at zero balance.\n */\n onDemandCredits: number\n}\n\n/**\n * Whether the picker lists `modelId` for an account with the given billing\n * access. Fails open at every uncertainty: no billing data, an unknown plan,\n * or a model outside {@link KNOWN_PLANS} all keep the model visible — the\n * server remains the final gate (`403 MODEL_NOT_IN_PLAN`).\n */\nexport function modelVisibleInPlan(modelId: string, access: CommandCodeBillingAccess | undefined): boolean {\n if (access === undefined) return true\n if (access.onDemandCredits > 0) return true\n if (access.tierWeight === undefined) return true\n const tier = KNOWN_PLANS[modelId]\n if (tier === undefined) return true\n const weight = PLAN_ORDER[tier]\n if (weight === undefined) return true\n return weight <= access.tierWeight\n}\n\n/**\n * Active pricing deals per the official pricing page\n * (`/docs/resources/pricing-limits#deals`). Each entry records the model's\n * promotional label and — critically — when it expires, so the picker never\n * shows a stale discount after the plugin's snapshot has gone out of date.\n *\n * - `expiresAt` is an ISO timestamp. When it is in the past (checked at\n * render time against `Date.now()`), the deal label is hidden until the\n * snapshot is refreshed from the official page. `undefined` means\n * \"no expiry\" (permanent).\n * - `free` marks models whose requests cost no credits (Laguna S 2.1), shown\n * as a `FREE` badge; it degrades to a plain discount once the deal lapses.\n *\n * Keep in sync with the official pricing page when deals change (see the\n * dsh-commandcode-upstream skill).\n */\nexport interface KnownDeal {\n /** Promotional label, e.g. \"50% off\" or \"2× usage\". */\n label: string\n /** Deal end date (ISO). `undefined` = permanent / no expiry. */\n expiresAt?: string\n /** Model is free (requests cost no credits). */\n free?: boolean\n}\n\nexport const KNOWN_DEALS: Readonly<Record<string, KnownDeal>> = {\n // Gemini 3.7 Flash's 50% off deal was retired from the official pricing\n // page's #deals section (command-code@1.38.2 sync); the model now shows at\n // full price.\n 'MiniMaxAI/MiniMax-M3': { label: '50% off' },\n 'xiaomi/mimo-v2.5-pro': { label: '99% off' },\n 'xiaomi/mimo-v2.5': { label: '98% off' },\n // The MiniMax M3 / M2.7 FREE promo variants were retired in\n // command-code@1.39.2 (\"Retire MiniMax free models\"): the official CLI hides\n // them and the pricing page no longer lists them as free, so the free\n // entries that shipped through 1.38.2 (with a 2026-09-05 expiry) are removed\n // here rather than left to lapse on schedule. The paid MiniMax M3 / M2.7\n // rows keep their own rates.\n 'poolside/laguna-s-2.1-free': { label: 'FREE', free: true },\n}\n\n/**\n * Models with time-of-day (peak/off-peak) pricing, per the official pricing\n * page (`/docs/resources/pricing-limits`). Since 2026-08-16 16:00 UTC, DeepSeek\n * charges by the hour: peak hours are 01:00–04:00 and 06:00–10:00 UTC (7h/day,\n * full price); the other 17 hours are off-peak at half price. The V4 Flash\n * Vision (exp) variant (command-code@1.32.0) shares the V4 Flash windows and\n * peak prices ($0.44/$1.32) — each row's hover annotation states exactly 2×\n * that row's displayed off-peak prices. The picker shows the\n * *current* state as a compact\n * label (`Peak`/`Half`) matching the English noun style of the other markers\n * (`Image`, `FREE`), so a developer can tell at a glance whether calling the\n * model right now is cheap or expensive.\n *\n * Extraction caution: in the page's HTML each annotation div sits inside its\n * OWN row's container, immediately before the NEXT row starts — flattening\n * the page to text makes every annotation look like it belongs to the model\n * printed after it. Verify membership against the enclosing row and the 2×\n * price relation, not the flat-text neighbor.\n *\n * Keep in sync with the official pricing page when the model set or the peak\n * windows change (see the dsh-commandcode-upstream skill).\n */\nexport const KNOWN_PEAK_PRICING: ReadonlySet<string> = new Set([\n 'deepseek/deepseek-v4-pro',\n 'deepseek/deepseek-v4-flash',\n 'deepseek/deepseek-v4-flash-vision-exp',\n // Added in command-code@1.39.0: DeepSeek V4 Flash Fast shares the V4 Flash\n // peak windows and peak prices ($0.44 / $1.32 per the pricing page's\n // off-peak annotation).\n 'deepseek/deepseek-v4-flash-fast',\n])\n\n/** Peak hours (UTC, hour-of-day range end-exclusive): 01–03 and 06–09. */\nconst PEAK_HOUR_RANGES: ReadonlyArray<readonly [number, number]> = [\n [1, 4],\n [6, 10],\n]\n\n/**\n * Whether `now` (defaults to `Date.now()`) falls in a peak-pricing hour for\n * time-of-day-priced models. `undefined` for models outside the snapshot.\n */\nexport function peakPricingState(\n modelId: string,\n now: number = Date.now(),\n): 'peak' | 'off-peak' | undefined {\n if (!KNOWN_PEAK_PRICING.has(modelId)) return undefined\n const hour = new Date(now).getUTCHours()\n const inPeak = PEAK_HOUR_RANGES.some(([start, end]) => hour >= start && hour < end)\n return inPeak ? 'peak' : 'off-peak'\n}\n\n/**\n * Compact label for the current peak/off-peak state: `Peak` (full price) or\n * `Half` (off-peak, half price). These English nouns match the picker's other\n * markers (`Go`, `Image`, `FREE`), and since they appear only on time-of-day\n * priced models they double as a \"priced by the hour\" signal. Returns undefined\n * for models without time-of-day pricing.\n */\nexport function peakPricingLabel(\n modelId: string,\n now: number = Date.now(),\n): string | undefined {\n const state = peakPricingState(modelId, now)\n if (state === undefined) return undefined\n return state === 'peak' ? 'Peak' : 'Half'\n}\n\nexport const COMMAND_CODE_CLI_VERSION = '1.39.2'\nexport const DEFAULT_API_BASE = 'https://api.commandcode.ai'\nexport const DEFAULT_GENERATE_MAX_TOKENS = 64_000\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 65_536\nexport const MODELS_TIMEOUT_MS = 10_000\n/** How long the picker's plan-filter billing facts stay cached before refetching. */\nexport const BILLING_ACCESS_TTL_MS = 5 * 60_000\n\n/**\n * Subscription statuses the CLI treats as live (`Mr` in command-code's\n * cli.mjs): the plan gate applies only under one of these.\n */\nconst ACTIVE_SUBSCRIPTION_STATUSES: ReadonlySet<string> = new Set(['active', 'trialing', 'past_due'])\n/** Head-of-request timeout: how long to wait for the first response byte. */\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 60_000\n/** Stream idle timeout: a generation that stalls this long is a dead connection. */\nexport const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000\nconst MODEL_CACHE_VERSION = 1\n\n// ---------------------------------------------------------------------------\n// Small helpers (ported from converters.ts / models.ts)\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Official display label for a model's minimum plan, or undefined for models\n * outside the snapshot (e.g. future catalog additions).\n */\nexport function planLabel(modelId: string): string | undefined {\n const plan = KNOWN_PLANS[modelId]\n return plan === undefined ? undefined : PLAN_LABELS[plan]\n}\n\n/**\n * The active deal label for a model, or undefined when the model has no deal\n * or the deal has expired. Expiry is judged against `now` (defaults to\n * `Date.now()`), so a snapshot that has gone stale stops showing its discount\n * the moment the official end date passes — the user never believes a lapsed\n * deal is still live. Permanent deals (no `expiresAt`) never lapse.\n */\nexport function dealLabel(modelId: string, now: number = Date.now()): string | undefined {\n const deal = KNOWN_DEALS[modelId]\n if (deal === undefined) return undefined\n if (deal.expiresAt !== undefined && now >= Date.parse(deal.expiresAt)) return undefined\n return deal.label\n}\n\n/**\n * Compact human-readable context window, e.g. `1_000_000 -> \"1M\"`,\n * `256_000 -> \"256K\"`, `262_144 -> \"256K\"` (floor to the nearest K).\n * Returns undefined for unknown/absent sizes.\n */\nexport function formatContext(contextWindow: number | undefined): string | undefined {\n if (contextWindow === undefined || !Number.isFinite(contextWindow) || contextWindow <= 0) {\n return undefined\n }\n if (contextWindow >= 1_000_000) {\n const m = contextWindow / 1_000_000\n // Round to one decimal only when it adds information: 1_048_576 -> \"1M\",\n // 1_050_000 -> \"1.1M\".\n const rounded = Math.round(m * 10) / 10\n return `${Number.isInteger(rounded) ? rounded : rounded.toFixed(1)}M`\n }\n return `${Math.floor(contextWindow / 1_000)}K`\n}\n\n/**\n * Compact one-line summary for the model picker: plan tier, then any active\n * deal (discount or FREE), then the current peak/off-peak state (`Peak`/`Half`)\n * for time-of-day-priced models, then `Image` for Vision-capable models, then\n * the context window. Text-only models simply omit the Image marker — \"Text\n * only\" adds nothing the picker needs to show.\n */\nexport function capabilityDescription(\n modelId: string,\n contextWindow?: number,\n now: number = Date.now(),\n): string {\n const parts: string[] = []\n const plan = planLabel(modelId)\n if (plan !== undefined) parts.push(plan)\n const deal = dealLabel(modelId, now)\n if (deal !== undefined) parts.push(deal)\n const peak = peakPricingLabel(modelId, now)\n if (peak !== undefined) parts.push(peak)\n if (KNOWN_IMAGE_MODELS.has(modelId)) parts.push('Image')\n const ctx = formatContext(contextWindow)\n if (ctx !== undefined) parts.push(ctx)\n return parts.join(' · ')\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\nfunction booleanValue(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined\n}\n\n/** Parse a billing-period timestamp (ISO string or millis) into millis; 0 when absent/invalid. */\nfunction periodEndValue(value: unknown): number {\n const asNumber = numberValue(value)\n if (asNumber !== undefined) return asNumber\n const asString = stringValue(value)\n if (asString === undefined) return 0\n const parsed = Date.parse(asString)\n return Number.isNaN(parsed) ? 0 : parsed\n}\n\n/**\n * Terminal stream-error markers from the official CLI (`Xw` in command-code's\n * cli.mjs): these always mean \"retrying cannot succeed\", so the adapter must\n * not classify them as transient server errors.\n */\nconst TERMINAL_STREAM_ERROR_MARKERS = [\n 'premium_credits_exhausted',\n 'model_not_in_plan',\n 'insufficient credits',\n]\n\nfunction hasTerminalStreamMarker(message: string): boolean {\n const lower = message.toLowerCase()\n return TERMINAL_STREAM_ERROR_MARKERS.some((marker) => lower.includes(marker))\n}\n\nfunction recordOrEmpty(value: unknown): Record<string, unknown> {\n if (isRecord(value)) return value\n if (typeof value === 'string') {\n try {\n const parsed: unknown = JSON.parse(value)\n if (isRecord(parsed)) return parsed\n } catch {\n // Some providers stream incomplete JSON argument fragments.\n }\n }\n return {}\n}\n\nexport function projectSlugFromPath(pathName: string): string {\n const slug = pathName\n .toLowerCase()\n .replace(/^[a-z]:/i, '')\n .replace(/[^a-z0-9]+/g, '-')\n // Trim leading/trailing separators. This must stay linear: the classic\n // `/^-+|-+$/` form is ambiguous — on `a<200k dashes>b` the unanchored\n // `-+$` retries every start position, giving O(n^2) matching (CodeQL\n // js/polynomial-redos). The negative lookbehind `(?<!-)` restricts `-+$`\n // to the first dash of the trailing run, so only one start position is\n // tried. Verified empirically: ~14.5s -> ~0ms on a 200k-dash input.\n .replace(/^-+|(?<!-)-+$/g, '')\n return slug || 'project'\n}\n\nfunction parseStreamEventLine(line: string): unknown | undefined {\n let trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(':') || trimmed.startsWith('event:')) return undefined\n if (trimmed.startsWith('data:')) trimmed = trimmed.slice(5).trim()\n if (!trimmed || trimmed === '[DONE]') return undefined\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return undefined\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential fallback from the official Command Code CLI auth file. Used as\n// the last fallback by the plugin entry, so a user who already logged in with\n// `command-code login` can reuse that credential. Only the official CLI's own\n// file is read — pi/OMP auth files are intentionally not scanned, so their\n// credentials and formats cannot surprise this adapter.\n// ---------------------------------------------------------------------------\n\n/** Extract the key from the CLI's nested credential records (`command-code`). */\nfunction apiKeyFromCredentialRecord(value: unknown): string | undefined {\n if (!isRecord(value)) return undefined\n const type = stringValue(value.type)\n if (type === 'api') return stringValue(value.key)\n if (type === 'oauth') return stringValue(value.access)\n return stringValue(value.key) ?? stringValue(value.access)\n}\n\n/** Read a usable Command Code credential from the official CLI auth file. */\nexport function resolveAuthFileApiKey(): string | undefined {\n const authPath = join(homedir(), '.commandcode', 'auth.json')\n try {\n if (!existsSync(authPath)) return undefined\n const parsed: unknown = JSON.parse(readFileSync(authPath, 'utf-8'))\n if (!isRecord(parsed)) return undefined\n const direct = stringValue(parsed.apiKey) ?? stringValue(parsed.commandcode)\n if (direct) return direct\n const nested =\n apiKeyFromCredentialRecord(parsed.commandcode) ??\n apiKeyFromCredentialRecord(parsed['command-code'])\n return nested\n } catch {\n // Ignore malformed or unreadable auth file.\n }\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog discovery with on-disk cache fallback (ported from models.ts)\n// ---------------------------------------------------------------------------\n\ninterface CommandCodeModel {\n id: string\n name: string\n contextWindow: number\n maxTokens: number\n}\n\nfunction parseCatalogResponse(value: unknown): CommandCodeModel[] {\n if (!isRecord(value) || value.object !== 'list' || !Array.isArray(value.data)) {\n throw new LlmError('Unexpected Command Code models response shape', 'PROVIDER_PROTOCOL_ERROR')\n }\n const models: CommandCodeModel[] = []\n for (const entry of value.data) {\n if (!isRecord(entry)) continue\n const id = stringValue(entry.id)\n const name = stringValue(entry.name)\n const contextLength = numberValue(entry.context_length)\n if (!id || !name || !contextLength || contextLength <= 0) continue\n models.push({\n id,\n name,\n contextWindow: contextLength,\n maxTokens: Math.min(contextLength, DEFAULT_MAX_OUTPUT_TOKENS),\n })\n }\n if (models.length === 0) {\n throw new LlmError('Command Code returned an empty model catalog', 'PROVIDER_PROTOCOL_ERROR')\n }\n return models\n}\n\nasync function readModelsCache(cachePath: string): Promise<CommandCodeModel[]> {\n const parsed: unknown = JSON.parse(await readFile(cachePath, 'utf-8'))\n if (!isRecord(parsed) || parsed.version !== MODEL_CACHE_VERSION || !Array.isArray(parsed.models)) {\n throw new Error(`Invalid model cache at ${cachePath}`)\n }\n return parsed.models as CommandCodeModel[]\n}\n\nasync function writeModelsCache(cachePath: string, models: CommandCodeModel[]): Promise<void> {\n await mkdir(dirname(cachePath), { recursive: true })\n const tmp = `${cachePath}.${process.pid}.tmp`\n try {\n await writeFile(tmp, `${JSON.stringify({ version: MODEL_CACHE_VERSION, models }, null, 2)}\\n`, {\n encoding: 'utf-8',\n mode: 0o600,\n })\n await rename(tmp, cachePath)\n } finally {\n await rm(tmp, { force: true }).catch(() => undefined)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message conversion: harness Message[] -> Command Code wire messages.\n// Reasoning blocks are intentionally NOT replayed (matches the pi plugin and\n// the official CLI: prior private reasoning must not leak into later turns).\n// Only tool calls with a paired tool result are replayed.\n// ---------------------------------------------------------------------------\n\n/**\n * Collect the tool calls that have a paired tool result, plus each call's\n * name. The name map feeds the `toolName` of replayed tool results: some\n * backends (e.g. Google Gemini `functionResponse`) reject a result whose\n * function name is empty, so the real name must round-trip (the official\n * CLI does the same via its `tool_use_id -> toolName` map).\n */\nfunction pairedToolCalls(messages: readonly Message[]): {\n ids: Set<string>\n names: Map<string, string>\n} {\n const callIds = new Set<string>()\n const names = new Map<string, string>()\n const resultIds = new Set<string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (message.role === 'assistant' && block.type === 'tool-call') {\n callIds.add(block.id)\n names.set(block.id, block.name)\n }\n if (block.type === 'tool-result') resultIds.add(block.toolCallId)\n }\n }\n return { ids: new Set([...callIds].filter((id) => resultIds.has(id))), names }\n}\n\nfunction blockText(block: ContentBlock): string {\n return block.type === 'text' || block.type === 'reasoning' ? block.text : ''\n}\n\nfunction toolResultText(block: Extract<ContentBlock, { type: 'tool-result' }>): string {\n return block.content.map(blockText).filter(Boolean).join('\\n')\n}\n\nfunction hasImageContent(message: Message): boolean {\n const check = (blocks: readonly ContentBlock[]): boolean =>\n blocks.some(\n (b) => b.type === 'image' || (b.type === 'tool-result' && check(b.content)),\n )\n return check(message.content)\n}\n\n/**\n * Convert one image reference to the Command Code wire format, as the official\n * CLI does: `{ type: 'image', source: { type: 'base64', media_type, data } }`.\n * Bytes come from the durable attachment service; the media type is the one\n * verified at save time.\n */\nasync function imageToCommandCode(\n ref: ImageAttachmentRef,\n readImage: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<{ type: 'image'; source: { type: 'base64'; media_type: string; data: string } }> {\n const data = await readImage(ref)\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: ref.mediaType,\n data: Buffer.from(data).toString('base64'),\n },\n }\n}\n\nasync function messagesToCC(\n messages: readonly Message[],\n readImage?: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<unknown[]> {\n const out: unknown[] = []\n const { ids: paired, names: toolNames } = pairedToolCalls(messages)\n\n for (const message of messages) {\n if (message.role === 'system') continue // folded into params.system by the caller\n\n if (message.role === 'user' && message.source.kind !== 'tool') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') parts.push({ type: 'text', text: block.text })\n if (block.type === 'image') {\n // The caller (stream) has already gated image input on model\n // capability and attachment-service availability, so reaching this\n // branch with no resolver is an internal contract violation.\n if (!readImage) {\n throw new LlmError(\n 'Image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n parts.push(await imageToCommandCode(block.attachment, readImage))\n }\n }\n out.push({ role: 'user', content: parts })\n continue\n }\n\n if (message.role === 'assistant') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') {\n parts.push({ type: 'text', text: block.text })\n } else if (block.type === 'tool-call' && paired.has(block.id)) {\n parts.push({\n type: 'tool-call',\n toolCallId: block.id,\n toolName: block.name,\n input: recordOrEmpty(block.arguments),\n })\n }\n // reasoning blocks: skipped by design (see header comment)\n }\n if (parts.length > 0) out.push({ role: 'assistant', content: parts })\n continue\n }\n\n // tool-result message (user role, single tool-result block)\n if (message.role === 'user' && message.source.kind === 'tool') {\n const block = message.content[0]\n if (!block || block.type !== 'tool-result' || !paired.has(block.toolCallId)) continue\n out.push({\n role: 'tool',\n content: [\n {\n type: 'tool-result',\n toolCallId: block.toolCallId,\n // `paired` guarantees a call with this id exists, so the map\n // always hits; `|| 'unknown'` also guards an empty call name\n // (matches the official CLI's `?? \"unknown\"` fallback).\n toolName: toolNames.get(block.toolCallId) || 'unknown',\n output: block.isError\n ? { type: 'error-text', value: toolResultText(block) }\n : { type: 'text', value: toolResultText(block) },\n },\n ],\n })\n }\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Adapter\n// ---------------------------------------------------------------------------\n/** Connection facts resolved fresh per request by the plugin entry. */\nexport interface CommandCodeConnectionOptions {\n /** API base; the Provider API lives under it (`/alpha/generate`, `/provider/v1/models`). */\n apiBase: string\n /** Working directory reported to the API (project slug, config block). */\n workingDir: string\n /** Model catalog cache path. */\n modelsCachePath: string\n /**\n * Milliseconds to wait for generate response headers / first byte (default 60s).\n * Must not bound the subsequent body stream — long generations are gated by\n * {@link streamIdleTimeoutMs} and the caller AbortSignal instead.\n */\n requestTimeoutMs: number\n /** Milliseconds a stream may stall before it is treated as a dead connection (default 300s). */\n streamIdleTimeoutMs: number\n /**\n * Whether the picker hides models above the account's subscription tier\n * (default true). The filter fails open: unknown plan, billing-endpoint\n * failure, a positive on-demand credit balance, or an unmapped model all\n * keep the full catalog visible. Set false to always list every model.\n */\n filterModelsByPlan?: boolean\n}\n\n/**\n * Resolve the durable attachment service, or undefined when the host does not\n * provide one. Called lazily only when a request actually carries images, so a\n * text-only request never depends on the attachment seam.\n */\nexport type ResolveAttachments = () => AttachmentStore | undefined\n\n/** Everything the adapter needs beyond the request itself. */\nexport interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** Resolve the current connection facts (fresh per request, settings-aware). */\n options: () => C\n /**\n * Resolve a usable API key for the given connection facts and the request's\n * model id, or throw `MISSING_CREDENTIAL`. The model is optional: hosts\n * without model-aware routing ignore it.\n */\n resolveApiKey: (connection: C, model?: string) => Promise<string>\n /**\n * Multi-account rotation hook: the request sent with `rejectedKey` was\n * refused with 429 (`rate-limit`) or 401 (`invalid-credential`) before\n * any response body streamed. The host marks that key and returns the next\n * account's key to retry with, or `undefined` to surface the failure.\n * Only pre-stream rejections rotate — a mid-stream failure never replays a\n * partially consumed generation against another account.\n */\n rotateApiKey?: (rejectedKey: string, rejection: 'rate-limit' | 'invalid-credential', connection: C, model?: string) => Promise<string | undefined>\n /** HTTP transport override (tests); defaults to the global `fetch`. */\n fetchImpl?: typeof fetch\n /** Resolve the optional durable attachment service for image input (tests); defaults to none. */\n resolveAttachments?: ResolveAttachments\n}\n\n/** Account identity from `/alpha/whoami`. */\nexport interface CommandCodeAccount {\n id: string\n name: string\n userName: string\n}\n\n/** Usage summary from `/alpha/usage/summary`. */\nexport interface CommandCodeUsage {\n totalCount: number\n totalCost: number\n successRate: number\n completedCount: number\n failedCount: number\n totalTokensIn: number\n totalTokensOut: number\n totalCredits: number\n periodBasis: string\n}\n\n/** Credit/limit state from `/alpha/billing/credits`. */\nexport interface CommandCodeCredits {\n monthlyCredits: number\n purchasedCredits: number\n freeCredits: number\n /** Five-hour rolling window limits. */\n fiveHour: { used: number; cap: number; exceeded: boolean; resetAt: number }\n /** Weekly window limits. */\n weekly: { used: number; cap: number; exceeded: boolean; resetAt: number }\n}\n\n/** Subscription plan state from `/alpha/billing/subscriptions`. */\nexport interface CommandCodePlan {\n /** Raw subscription plan id (e.g. `individual-pro`); empty when unreported. */\n planId: string\n /** Display name (e.g. `Pro`); falls back to the raw id for unknown plans. */\n name: string\n /** Raw subscription status (`active`, `trialing`, `past_due`, …); empty when unreported. */\n status: string\n /** The plan's monthly credit total per {@link KNOWN_SUBSCRIPTION_PLANS}; null for unknown plans. */\n monthlyCredits: number | null\n /** Billing period end in millis; 0 when the endpoint did not report one. */\n currentPeriodEnd: number\n}\n\n/**\n * Why every account endpoint failed at once (the report then carries no data\n * at all, so the degraded per-endpoint view would hide the root cause behind\n * a generic \"partial data\" note). Undefined for partial failures.\n */\nexport type UsageBlockReason = 'invalid-key' | 'service-unavailable' | 'network'\n\n/** Account endpoints fetched by one `getUsage()` run (see the classification there). */\nconst USAGE_ENDPOINT_COUNT = 4\n\n/** Everything the usage endpoints report, fetched together. */\nexport interface CommandCodeUsageReport {\n account?: CommandCodeAccount\n usage?: CommandCodeUsage\n credits?: CommandCodeCredits\n plan?: CommandCodePlan\n /** Endpoint failures degrade the report instead of failing it. */\n failures: string[]\n /**\n * The single reason every endpoint failed, when they all did: `invalid-key`\n * (every call rejected with 401 — the stored key is wrong or expired),\n * `service-unavailable` (every call answered 5xx), or `network` (no HTTP\n * response at all). Undefined when any endpoint succeeded.\n */\n blocked?: UsageBlockReason\n}\n\nexport class CommandCodeAdapter<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> extends LlmAdapter {\n private catalog: CommandCodeModel[] = []\n private readonly fetchImpl: typeof fetch\n private readonly resolveAttachments: ResolveAttachments | undefined\n // Billing facts are per account: with a multi-account pool each key has its\n // own subscription tier, so the cache and the in-flight dedupe are keyed by\n // the resolved API key (process-local only, never logged).\n private readonly billingAccess = new Map<string, { value: CommandCodeBillingAccess | undefined; at: number }>()\n private readonly billingAccessInflight = new Map<string, Promise<CommandCodeBillingAccess | undefined>>()\n\n constructor(private readonly deps: CommandCodeAdapterDeps<C>) {\n super()\n this.fetchImpl = deps.fetchImpl ?? fetch\n this.resolveAttachments = deps.resolveAttachments\n }\n\n /**\n * Display metadata for the picker's provider group header. The base class\n * returns the raw route id (`commandcode`, all lowercase) as the name, which\n * is what the model selector shows as this group's sticky title; return the\n * proper display name instead, matching the Models settings page card (the\n * configurable-provider `displayName`). The id must stay equal to the route.\n */\n override providerInfo(provider: string): LlmProviderInfo {\n return { id: provider, name: 'Command Code' }\n }\n\n /**\n * Near-unbounded retry for transient failures only (`mode: 'normal'` with\n * an explicit 1000-attempt cap — opencode-style persistence without the\n * unbounded loop): `RATE_LIMIT`/`SERVER`/`TIMEOUT`/`TRANSPORT`/\n * `EMPTY_RESPONSE` retry up to 1000 times with waits doubling from 500 ms\n * and capping at 15 minutes (±10% jitter), so an exhausted 5-hour window\n * recovers in-session instead of failing after two tries. Permanent\n * failures (an invalid key's `INVALID_CREDENTIAL`, `UNSUPPORTED_CONTENT`,\n * plan rejections) are absent from the whitelist and surface immediately\n * instead of looping. Waits the pool/adapter attach as\n * `providerRetryAfterMs` are honored verbatim at or below the 15-minute\n * cap and never attached above it (in normal mode a longer attached wait\n * makes the executor abandon the retry outright — see RETRY_MAX_DELAY_MS).\n *\n * Captured once at route registration (dsh-llm snapshots this value), so a\n * future config knob for it would apply on profile restart, not per request.\n */\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return resolveRetryPolicy(\n {\n mode: 'normal',\n maxRetries: 1000,\n retryableCodes: ['EMPTY_RESPONSE', 'RATE_LIMIT', 'SERVER', 'TIMEOUT', 'TRANSPORT'],\n backoff: { initialDelayMs: 500, maxDelayMs: RETRY_MAX_DELAY_MS, jitterRatio: 0.1 },\n },\n 'llm-commandcode: retryPolicy',\n )\n }\n\n /** Refresh the catalog (live fetch, cache fallback) and return it. */\n private async loadCatalog(signal?: AbortSignal): Promise<CommandCodeModel[]> {\n const { apiBase, modelsCachePath } = this.deps.options()\n try {\n const response = await this.fetchImpl(`${apiBase}/provider/v1/models`, {\n headers: { accept: 'application/json', ...attributionHeaders() },\n signal: signal ?? AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n throw new Error(`models endpoint returned ${response.status}`)\n }\n this.catalog = parseCatalogResponse(await response.json())\n await writeModelsCache(modelsCachePath, this.catalog).catch(() => undefined)\n } catch (error) {\n if (signal?.aborted) throw error\n // A catalog refresh failure is a degradation, not a request failure:\n // fall back to the last successful catalog on disk (or the in-memory\n // one from an earlier successful load). The adapter still serves any\n // model the user names; only the advisory selector loses entries.\n this.catalog = await readModelsCache(modelsCachePath).catch(() => this.catalog)\n }\n return this.catalog\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n const catalog = await this.loadCatalog()\n // Plan filter: hide models above the account's subscription tier. Fails\n // open — a billing-fetch problem, an unknown plan, or a positive\n // on-demand balance all keep the full catalog visible, and the server\n // remains the final gate (403 MODEL_NOT_IN_PLAN). The catalog itself is\n // never filtered: resolveModel still serves every model.\n const access = this.deps.options().filterModelsByPlan === false\n ? undefined\n : await this.loadBillingAccess()\n return catalog\n .filter((model) => modelVisibleInPlan(model.id, access))\n .map((model) => {\n const vision = KNOWN_IMAGE_MODELS.has(model.id)\n return {\n provider,\n id: model.id,\n name: `${model.name} (CC)`,\n // The picker renders `description` under the model name: plan tier,\n // active deal, Image marker for Vision models, and context window.\n description: capabilityDescription(model.id, model.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n }\n })\n // The picker renders rows in the order returned: sort by plan tier\n // (Go first, … Provider last) so the models a Go-plan user can actually\n // use lead the list, then alphabetically within each tier.\n .sort(compareByPlan)\n }\n\n override async resolveModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<LlmResolvedModelInfo> {\n const entry =\n this.catalog.find((m) => m.id === model) ??\n (await this.loadCatalog(signal)).find((m) => m.id === model)\n\n const efforts = KNOWN_EFFORTS[model]\n const vision = KNOWN_IMAGE_MODELS.has(model)\n return {\n provider,\n id: model,\n name: entry ? `${entry.name} (CC)` : model,\n description: capabilityDescription(model, entry?.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n ...(entry\n ? {\n context: { contextWindow: entry.contextWindow },\n defaultMaxTokens: Math.min(entry.maxTokens, DEFAULT_GENERATE_MAX_TOKENS),\n }\n : {}),\n // Omit `reasoning` entirely for models without known effort support:\n // the harness then treats the model as having no selectable efforts.\n ...(efforts\n ? {\n reasoning: {\n efforts: efforts.map((effort) => ({\n id: ReasoningEffortId(effort),\n name: effort,\n })),\n },\n }\n : {}),\n }\n }\n\n /** The headers every authenticated account endpoint shares. */\n private async accountHeaders(apiKey?: string): Promise<Record<string, string>> {\n const connection = this.deps.options()\n const key = apiKey ?? (await this.deps.resolveApiKey(connection))\n return {\n Authorization: `Bearer ${key}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n }\n }\n\n /**\n * The billing facts behind the picker's plan filter, cached for\n * {@link BILLING_ACCESS_TTL_MS} and shared across concurrent callers.\n * `undefined` means \"unknown — show everything\" (fail-open).\n */\n private async loadBillingAccess(): Promise<CommandCodeBillingAccess | undefined> {\n let apiKey: string\n try {\n apiKey = await this.deps.resolveApiKey(this.deps.options())\n } catch {\n return undefined\n }\n const cached = this.billingAccess.get(apiKey)\n if (cached !== undefined && Date.now() - cached.at < BILLING_ACCESS_TTL_MS) return cached.value\n const existing = this.billingAccessInflight.get(apiKey)\n if (existing !== undefined) return existing\n const inflight = this.fetchBillingAccess(apiKey)\n .then((value) => {\n this.billingAccess.set(apiKey, { value, at: Date.now() })\n return value\n })\n .finally(() => {\n this.billingAccessInflight.delete(apiKey)\n })\n this.billingAccessInflight.set(apiKey, inflight)\n return inflight\n }\n\n /**\n * The billing facts behind the picker's plan filter, mirroring the CLI's\n * `createBilling` flow: whoami yields the org id, then the subscriptions\n * and credits endpoints answer in parallel. The plan id is honored only\n * when the subscription reports an active-ish status (the CLI's rule); when\n * the subscriptions endpoint fails entirely, `credits.planId` is the\n * fallback (the CLI stamps plan identity from it too). Any failure resolves\n * to `undefined` (fail-open) rather than breaking the picker.\n */\n private async fetchBillingAccess(apiKey: string): Promise<CommandCodeBillingAccess | undefined> {\n try {\n const connection = this.deps.options()\n const headers = await this.accountHeaders(apiKey)\n const base = connection.apiBase\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n const response = await this.fetchImpl(`${base}${path}`, {\n headers,\n // A hung billing connection must not stall the picker forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) return undefined\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n }\n const whoami = await getJson('/alpha/whoami')\n const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\n const [subscription, credits] = await Promise.all([\n getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`),\n getJson('/alpha/billing/credits'),\n ])\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n if (subData === undefined && creditsData === undefined) return undefined\n let planId: string | undefined\n if (subData !== undefined) {\n const status = stringValue(subData.status)\n if (status !== undefined && ACTIVE_SUBSCRIPTION_STATUSES.has(status)) planId = stringValue(subData.planId)\n } else {\n planId = stringValue(creditsData?.planId)\n }\n return {\n tierWeight: planId === undefined ? undefined : subscriptionPlanInfo(planId)?.tierWeight,\n onDemandCredits: (numberValue(creditsData?.purchasedCredits) ?? 0) + (numberValue(creditsData?.freeCredits) ?? 0),\n }\n } catch {\n return undefined\n }\n }\n\n /**\n * Fetch account, usage, credit, and subscription state from the Command\n * Code account endpoints (`/alpha/whoami`, `/alpha/usage/summary`,\n * `/alpha/billing/credits`, `/alpha/billing/subscriptions`).\n * Each endpoint degrades independently: a failed one lands in `failures`\n * while the rest still report, so a transient outage never blanks the whole\n * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).\n * Pass `apiKey` to report on a specific account of a multi-account pool;\n * the default resolves the currently active account.\n */\n async getUsage(apiKey?: string): Promise<CommandCodeUsageReport> {\n const connection = this.deps.options()\n const base = connection.apiBase\n const headers = await this.accountHeaders(apiKey)\n const failures: string[] = []\n // HTTP status per failed endpoint (undefined for transport failures), in\n // failure order — the all-failed classification below reads it.\n const failedStatuses: Array<number | undefined> = []\n\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n try {\n const response = await this.fetchImpl(`${base}${path}`, {\n headers,\n // A hung account endpoint degrades into `failures` instead of\n // stalling the usage card / command forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n failures.push(`${path}: HTTP ${response.status}`)\n failedStatuses.push(response.status)\n return undefined\n }\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n } catch (error: unknown) {\n failures.push(`${path}: ${error instanceof Error ? error.message : String(error)}`)\n failedStatuses.push(undefined)\n return undefined\n }\n }\n\n const report: CommandCodeUsageReport = { failures }\n\n // whoami -> account identity (+ org id for the billing endpoints).\n const whoami = await getJson('/alpha/whoami')\n const whoamiData = whoami && isRecord(whoami.user) ? whoami.user : undefined\n if (whoamiData) {\n report.account = {\n id: stringValue(whoamiData.id) ?? '',\n name: stringValue(whoamiData.name) ?? '',\n userName: stringValue(whoamiData.userName) ?? '',\n }\n }\n const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\n\n // usage/summary -> totals.\n const usage = await getJson('/alpha/usage/summary')\n if (usage) {\n report.usage = {\n totalCount: numberValue(usage.totalCount) ?? 0,\n totalCost: numberValue(usage.totalCost) ?? 0,\n successRate: numberValue(usage.successRate) ?? 0,\n completedCount: numberValue(usage.completedCount) ?? 0,\n failedCount: numberValue(usage.failedCount) ?? 0,\n totalTokensIn: numberValue(usage.totalTokensIn) ?? 0,\n totalTokensOut: numberValue(usage.totalTokensOut) ?? 0,\n totalCredits: numberValue(usage.totalCredits) ?? 0,\n periodBasis: stringValue(usage.periodBasis) ?? 'billing-period',\n }\n }\n\n // billing/credits -> credit + window limits.\n const credits = await getJson('/alpha/billing/credits')\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n const windowLimits = credits && isRecord(credits.windowLimits) ? credits.windowLimits : undefined\n const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : undefined\n const weekly = windowLimits && isRecord(windowLimits.weekly) ? windowLimits.weekly : undefined\n if (creditsData || fiveHour || weekly) {\n report.credits = {\n monthlyCredits: numberValue(creditsData?.monthlyCredits) ?? 0,\n purchasedCredits: numberValue(creditsData?.purchasedCredits) ?? 0,\n freeCredits: numberValue(creditsData?.freeCredits) ?? 0,\n fiveHour: {\n used: numberValue(fiveHour?.used) ?? 0,\n cap: numberValue(fiveHour?.cap) ?? 0,\n exceeded: fiveHour?.exceeded === true,\n resetAt: numberValue(fiveHour?.resetAt) ?? 0,\n },\n weekly: {\n used: numberValue(weekly?.used) ?? 0,\n cap: numberValue(weekly?.cap) ?? 0,\n exceeded: weekly?.exceeded === true,\n resetAt: numberValue(weekly?.resetAt) ?? 0,\n },\n }\n }\n\n // billing/subscriptions -> plan identity + billing period. The credits\n // response may also carry a planId; it is the fallback when the\n // subscriptions endpoint fails. Mirrors the CLI: orgId rides as a query\n // param when whoami reported one.\n const subscription = await getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`)\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const planId = stringValue(subData?.planId) ?? stringValue(creditsData?.planId)\n if (subData !== undefined || planId !== undefined) {\n const info = planId === undefined ? undefined : subscriptionPlanInfo(planId)\n report.plan = {\n planId: planId ?? '',\n name: info?.name ?? planId ?? '',\n status: stringValue(subData?.status) ?? '',\n monthlyCredits: info?.monthlyCredits ?? null,\n currentPeriodEnd: periodEndValue(subData?.currentPeriodEnd),\n }\n }\n\n // Classify a TOTAL failure: when every endpoint failed with one class of\n // error, the degraded per-endpoint view would hide the root cause behind\n // a generic \"partial data\" note — name it instead. Four endpoints are\n // fetched (whoami, usage/summary, billing/credits, billing/subscriptions;\n // the last may carry an orgId query, so classification counts, not paths).\n if (failures.length === USAGE_ENDPOINT_COUNT) {\n const codes = failedStatuses.filter((status): status is number => status !== undefined)\n if (codes.length === USAGE_ENDPOINT_COUNT && codes.every((code) => code === 401)) {\n report.blocked = 'invalid-key'\n } else if (codes.length === USAGE_ENDPOINT_COUNT && codes.every((code) => code >= 500)) {\n report.blocked = 'service-unavailable'\n } else if (codes.length === 0) {\n report.blocked = 'network'\n }\n }\n\n return report\n }\n\n /**\n * Probe one account's five-hour window from `/alpha/billing/credits`. The\n * multi-account pool calls this when every account is marked exhausted: an\n * account whose window no longer reports `exceeded` is revived, and the\n * `resetAt` values feed the \"earliest reset\" error message. Returns\n * `undefined` when the probe itself failed (transport, non-200, or a\n * payload without window limits) — a failed probe never changes pool state.\n */\n async probeFiveHourWindow(apiKey: string): Promise<{ exceeded: boolean; resetAt: number } | undefined> {\n try {\n const connection = this.deps.options()\n const response = await this.fetchImpl(`${connection.apiBase}/alpha/billing/credits`, {\n headers: await this.accountHeaders(apiKey),\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) return undefined\n const parsed: unknown = await response.json()\n if (!isRecord(parsed)) return undefined\n const windowLimits = isRecord(parsed.windowLimits) ? parsed.windowLimits : undefined\n const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : undefined\n if (fiveHour === undefined) return undefined\n return { exceeded: fiveHour.exceeded === true, resetAt: numberValue(fiveHour.resetAt) ?? 0 }\n } catch {\n return undefined\n }\n }\n\n async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n if (options.stop?.length) {\n // The Command Code wire format has no documented stop field; refuse\n // loudly instead of silently dropping a request field.\n throw new LlmError('Command Code adapter does not support stop sequences', 'UNSUPPORTED_OPTION')\n }\n const hasImages = options.messages.some(hasImageContent)\n // Per-call image byte resolver, set only when this request carries images.\n // Local, not an instance field: concurrent streams must never read each\n // other's resolver.\n let readImage: ((ref: ImageAttachmentRef) => Promise<Uint8Array>) | undefined\n if (hasImages) {\n // Model-capability gate: only models the official registry lists with\n // Vision accept images natively. Command Code's own CLI falls back to a\n // client-side VISION side-call for text-only models; this adapter does\n // not reproduce that interactive feature, so it refuses loudly instead\n // of sending bytes to a model that cannot read them.\n if (!KNOWN_IMAGE_MODELS.has(options.model)) {\n throw new LlmError(\n `Command Code model \"${options.model}\" does not support image input;`\n + ' switch to a Vision-capable model (see the model registry)',\n 'UNSUPPORTED_CONTENT',\n )\n }\n // Attachment seam: images arrive as durable references; resolving them\n // requires the host's attachment service.\n const attachments = this.resolveAttachments?.()\n if (attachments === undefined) {\n throw new LlmError(\n 'Command Code image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n readImage = (ref) => attachments.readImage(ref).then((stored) => stored.data)\n }\n\n const connection = this.deps.options()\n // The model id reaches key resolution so hosts with model→account routing\n // rules can pick the account that covers this model.\n let apiKey = await this.deps.resolveApiKey(connection, options.model)\n const entry = this.catalog.find((m) => m.id === options.model)\n const modelMax = entry?.maxTokens ?? DEFAULT_MAX_OUTPUT_TOKENS\n const maxTokens = Math.min(\n options.maxTokens ?? modelMax,\n modelMax,\n DEFAULT_GENERATE_MAX_TOKENS,\n )\n\n const effort = options.reasoningEffort as string | undefined\n const supported = KNOWN_EFFORTS[options.model]\n const reasoningEffort =\n effort && effort !== 'off' && supported?.includes(effort) ? effort : undefined\n\n const systemText = [\n options.system ?? '',\n ...options.messages\n .filter((m) => m.role === 'system')\n .map((m) => m.content.map(blockText).filter(Boolean).join('\\n')),\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const body = {\n config: {\n workingDir: connection.workingDir,\n date: new Date().toISOString().split('T')[0],\n environment: `${process.platform}-${process.arch}, Node.js ${process.version}`,\n structure: [],\n isGitRepo: false,\n currentBranch: '',\n mainBranch: '',\n gitStatus: '',\n recentCommits: [],\n },\n memory: null,\n taste: null,\n skills: null,\n params: {\n model: options.model,\n messages: await messagesToCC(options.messages, readImage),\n tools: (options.tools ?? []).map((tool) => ({\n type: 'function',\n name: tool.name,\n description: tool.description,\n input_schema: tool.parameters,\n })),\n system: systemText,\n max_tokens: maxTokens,\n temperature: options.temperature ?? 0.3,\n stream: true,\n ...(reasoningEffort ? { reasoning_effort: reasoningEffort } : {}),\n },\n threadId: randomUUID(),\n }\n\n // requestTimeoutMs must only bound the wait for response headers.\n // Passing AbortSignal.timeout() straight into fetch() also aborts a healthy\n // body after that duration, which cuts long reasoning/generation mid-stream\n // and surfaces as \"failed while reading: aborted due to timeout\". After\n // headers arrive, only the caller signal and streamIdleTimeoutMs may abort.\n //\n // One connect attempt per account key: a pre-stream 429/401 hands the key\n // to the multi-account rotation hook (when the host wired one) and retries\n // with the next account — the request body is account-independent and\n // nothing has streamed yet, so the switch is invisible to the caller.\n const connect = async (\n key: string,\n ): Promise<{ response: Response; cleanup: () => void } | { status: number; errText: string; retryAfterMs?: number }> => {\n const connectAbort = new AbortController()\n let connectTimedOut = false\n const connectTimer = setTimeout(() => {\n connectTimedOut = true\n connectAbort.abort(\n new DOMException(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`,\n 'TimeoutError',\n ),\n )\n }, connection.requestTimeoutMs)\n const onCallerAbort = () => {\n connectAbort.abort(options.signal?.reason)\n }\n if (options.signal) {\n if (options.signal.aborted) {\n onCallerAbort()\n } else {\n options.signal.addEventListener('abort', onCallerAbort, { once: true })\n }\n }\n // On success the caller-abort listener must outlive the connect phase\n // (it aborts a stalled body read), so the streaming tail calls cleanup;\n // every failure path cleans up before returning or throwing.\n const cleanup = () => {\n clearTimeout(connectTimer)\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n }\n\n let response: Response\n try {\n response = await this.fetchImpl(`${connection.apiBase}/alpha/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${key}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n 'x-project-slug': projectSlugFromPath(connection.workingDir),\n 'x-taste-learning': 'true',\n 'x-co-flag': 'false',\n ...attributionHeaders(),\n },\n body: JSON.stringify(body),\n signal: connectAbort.signal,\n })\n clearTimeout(connectTimer)\n } catch (error: unknown) {\n cleanup()\n if (options.signal?.aborted) {\n throw error\n }\n if (connectTimedOut || (error instanceof DOMException && error.name === 'TimeoutError')) {\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`\n + `: ${errorChain(error)}`\n + `;Command Code API 请求在 ${connection.requestTimeoutMs} 毫秒内未收到响应——通常是网络或代理问题,请检查后重试`,\n 'TIMEOUT',\n { cause: error },\n )\n }\n // fetch wraps every transport failure (DNS, refused connection, TLS,\n // proxy, reset) in a bare `TypeError: fetch failed` whose actionable\n // detail lives on `cause`. Include the full chain so the failure reason\n // shown in the web UI (which renders only the message, not `cause`)\n // names the real root cause instead of a generic wrapper.\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate failed: ${errorChain(error)}`\n + ';Command Code API 请求连接失败——通常是网络或代理问题,请检查网络或代理设置后重试',\n 'TRANSPORT',\n { cause: error },\n )\n }\n\n if (!response.ok) {\n const errText = await response.text().catch(() => '')\n cleanup()\n const retryAfterMs = parseRetryAfterMs(response.headers.get('retry-after'))\n // exactOptionalPropertyTypes: the key must be absent, not undefined.\n return retryAfterMs === undefined\n ? { status: response.status, errText }\n : { status: response.status, errText, retryAfterMs }\n }\n return { response, cleanup }\n }\n\n // Account rotation loop: the first attempt uses the pool's active key; a\n // pre-stream 429/401 rotates to the next account (at most one attempt per\n // distinct key, hard-capped so a misbehaving hook cannot loop forever).\n const tried = new Set<string>()\n let connected: { response: Response; cleanup: () => void } | undefined\n for (;;) {\n tried.add(apiKey)\n const attempt = await connect(apiKey)\n if ('response' in attempt) {\n connected = attempt\n break\n }\n const rotate = this.deps.rotateApiKey\n if (\n (attempt.status === 429 || attempt.status === 401)\n && rotate !== undefined\n && options.signal?.aborted !== true\n && tried.size < MAX_ACCOUNT_ROTATIONS\n ) {\n const next = await rotate(apiKey, attempt.status === 429 ? 'rate-limit' : 'invalid-credential', connection, options.model)\n if (next !== undefined && !tried.has(next)) {\n apiKey = next\n continue\n }\n }\n throw generateHttpError(attempt.status, attempt.errText, attempt.retryAfterMs)\n }\n const { response, cleanup } = connected\n if (!response.body) {\n cleanup()\n throw new LlmError('Command Code API returned no response body', 'PROVIDER_PROTOCOL_ERROR')\n }\n\n // --- SSE/JSONL event stream -> harness StreamChunk protocol ---\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n // Stream idle watchdog: a generation that stalls this long has a dead\n // connection (the API keeps the socket open between reasoning/text\n // bursts). The default (300s) is deliberately generous: frontier\n // reasoning models (xhigh/max effort) can legitimately stay silent for\n // minutes while thinking, and the official CLI sets no idle cap at all —\n // an aggressive cap turns long thinking into spurious TIMEOUTs and\n // retries. reader.cancel() unblocks a pending read(), which the loop then\n // turns into a TIMEOUT failure instead of hanging forever.\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n let idleFired = false\n const armIdle = () => {\n if (idleTimer !== undefined) clearTimeout(idleTimer)\n idleTimer = setTimeout(() => {\n idleFired = true\n void reader.cancel().catch(() => undefined)\n }, connection.streamIdleTimeoutMs)\n }\n const clearIdle = () => {\n if (idleTimer !== undefined) {\n clearTimeout(idleTimer)\n idleTimer = undefined\n }\n }\n\n // Block assembly state: at most one text block and one reasoning block\n // are open at a time (same assumption as the pi plugin).\n let nextIndex = 0\n let textIndex = -1\n let textContent = ''\n let reasoningIndex = -1\n let reasoningContent = ''\n let sawContent = false\n\n const closeText = function* (): Generator<StreamChunk> {\n if (textIndex < 0) return\n yield {\n type: 'block-end',\n index: textIndex,\n block: { type: 'text', text: textContent },\n }\n textIndex = -1\n textContent = ''\n }\n const closeReasoning = function* (): Generator<StreamChunk> {\n if (reasoningIndex < 0) return\n yield {\n type: 'block-end',\n index: reasoningIndex,\n block: { type: 'reasoning', text: reasoningContent },\n }\n reasoningIndex = -1\n reasoningContent = ''\n }\n\n const handleEvent = (event: unknown): StreamChunk[] => {\n const chunks: StreamChunk[] = []\n if (!isRecord(event)) return chunks\n\n switch (event.type) {\n case 'text-delta': {\n chunks.push(...closeReasoning())\n if (textIndex < 0) {\n textIndex = nextIndex++\n chunks.push({ type: 'block-start', index: textIndex, blockType: 'text' })\n }\n const delta = stringValue(event.text) ?? ''\n textContent += delta\n sawContent = true\n chunks.push({ type: 'text-delta', index: textIndex, text: delta })\n break\n }\n case 'reasoning-delta': {\n chunks.push(...closeText())\n if (reasoningIndex < 0) {\n reasoningIndex = nextIndex++\n chunks.push({ type: 'block-start', index: reasoningIndex, blockType: 'reasoning' })\n }\n const delta = stringValue(event.text) ?? ''\n reasoningContent += delta\n chunks.push({ type: 'reasoning-delta', index: reasoningIndex, text: delta })\n break\n }\n case 'reasoning-start':\n chunks.push(...closeText())\n break\n case 'reasoning-end':\n chunks.push(...closeReasoning())\n break\n case 'tool-call': {\n chunks.push(...closeText(), ...closeReasoning())\n const id = stringValue(event.toolCallId) ?? randomUUID()\n const name = stringValue(event.toolName) ?? ''\n const args = JSON.stringify(recordOrEmpty(event.input ?? event.args ?? event.arguments))\n const index = nextIndex++\n sawContent = true\n chunks.push(\n { type: 'block-start', index, blockType: 'tool-call' },\n { type: 'tool-call-delta', index, id: ToolCallId(id), name, argumentsDelta: args },\n {\n type: 'block-end',\n index,\n block: { type: 'tool-call', id: ToolCallId(id), name, arguments: args },\n },\n )\n break\n }\n case 'finish': {\n chunks.push(...closeText(), ...closeReasoning())\n const usage = isRecord(event.totalUsage) ? event.totalUsage : undefined\n if (usage) {\n const details = isRecord(usage.inputTokenDetails) ? usage.inputTokenDetails : undefined\n const totalInput = numberValue(usage.inputTokens) ?? 0\n const cacheRead = numberValue(details?.cacheReadTokens) ?? 0\n const cacheWrite = numberValue(details?.cacheWriteTokens) ?? 0\n // Harness TokenUsage counts are disjoint: uncached input only.\n const tokenUsage: TokenUsage = {\n inputTokens:\n numberValue(details?.noCacheTokens) ?? Math.max(0, totalInput - cacheRead - cacheWrite),\n outputTokens: numberValue(usage.outputTokens) ?? 0,\n cacheReadTokens: cacheRead,\n cacheWriteTokens: cacheWrite,\n }\n chunks.push({ type: 'usage', usage: tokenUsage })\n }\n chunks.push({ type: 'finish', reason: mapFinishReason(event.finishReason) })\n break\n }\n case 'error': {\n // Mirror the official CLI's stream-error classification\n // (readStreamErrorEvent + isStreamErrorRetryable in command-code's\n // cli.mjs): a stream error that is explicitly non-retryable, carries\n // a terminal marker (quota/plan/credits), or reports a non-retryable\n // HTTP status is a hard failure; anything else is a transient\n // mid-stream drop that the harness's default retry policy should\n // retry (SERVER is in the default retryable set, PROVIDER_STREAM_ERROR\n // is not). Without this, a server-side blip that the official CLI\n // silently recovers from fails the whole turn.\n const err = isRecord(event.error) ? event.error : undefined\n const detail = isRecord(event.error)\n ? (stringValue(event.error.message) ?? JSON.stringify(event.error))\n : (stringValue(event.error) ?? stringValue(event.message) ?? 'Stream error')\n const statusCode = err ? numberValue(err.statusCode) : undefined\n const isRetryable = err ? booleanValue(err.isRetryable) : undefined\n const retryableStatus = statusCode !== undefined && (statusCode === 429 || statusCode >= 500)\n const terminal = hasTerminalStreamMarker(detail)\n const retryable = isRetryable === true\n || (statusCode !== undefined ? retryableStatus : (isRetryable !== false && !terminal))\n if (!retryable) {\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'PROVIDER_STREAM_ERROR',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'SERVER',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n }\n return chunks\n }\n\n try {\n let finished = false\n for (;;) {\n let read: ReadableStreamReadResult<Uint8Array>\n armIdle()\n try {\n read = await reader.read()\n } catch (error: unknown) {\n // A mid-stream transport failure (connection reset, TLS teardown)\n // surfaces here. Caller cancellation propagates as-is.\n if (options.signal?.aborted) throw error\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} failed while reading: ${errorChain(error)}`\n + ';Command Code API 流式响应中途断开——网络波动所致,重试通常可恢复',\n 'TRANSPORT',\n { cause: error },\n )\n } finally {\n clearIdle()\n }\n const { done, value } = read\n if (done) {\n // The idle watchdog cancels the reader to unblock a stalled read;\n // cancel() resolves a pending read() as done, so a done here after\n // the watchdog fired is a timeout, not a normal stream end.\n if (idleFired) {\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} was idle for ${connection.streamIdleTimeoutMs}ms`\n + ' (no events) and was treated as a dead connection'\n + `;Command Code API 流式响应已 ${connection.streamIdleTimeoutMs} 毫秒无任何事件,被判定为死连接——长思考模型可在设置中调大流空闲超时`,\n 'TIMEOUT',\n )\n }\n if (buffer.trim()) for (const chunk of handleEvent(parseStreamEventLine(buffer))) yield chunk\n break\n }\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n const chunks = handleEvent(parseStreamEventLine(line))\n for (const chunk of chunks) {\n yield chunk\n if (chunk.type === 'finish') finished = true\n }\n }\n if (finished) break\n }\n if (!finished) {\n // Stream ended without a finish event: close open blocks and\n // terminate according to the adapter contract (usage, then finish).\n yield* closeText()\n yield* closeReasoning()\n if (!sawContent) {\n throw new LlmError('Command Code returned an empty response;Command Code 返回了空响应,重试通常可恢复', 'EMPTY_RESPONSE')\n }\n yield { type: 'finish', reason: { kind: 'stop' } }\n }\n } finally {\n clearIdle()\n cleanup()\n await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n }\n}\n\n/** Hard cap on account rotations within one request (one attempt per distinct key). */\nconst MAX_ACCOUNT_ROTATIONS = 16\n\n/**\n * Map a pre-stream generate HTTP failure onto a stable LlmError. Command\n * Code folds several business rejections into 403 (plan limits, CLI version,\n * model access): prefer the machine-readable `error.code` when present; the\n * status alone cannot distinguish them. A 429's `Retry-After` rides along as\n * `providerRetryAfterMs` so dsh-llm-retry can wait exactly that long instead\n * of guessing at the backoff cadence — capped at RETRY_MAX_DELAY_MS, because\n * in normal mode a longer attached wait makes the executor abandon the retry\n * outright instead of falling back to local backoff.\n */\nfunction generateHttpError(status: number, errText: string, retryAfterMs?: number): LlmError {\n let providerCode: string | undefined\n try {\n const parsed: unknown = JSON.parse(errText)\n if (isRecord(parsed) && isRecord(parsed.error)) {\n providerCode = stringValue(parsed.error.code)\n }\n } catch {\n // Plain-text bodies: rely on the status mapping below.\n }\n const detail = providerCode ?? `HTTP ${status}`\n if (status === 401) {\n // An invalid or missing credential is a config problem, not a\n // transport failure: retrying it identically cannot succeed. Bilingual —\n // the harness UI renders this message verbatim in its retry chrome.\n return new LlmError(\n `Command Code API error 401 (${detail}): the API key is missing or invalid — check the`\n + ' key stored for COMMANDCODE_API_KEY (Models page) or the auth file'\n + ';Command Code API 返回 401:API 密钥缺失或无效——请在设置页检查 COMMANDCODE_API_KEY 存储的密钥,或检查 auth 文件',\n 'INVALID_CREDENTIAL',\n { status: 401 },\n )\n }\n return new LlmError(\n `Command Code API error ${status}${detail === `HTTP ${status}` ? '' : ` (${detail})`}: ${errText.slice(0, 500)}`,\n status === 429 ? 'RATE_LIMIT' : 'PROVIDER_HTTP_ERROR',\n {\n status,\n ...(retryAfterMs !== undefined && retryAfterMs > 0 && retryAfterMs <= RETRY_MAX_DELAY_MS\n ? { providerRetryAfterMs: retryAfterMs }\n : {}),\n },\n )\n}\n\n/**\n * Parse an HTTP `Retry-After` value (delay-seconds or an HTTP-date) into\n * milliseconds; undefined when absent or unparseable. An HTTP-date in the\n * past yields 0, which the caller drops (LlmError wants a positive delay).\n * A delay-seconds value whose millisecond product is not finite (e.g. `1e308`)\n * also yields undefined: LlmError validates its options and would otherwise\n * replace the provider failure with an internal construction error.\n */\nfunction parseRetryAfterMs(value: string | null | undefined, now = Date.now()): number | undefined {\n if (value === undefined || value === null) return undefined\n const trimmed = value.trim()\n if (trimmed === '') return undefined\n const seconds = Number(trimmed)\n if (Number.isFinite(seconds) && seconds >= 0) {\n const ms = seconds * 1000\n return Number.isFinite(ms) ? Math.round(ms) : undefined\n }\n const date = Date.parse(trimmed)\n if (!Number.isNaN(date)) return Math.max(0, date - now)\n return undefined\n}\n\nfunction mapFinishReason(reason: unknown): FinishReason {\n if (reason === 'tool-calls') return { kind: 'tool-calls' }\n if (\n reason === 'length' ||\n reason === 'max_tokens' ||\n reason === 'max-tokens' ||\n reason === 'max_output_tokens'\n ) {\n return { kind: 'max-tokens' }\n }\n return { kind: 'stop' }\n}\n","/**\n * Locale copy for the `/commandcode` usage command and the friendly\n * image-gate error rewrite. Distinct from `./client/locales.ts` (the\n * settings-page namespace `settings.commandcode`): the command runs on the\n * Host and has no access to the client's `ctx.locale`, so the dictionaries\n * are exposed as plain constants for direct lookup; the resolver lives in\n * `pickCommandLocale()`. The image-gate wrapper also lives on the client\n * but is reached from a non-React path that has no `t` in scope, so the\n * same dictionaries serve both surfaces.\n *\n * zh is the source of truth for the key set; en must carry the exact same\n * keys — a mismatch is a compile error at the lookup site.\n */\n\n/** Active locale id recognized by the command and the image-gate wrapper. */\nexport type LocaleId = 'zh' | 'en'\n\n/** Dictionary keys used by the `/commandcode` command and the image-gate wrapper. */\nexport type CommandCodeCommandKey =\n | 'title' // top heading of a single-account report\n | 'accountTitle' // per-account heading in the multi-account view\n | 'accountSeparator' // rule between accounts in the multi-account view\n | 'activeBadge' // \"currently serving\" badge\n | 'invalidCredentialBadge' // mark for an account whose key is invalid\n | 'cooldownBadge' // mark for an account in rate-limit cooldown\n | 'rateLimitBadge' // mark when the pool has marked a key rate-limited\n | 'unconfigured' // one-account row when the slot has no key\n | 'blockedInvalidKey' // top-of-report block when the whole account is 401\n | 'blockedServiceUnavailable' // 5xx\n | 'blockedNetwork' // network unreachable\n | 'planLine' // \" 📦 套餐 {name}{status}{period}\"\n | 'planPeriodSuffix' // \" · 账期截止 {date}\" / \" · period ends {date}\"\n | 'usageHeader' // \"── 请求 ─────...\"\n | 'requestsLine' // \" 💬 请求 {n} 次 / 失败 {f} 成功率 {r}%\"\n | 'costLine' // \" 💰 花费 {money} ({credits} credits)\"\n | 'tokensLine' // \" 🔤 Token {in} 入 / {out} 出\"\n | 'creditsHeader' // \"── 信用 ─────...\"\n | 'monthlyLine' // \" 💳 月额度 {monthly} (已购 {purchased} / 赠送 {free})\"\n | 'barLine' // \" └ {bar} {pct}%\"\n | 'windowsHeader' // \"── 窗口用量 ─────...\"\n | 'fiveHourLine' // \" ⏱ 5 小时 {used} / {cap}{warn}\"\n | 'weeklyLine' // \" 📅 每周 {used} / {cap}{warn}\"\n | 'windowBarLine' // \" └ {bar} 重置 {when}\"\n | 'exceededWarning' // the trailing \" ⚠️ 超限!\" / \" ⚠️ exceeded!\"\n | 'resetSuffix' // \"重置 {when}\" (the suffix after the bar)\n | 'partialFailures' // \"⚠️ 部分端点失败: {list}\"\n | 'noData' // \"(no data — check your API key)\"\n | 'errorText' // \"Could not fetch Command Code usage: {message}\"\n | 'imageGate' // image-gate rejection rewrite (with {model})\n\nexport const commandcodeCommand: Record<LocaleId, Record<CommandCodeCommandKey, string>> = {\n zh: {\n title: '📊 Command Code 用量{account}',\n accountTitle: '📊 {label}{badges}',\n accountSeparator: '────────────────────',\n activeBadge: ' ✅ 当前使用',\n invalidCredentialBadge: ' ⛔ 密钥无效',\n cooldownBadge: ' ⏳ 限额冷却中,重置 {when}',\n rateLimitBadge: ' ⏳ 已达限额(等待窗口探测)',\n unconfigured: ' (未配置 API 密钥)',\n blockedInvalidKey:\n '⛔ API 密钥无效或已过期 — 服务端拒绝了全部请求(401),请检查该账户的密钥配置',\n blockedServiceUnavailable:\n '⚠️ Command Code 服务暂时不可用(5xx),稍后重试',\n blockedNetwork:\n '⚠️ 无法连接 Command Code 服务 — 请检查网络或 API 地址',\n planLine: ' 📦 套餐 {name}{status}{period}',\n planPeriodSuffix: ' · 账期截止 {date}',\n usageHeader: '── 请求 ──────────────────────────────',\n requestsLine: ' 💬 请求 {n} 次 / 失败 {f} 成功率 {r}%',\n costLine: ' 💰 花费 {money} ({credits} credits)',\n tokensLine: ' 🔤 Token {in} 入 / {out} 出',\n creditsHeader: '── 信用 ──────────────────────────────',\n monthlyLine: ' 💳 月额度 {monthly} (已购 {purchased} / 赠送 {free})',\n barLine: ' └ {bar} {pct}%',\n windowsHeader: '── 窗口用量 ──────────────────────────',\n fiveHourLine: ' ⏱ 5 小时 {used} / {cap}{warn}',\n weeklyLine: ' 📅 每周 {used} / {cap}{warn}',\n windowBarLine: ' └ {bar} 重置 {when}',\n exceededWarning: ' ⚠️ 超限!',\n resetSuffix: '重置 {when}',\n partialFailures: '⚠️ 部分端点失败: {list}',\n noData: '(no data — check your API key)',\n errorText: 'Could not fetch Command Code usage: {message}',\n imageGate:\n '当前会话已包含图片,而模型 {model} 不支持图片输入;'\n + '请选择支持图片的模型,或先移除会话中的图片。',\n },\n en: {\n title: '📊 Command Code usage{account}',\n accountTitle: '📊 {label}{badges}',\n accountSeparator: '────────────────────',\n activeBadge: ' ✅ active',\n invalidCredentialBadge: ' ⛔ invalid key',\n cooldownBadge: ' ⏳ cooling down, resets {when}',\n rateLimitBadge: ' ⏳ rate-limited (waiting for window probe)',\n unconfigured: ' (no API key configured)',\n blockedInvalidKey:\n '⛔ API key invalid or expired — the server rejected every request (401); check the key configured for this account',\n blockedServiceUnavailable:\n '⚠️ Command Code service temporarily unavailable (5xx); try again later',\n blockedNetwork:\n '⚠️ could not reach the Command Code service — check your network or the API base setting',\n planLine: ' 📦 Plan {name}{status}{period}',\n planPeriodSuffix: ' · period ends {date}',\n usageHeader: '── Requests ──────────────────────────',\n requestsLine: ' 💬 Requests {n} / failed {f} success rate {r}%',\n costLine: ' 💰 Spend {money} ({credits} credits)',\n tokensLine: ' 🔤 Tokens {in} in / {out} out',\n creditsHeader: '── Credits ───────────────────────────',\n monthlyLine: ' 💳 Monthly {monthly} (purchased {purchased} / free {free})',\n barLine: ' └ {bar} {pct}%',\n windowsHeader: '── Window usage ──────────────────────',\n fiveHourLine: ' ⏱ 5-hour {used} / {cap}{warn}',\n weeklyLine: ' 📅 Weekly {used} / {cap}{warn}',\n windowBarLine: ' └ {bar} resets {when}',\n exceededWarning: ' ⚠️ exceeded!',\n resetSuffix: 'resets {when}',\n partialFailures: '⚠️ some endpoints failed: {list}',\n noData: '(no data — check your API key)',\n errorText: 'Could not fetch Command Code usage: {message}',\n imageGate:\n 'This session already contains images, and model {model} does not accept'\n + ' image input; please select an image-capable model, or remove the'\n + ' images from the session first.',\n },\n}\n\n/**\n * Resolve the active locale for a Host-side command run.\n *\n * Priority: explicit `override` (from `Config.lang`) → `LC_ALL` → `LANG` →\n * the conventional fallback (`'zh'`, matching the existing single-language\n * behavior so unconfigured deployments keep their current output).\n *\n * The values are matched on the leading tag only — `zh_CN.UTF-8`,\n * `zh-Hans`, `zh` all map to `'zh'`; everything starting with `en` maps to\n * `'en'`; anything else falls back to `'zh'` (a non-`en` shell that\n * already has Chinese in the terminal is the closest sensible default;\n * a Western shell that happens to be neither keeps the existing Chinese\n * output rather than swapping to half-translated English).\n */\nexport function pickCommandLocale(\n override: string | undefined,\n env: Readonly<Record<string, string | undefined>> = process.env as Record<string, string | undefined>,\n): LocaleId {\n if (override === 'zh' || override === 'en') return override\n const raw = env.LC_ALL ?? env.LANG ?? ''\n const tag = raw.toLowerCase().split(/[._-]/)[0] ?? ''\n if (tag === 'en') return 'en'\n return 'zh'\n}\n\n/** Look up a key in the active locale, with an internal en fallback. */\nexport function commandCopy(locale: LocaleId, key: CommandCodeCommandKey): string {\n return commandcodeCommand[locale][key] ?? commandcodeCommand.en[key] ?? key\n}\n","/**\n * `/commandcode` slash command — account usage dashboard.\n *\n * /commandcode show account, usage, and credit state\n * /commandcode status same as bare `/commandcode`\n *\n * Backed by the Command Code account endpoints the official CLI uses\n * (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`),\n * exposed through `CommandCodeAdapter.getUsage()`.\n *\n * The command is Host-side and has no access to the client's `ctx.locale`;\n * the active locale is resolved through `deps.getLocale()` (supplied by the\n * plugin entry from `Config.lang` and the shell's `LC_ALL`/`LANG`). All\n * user-facing copy lives in `./command-locales.ts`; the dictionaries\n * resolve to identical keys, so a missing or unknown locale falls back to\n * `en` rather than dropping text.\n *\n * @module dsh-commandcode-provider/commands\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n// Type-only import that loads the module augmentation (`ctx.commands`).\nimport type { CommandDefinition } from '@deepseek-ai/dsh-commands'\nimport { CommandCodeAdapter } from './adapter.ts'\nimport type { CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\nimport type { CommandCodeAccountUsage, CommandCodeAccountsReport } from './usage-wire.ts'\nimport { commandCopy, type LocaleId } from './command-locales.ts'\n\n/** Everything the command needs beyond the adapter itself. */\nexport interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage / listModels). */\n adapter: CommandCodeAdapter<C>\n /**\n * Multi-account report source (wired by the plugin entry). Absent in\n * programmatic setups, the command falls back to a single\n * `adapter.getUsage()` report.\n */\n reports?: () => Promise<CommandCodeAccountsReport>\n /**\n * Resolve the active locale for one command run. The plugin entry wires\n * this from `Config.lang` and the shell's `LC_ALL`/`LANG`. Absent in\n * programmatic setups (notably the existing test), the command renders\n * with the default locale (`'zh'`) — historically the only language the\n * command ever shipped in.\n */\n getLocale?: () => LocaleId\n}\n\n// ---------------------------------------------------------------------------\n// Number / time formatting (locale-independent; the locale only changes\n// the surrounding labels)\n// ---------------------------------------------------------------------------\n\n/** Format a dollar amount. */\nfunction money(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\n/** Format a dollar amount compactly (2 decimals). */\nfunction moneyShort(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\n/** Format a large token count compactly (1.9M style). */\nfunction tokensCompact(value: number): string {\n if (value >= 1e9) return `${(value / 1e9).toFixed(1)}B`\n if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`\n if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`\n return String(value)\n}\n\n/** Format a millis timestamp as a local date; `n/a` when unset. */\nfunction resetLabel(ms: number): string {\n if (ms <= 0) return 'n/a'\n return new Date(ms).toLocaleString()\n}\n\n/**\n * A 10-cell horizontal bar: `██████████` for 100%, `███░░░░░░░` for ~33%.\n * Handles caps of 0 (no limit) and out-of-range values.\n */\nfunction bar(used: number, cap: number): string {\n if (cap <= 0) return '—'\n const ratio = Math.max(0, Math.min(1, used / cap))\n const filled = Math.round(ratio * 10)\n return '█'.repeat(filled) + '░'.repeat(10 - filled)\n}\n\n// ---------------------------------------------------------------------------\n// Report rendering\n// ---------------------------------------------------------------------------\n\n/** Render one account's rotation mark / cooldown as a short badge. */\nfunction markLabel(entry: CommandCodeAccountUsage, locale: LocaleId): string {\n if (entry.mark === 'invalid-credential') return commandCopy(locale, 'invalidCredentialBadge')\n if (entry.cooldownUntil > 0) {\n return commandCopy(locale, 'cooldownBadge').replace('{when}', resetLabel(entry.cooldownUntil))\n }\n if (entry.mark === 'rate-limit') return commandCopy(locale, 'rateLimitBadge')\n return ''\n}\n\n/** Render the usage report as a structured, aligned, bar-chart text view. */\nfunction renderReport(report: CommandCodeUsageReport, locale: LocaleId, title?: string): string {\n const lines: string[] = []\n const account = report.account ? ` (${report.account.userName || report.account.name})` : ''\n\n lines.push(\n title ?? commandCopy(locale, 'title').replace('{account}', account),\n '',\n )\n\n // A total failure names its cause up front; the per-endpoint failure list\n // at the bottom would bury it.\n if (report.blocked === 'invalid-key') {\n lines.push(commandCopy(locale, 'blockedInvalidKey'), '')\n } else if (report.blocked === 'service-unavailable') {\n lines.push(commandCopy(locale, 'blockedServiceUnavailable'), '')\n } else if (report.blocked === 'network') {\n lines.push(commandCopy(locale, 'blockedNetwork'), '')\n }\n\n if (report.plan && report.plan.name !== '') {\n const p = report.plan\n const status = p.status !== '' && p.status !== 'active' ? ` (${p.status})` : ''\n const period = p.currentPeriodEnd > 0\n ? commandCopy(locale, 'planPeriodSuffix').replace('{date}', new Date(p.currentPeriodEnd).toLocaleDateString())\n : ''\n lines.push(commandCopy(locale, 'planLine')\n .replace('{name}', p.name)\n .replace('{status}', status)\n .replace('{period}', period), '')\n }\n\n if (report.usage) {\n const u = report.usage\n lines.push(\n commandCopy(locale, 'usageHeader'),\n commandCopy(locale, 'requestsLine')\n .replace('{n}', String(u.completedCount))\n .replace('{f}', String(u.failedCount))\n .replace('{r}', String(u.successRate)),\n commandCopy(locale, 'costLine')\n .replace('{money}', money(u.totalCost))\n .replace('{credits}', moneyShort(u.totalCredits)),\n commandCopy(locale, 'tokensLine')\n .replace('{in}', tokensCompact(u.totalTokensIn))\n .replace('{out}', tokensCompact(u.totalTokensOut)),\n '',\n )\n }\n\n if (report.credits) {\n const c = report.credits\n const monthlyPct = c.monthlyCredits > 0\n ? `${((c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits)) * 100).toFixed(0)}%`\n : '—'\n lines.push(\n commandCopy(locale, 'creditsHeader'),\n commandCopy(locale, 'monthlyLine')\n .replace('{monthly}', moneyShort(c.monthlyCredits))\n .replace('{purchased}', moneyShort(c.purchasedCredits))\n .replace('{free}', moneyShort(c.freeCredits)),\n commandCopy(locale, 'barLine')\n .replace('{bar}', bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits))\n .replace('{pct}', monthlyPct),\n '',\n commandCopy(locale, 'windowsHeader'),\n commandCopy(locale, 'fiveHourLine')\n .replace('{used}', moneyShort(c.fiveHour.used))\n .replace('{cap}', moneyShort(c.fiveHour.cap))\n .replace('{warn}', c.fiveHour.exceeded ? commandCopy(locale, 'exceededWarning') : ''),\n commandCopy(locale, 'windowBarLine')\n .replace('{bar}', bar(c.fiveHour.used, c.fiveHour.cap))\n .replace('{when}', resetLabel(c.fiveHour.resetAt)),\n commandCopy(locale, 'weeklyLine')\n .replace('{used}', moneyShort(c.weekly.used))\n .replace('{cap}', moneyShort(c.weekly.cap))\n .replace('{warn}', c.weekly.exceeded ? commandCopy(locale, 'exceededWarning') : ''),\n commandCopy(locale, 'windowBarLine')\n .replace('{bar}', bar(c.weekly.used, c.weekly.cap))\n .replace('{when}', resetLabel(c.weekly.resetAt)),\n '',\n )\n }\n\n if (report.failures.length > 0) {\n lines.push(commandCopy(locale, 'partialFailures').replace('{list}', report.failures.join('; ')), '')\n }\n if (!report.account && !report.usage && !report.credits) {\n lines.push(commandCopy(locale, 'noData'), '')\n }\n\n return lines.join('\\n').trimEnd()\n}\n\n/** The one registered `/commandcode` command. */\nexport function commandDefinition<C extends CommandCodeConnectionOptions>(\n deps: CommandCodeCommandDeps<C>,\n): CommandDefinition {\n const { adapter } = deps\n return {\n name: 'commandcode',\n description: 'Command Code account usage dashboard',\n input: { hint: '[status]' },\n handler: async () => {\n const locale: LocaleId = deps.getLocale?.() ?? 'zh'\n try {\n if (deps.reports !== undefined) {\n const { accounts } = await deps.reports()\n const sections = accounts.map((entry) => {\n const badges = `${entry.active ? commandCopy(locale, 'activeBadge') : ''}${markLabel(entry, locale)}`\n const title = commandCopy(locale, 'accountTitle')\n .replace('{label}', entry.label)\n .replace('{badges}', badges)\n if (!entry.configured) return `${title}\\n\\n${commandCopy(locale, 'unconfigured')}`\n return renderReport(entry.report, locale, title)\n })\n return { kind: 'success', text: sections.join(`\\n\\n${commandCopy(locale, 'accountSeparator')}\\n\\n`) }\n }\n const report = await adapter.getUsage()\n return { kind: 'success', text: renderReport(report, locale) }\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n kind: 'error',\n text: commandCopy(locale, 'errorText').replace('{message}', message),\n }\n }\n },\n }\n}\n\n/** Register the command on `ctx.commands` (called from the plugin entry). */\nexport function applyCommands<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeCommandDeps<C>,\n): void {\n ctx.commands.register(commandDefinition(deps))\n}\n","/**\n * Wire contract for the Command Code account-usage Remote\n * (`commandcode/report`).\n *\n * The settings page renders the same account/usage/credit facts the\n * `/commandcode` command prints, but the browser never holds the API key —\n * the report must be produced Host-side and cross the Connection RPC carrier.\n * The harness exposes plugin-defined Host methods through the Typert Gateway:\n * the Host half registers a strict invocation descriptor against a Cordis\n * service (`src/usage-remote.ts`), and the browser half mounts the matching\n * Remote contribution on `ctx.remote` (`src/client/index.ts`).\n *\n * This module is the single source both halves share: the result validator\n * (a hand-rolled {@link TypertSchema}, so neither half needs a schema library)\n * and the exact descriptor object, so the endpoint can never drift apart.\n * It is deliberately dependency-free — the client bundle inlines it, and only\n * `import type` edges leave it (erased at build).\n *\n * @module dsh-commandcode-provider/usage-wire\n */\n\nimport type { CommandCodeUsageReport, UsageBlockReason } from './adapter.ts'\n\nexport type { CommandCodeUsageReport, UsageBlockReason }\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\n\n/** One account's usage entry in the multi-account report. */\nexport interface CommandCodeAccountUsage {\n /** Stable slot id (`default`, `account-2`, …). */\n id: string\n /** Display label (user-provided or generated). */\n label: string\n /** Whether an API key resolved for this account. */\n configured: boolean\n /** Whether this account currently serves requests (first usable slot). */\n active: boolean\n /** Rotation mark: `''` (usable), `'rate-limit'`, or `'invalid-credential'`. */\n mark: string\n /** Known cooldown end in millis; 0 when unknown or not cooling down. */\n cooldownUntil: number\n /** The per-account report; `failures`-only when the fetch itself failed. */\n report: CommandCodeUsageReport\n}\n\n/** The settings page's account card data: one entry per configured account. */\nexport interface CommandCodeAccountsReport {\n accounts: CommandCodeAccountUsage[]\n}\n\n/** The npm package identity both contribution registrations claim. */\nexport const USAGE_REMOTE_PACKAGE = '@mars-sea/dsh-commandcode-provider'\n\n/** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */\nexport const USAGE_REPORT_ENDPOINT = 'commandcode/report'\n\n/** Reject one boundary value with a field-naming error. */\nfunction reject(field: string): never {\n throw new TypeError(`commandcode/report result: invalid ${field}`)\n}\n\n/** Read one required finite number field (`field` is the dotted error label). */\nfunction numberField(source: Record<string, unknown>, key: string, field: string): number {\n const value = source[key]\n if (typeof value !== 'number' || !Number.isFinite(value)) reject(field)\n return value\n}\n\n/** Read one required string field (`field` is the dotted error label). */\nfunction stringField(source: Record<string, unknown>, key: string, field: string): string {\n const value = source[key]\n if (typeof value !== 'string') reject(field)\n return value\n}\n\n/** Read one required boolean field (`field` is the dotted error label). */\nfunction booleanField(source: Record<string, unknown>, key: string, field: string): boolean {\n const value = source[key]\n if (typeof value !== 'boolean') reject(field)\n return value\n}\n\n/** Narrow an unknown value to a plain record, or reject. */\nfunction record(value: unknown, field: string): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) reject(field)\n return value as Record<string, unknown>\n}\n\n/** Validate one window-limit block (`fiveHour` / `weekly`). */\nfunction windowLimit(value: unknown, field: string): { used: number; cap: number; exceeded: boolean; resetAt: number } {\n const source = record(value, field)\n return {\n used: numberField(source, 'used', `${field}.used`),\n cap: numberField(source, 'cap', `${field}.cap`),\n exceeded: booleanField(source, 'exceeded', `${field}.exceeded`),\n resetAt: numberField(source, 'resetAt', `${field}.resetAt`),\n }\n}\n\n/**\n * Parse one untrusted boundary value into a {@link CommandCodeUsageReport}.\n * Optional sections stay optional; every present field is shape-checked so a\n * malformed frame fails the boundary instead of rendering garbage.\n */\nfunction parseUsageReport(value: unknown): CommandCodeUsageReport {\n const source = record(value, 'report')\n const failures = source.failures\n if (!Array.isArray(failures) || failures.some((entry) => typeof entry !== 'string')) reject('failures')\n const report: CommandCodeUsageReport = { failures: failures as string[] }\n\n if (source.blocked !== undefined) {\n const blocked = source.blocked\n if (blocked !== 'invalid-key' && blocked !== 'service-unavailable' && blocked !== 'network') reject('blocked')\n report.blocked = blocked\n }\n\n if (source.account !== undefined) {\n const account = record(source.account, 'account')\n report.account = {\n id: stringField(account, 'id', 'account.id'),\n name: stringField(account, 'name', 'account.name'),\n userName: stringField(account, 'userName', 'account.userName'),\n }\n }\n\n if (source.usage !== undefined) {\n const usage = record(source.usage, 'usage')\n report.usage = {\n totalCount: numberField(usage, 'totalCount', 'usage.totalCount'),\n totalCost: numberField(usage, 'totalCost', 'usage.totalCost'),\n successRate: numberField(usage, 'successRate', 'usage.successRate'),\n completedCount: numberField(usage, 'completedCount', 'usage.completedCount'),\n failedCount: numberField(usage, 'failedCount', 'usage.failedCount'),\n totalTokensIn: numberField(usage, 'totalTokensIn', 'usage.totalTokensIn'),\n totalTokensOut: numberField(usage, 'totalTokensOut', 'usage.totalTokensOut'),\n totalCredits: numberField(usage, 'totalCredits', 'usage.totalCredits'),\n periodBasis: stringField(usage, 'periodBasis', 'usage.periodBasis'),\n }\n }\n\n if (source.credits !== undefined) {\n const credits = record(source.credits, 'credits')\n report.credits = {\n monthlyCredits: numberField(credits, 'monthlyCredits', 'credits.monthlyCredits'),\n purchasedCredits: numberField(credits, 'purchasedCredits', 'credits.purchasedCredits'),\n freeCredits: numberField(credits, 'freeCredits', 'credits.freeCredits'),\n fiveHour: windowLimit(credits.fiveHour, 'credits.fiveHour'),\n weekly: windowLimit(credits.weekly, 'credits.weekly'),\n }\n }\n\n if (source.plan !== undefined) {\n const plan = record(source.plan, 'plan')\n const monthly = plan.monthlyCredits\n if (monthly !== null && (typeof monthly !== 'number' || !Number.isFinite(monthly))) reject('plan.monthlyCredits')\n report.plan = {\n planId: stringField(plan, 'planId', 'plan.planId'),\n name: stringField(plan, 'name', 'plan.name'),\n status: stringField(plan, 'status', 'plan.status'),\n monthlyCredits: monthly as number | null,\n currentPeriodEnd: numberField(plan, 'currentPeriodEnd', 'plan.currentPeriodEnd'),\n }\n }\n\n return report\n}\n\n/** Parse one untrusted boundary value into a {@link CommandCodeAccountUsage}. */\nfunction parseAccountUsage(value: unknown): CommandCodeAccountUsage {\n const source = record(value, 'account')\n return {\n id: stringField(source, 'id', 'account.id'),\n label: stringField(source, 'label', 'account.label'),\n configured: booleanField(source, 'configured', 'account.configured'),\n active: booleanField(source, 'active', 'account.active'),\n mark: stringField(source, 'mark', 'account.mark'),\n cooldownUntil: numberField(source, 'cooldownUntil', 'account.cooldownUntil'),\n report: parseUsageReport(source.report),\n }\n}\n\n/** Parse the wire result into a {@link CommandCodeAccountsReport}. */\nfunction parseAccountsReport(value: unknown): CommandCodeAccountsReport {\n const source = record(value, 'result')\n const accounts = source.accounts\n if (!Array.isArray(accounts)) reject('accounts')\n return { accounts: accounts.map(parseAccountUsage) }\n}\n\n/**\n * The strict result codec both halves attach to the descriptor. Hand-rolled:\n * the client bundle may not require a schema library, and `TypertSchema` is\n * deliberately minimal so one `parse` function satisfies it.\n */\nexport const usageReportSchema: TypertSchema<CommandCodeAccountsReport> = {\n parse: parseAccountsReport,\n}\n\n/**\n * The one invocation descriptor, shared verbatim by the Host registration and\n * the Client mount. `service` names the Cordis key the Gateway resolves the\n * receiver from; `namespace`/`method` name the wire endpoint.\n */\nexport const USAGE_REPORT_DESCRIPTOR: InvocationDescriptor = {\n id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method: 'report',\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`,\n schema: usageReportSchema,\n },\n}\n\n/** The Host-face contribution registered on `ctx.typert`. */\nexport const USAGE_HOST_CONTRIBUTION = {\n package: USAGE_REMOTE_PACKAGE,\n face: 'host' as const,\n schemas: [],\n // 0.1.2's Typert registry requires every Host contribution to carry its\n // reflection model. This hand-written Remote deliberately has no generated\n // reflection exports, so use the official empty-model form rather than a\n // cast that leaves registry inspection with `model: undefined`.\n model: { services: [], events: [], objects: [] },\n invocations: [USAGE_REPORT_DESCRIPTOR],\n}\n\n/** The Client-face contribution mounted on `ctx.remote`. */\nexport const USAGE_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [USAGE_REPORT_DESCRIPTOR],\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog Remote (`commandcode/models`)\n// ---------------------------------------------------------------------------\n\n/** One catalog entry the settings page's routing-rule editor offers. */\nexport interface CommandCodeCatalogModel {\n /** Catalog model id (e.g. `deepseek/deepseek-v4-pro`). */\n id: string\n /** Display name from the catalog. */\n name: string\n}\n\n/** The model-catalog Remote result: the full catalog, sorted for picking. */\nexport interface CommandCodeCatalog {\n models: CommandCodeCatalogModel[]\n}\n\n/** Canonical `<namespace>/<method>` endpoint of the model-catalog Remote. */\nexport const MODELS_ENDPOINT = 'commandcode/models'\n\n/** Parse one untrusted boundary value into a {@link CommandCodeCatalogModel}. */\nfunction parseCatalogModel(value: unknown): CommandCodeCatalogModel {\n const source = record(value, 'model')\n return {\n id: stringField(source, 'id', 'model.id'),\n name: stringField(source, 'name', 'model.name'),\n }\n}\n\n/** Parse the wire result into a {@link CommandCodeCatalog}. */\nfunction parseCatalog(value: unknown): CommandCodeCatalog {\n const source = record(value, 'result')\n const models = source.models\n if (!Array.isArray(models)) reject('models')\n return { models: models.map(parseCatalogModel) }\n}\n\n/** The strict result codec for the model-catalog Remote. */\nexport const modelsSchema: TypertSchema<CommandCodeCatalog> = {\n parse: parseCatalog,\n}\n\n/**\n * The model-catalog invocation descriptor, sharing the same `commandcodeUsage`\n * service and `commandcode` namespace as the usage report.\n */\nexport const MODELS_DESCRIPTOR: InvocationDescriptor = {\n id: `${USAGE_REMOTE_PACKAGE}#${MODELS_ENDPOINT}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method: 'models',\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`,\n schema: modelsSchema,\n },\n}\n\n/** The Client-face contribution for the model-catalog endpoint. */\nexport const MODELS_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [MODELS_DESCRIPTOR],\n}\n","/**\n * Wire contract for the Command Code login Remote endpoints\n * (`commandcode/loginBegin`, `commandcode/loginStatus`,\n * `commandcode/loginCancel`).\n *\n * The settings page can start a browser login against the official Command\n * Code Studio (the same loopback flow `command-code login` performs) instead\n * of pasting an API key. The loopback server must live in the Host half — it\n * binds a local port and receives the key — so the page drives it through the\n * Typert Gateway exactly like the usage report.\n *\n * This module is the single source both halves share, deliberately\n * dependency-free (`import type` edges only): the strict status validator the\n * client trusts, the three descriptors both halves register, and the two\n * contribution objects. The state shape mirrors the Host-only flow machine in\n * `src/login.ts` as plain JSON.\n *\n * @module dsh-commandcode-provider/login-wire\n */\n\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\nimport { USAGE_REMOTE_PACKAGE } from './usage-wire.ts'\n\n/** Why a login attempt ended in `failed` (stable across versions for copy). */\nexport type CommandCodeLoginFailureReason =\n /** The Studio page reported the authorization was denied by the user. */\n | 'denied'\n /** No callback arrived within the flow's timeout window. */\n | 'timeout'\n /** The delivered key failed `/alpha/whoami` validation (401). */\n | 'invalid-key'\n /** The validation request could not reach the API. */\n | 'network'\n /** The key could not be stored (credentials seam unavailable). */\n | 'unavailable'\n /** The attempt was cancelled by the user or torn down with the plugin. */\n | 'cancelled'\n /** Anything else. */\n | 'error'\n\n/** One login attempt's full state face, as carried over the wire. */\nexport interface CommandCodeLoginStatus {\n /**\n * `idle` — no attempt; `waiting` — the loopback server is up and the\n * Studio URL is live; `success` — the key validated and was stored;\n * `failed` — see `reason`/`message`.\n */\n state: 'idle' | 'waiting' | 'success' | 'failed'\n /** The Studio authorization URL while `waiting`. */\n authUrl?: string\n /** The account display name reported by the Studio, on `success`. */\n userName?: string\n /** The key's label from the Studio, on `success`. */\n keyName?: string\n /** Why the attempt failed, when `failed`. */\n reason?: CommandCodeLoginFailureReason\n /** Human-readable failure detail, when `failed` (secondary to `reason`). */\n message?: string\n}\n\n/** The canonical endpoint paths of the three login Remotes. */\nexport const LOGIN_BEGIN_ENDPOINT = 'commandcode/loginBegin'\nexport const LOGIN_STATUS_ENDPOINT = 'commandcode/loginStatus'\nexport const LOGIN_CANCEL_ENDPOINT = 'commandcode/loginCancel'\n\nconst REASONS: readonly CommandCodeLoginFailureReason[] = [\n 'denied', 'timeout', 'invalid-key', 'network', 'unavailable', 'cancelled', 'error',\n]\n\n/** Reject one boundary value with a field-naming error. */\nfunction reject(field: string): never {\n throw new TypeError(`commandcode/login result: invalid ${field}`)\n}\n\n/**\n * Parse one untrusted boundary value into a {@link CommandCodeLoginStatus}.\n * Every field is shape-checked so a malformed frame fails the boundary\n * instead of leaking into the page.\n */\nexport function parseLoginStatus(value: unknown): CommandCodeLoginStatus {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) reject('status')\n const source = value as Record<string, unknown>\n const state = source.state\n if (state !== 'idle' && state !== 'waiting' && state !== 'success' && state !== 'failed') {\n reject('state')\n }\n const status: CommandCodeLoginStatus = { state }\n if (source.authUrl !== undefined) {\n if (typeof source.authUrl !== 'string') reject('authUrl')\n status.authUrl = source.authUrl\n }\n if (source.userName !== undefined) {\n if (typeof source.userName !== 'string') reject('userName')\n status.userName = source.userName\n }\n if (source.keyName !== undefined) {\n if (typeof source.keyName !== 'string') reject('keyName')\n status.keyName = source.keyName\n }\n if (source.reason !== undefined) {\n if (!REASONS.includes(source.reason as CommandCodeLoginFailureReason)) reject('reason')\n status.reason = source.reason as CommandCodeLoginFailureReason\n }\n if (source.message !== undefined) {\n if (typeof source.message !== 'string') reject('message')\n status.message = source.message\n }\n return status\n}\n\n/** The strict result codec shared by all three login endpoints. */\nexport const loginStatusSchema: TypertSchema<CommandCodeLoginStatus> = {\n parse: parseLoginStatus,\n}\n\n/** Build one login invocation descriptor (uniform result, no parameters). */\nfunction loginDescriptor(endpoint: string, method: string): InvocationDescriptor {\n return {\n id: `${USAGE_REMOTE_PACKAGE}#${endpoint}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method,\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeLoginStatus`,\n schema: loginStatusSchema,\n },\n }\n}\n\n/** The three login descriptors, shared verbatim by Host registration and Client mount. */\nexport const LOGIN_DESCRIPTORS: readonly InvocationDescriptor[] = [\n loginDescriptor(LOGIN_BEGIN_ENDPOINT, 'loginBegin'),\n loginDescriptor(LOGIN_STATUS_ENDPOINT, 'loginStatus'),\n loginDescriptor(LOGIN_CANCEL_ENDPOINT, 'loginCancel'),\n]\n\n/** The Host-face contribution fragment registered on `ctx.typert`. */\nexport const LOGIN_HOST_CONTRIBUTION = {\n package: USAGE_REMOTE_PACKAGE,\n face: 'host' as const,\n schemas: [],\n invocations: LOGIN_DESCRIPTORS,\n}\n\n/** The Client-face contribution fragment mounted on `ctx.remote`. */\nexport const LOGIN_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: LOGIN_DESCRIPTORS,\n}\n","/**\n * Host half of the account-usage Remote (`commandcode/report`).\n *\n * The settings page's account card needs the same report the `/commandcode`\n * command prints, but the browser never holds the API key — the fetch must\n * run Host-side. This module exposes `adapter.getUsage()` through the Typert\n * Gateway: a `TypertRemoteService` provides the receiver the Gateway resolves,\n * and the shared strict descriptor (`src/usage-wire.ts`) is registered on the\n * `typert` registry so the Gateway claims the `commandcode/report` endpoint.\n *\n * The whole wiring rides an optional `ctx.inject(['typert'], ...)` fiber: a\n * profile without the web stack (no Typert registry, no Gateway) simply never\n * activates it, exactly like the `/commandcode` command rides `commands`.\n *\n * @module dsh-commandcode-provider/usage-remote\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport type { CommandCodeAdapter, CommandCodeConnectionOptions } from './adapter.ts'\nimport { USAGE_HOST_CONTRIBUTION } from './usage-wire.ts'\nimport { MODELS_DESCRIPTOR } from './usage-wire.ts'\nimport type { CommandCodeAccountsReport, CommandCodeCatalog } from './usage-wire.ts'\nimport { LOGIN_DESCRIPTORS } from './login-wire.ts'\nimport type { CommandCodeLoginStatus } from './login-wire.ts'\n\n/**\n * The browser-login face the usage service exposes (`commandcode/login*`).\n * Backed by the Host-half {@link !CommandCodeLoginFlow} when the plugin entry\n * wired one; absent, the methods degrade to a no-op status so an old client\n * against a fresh page still answers instead of hanging.\n */\nexport interface LoginFlowFacade {\n /** Start (or rejoin) an attempt; rejects when it cannot start at all. */\n begin(): Promise<CommandCodeLoginStatus>\n /** The current attempt's status. */\n status(): CommandCodeLoginStatus\n /** Cancel a waiting attempt. */\n cancel(): void\n}\n\n/** Everything the usage service needs beyond its Cordis context. */\nexport interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage). */\n adapter: CommandCodeAdapter<C>\n /**\n * Multi-account report source (wired by the plugin entry). Absent in\n * programmatic setups, the service falls back to a single default-account\n * entry around `adapter.getUsage()`.\n */\n reports?: () => Promise<CommandCodeAccountsReport>\n /**\n * Model-catalog source for the routing-rule editor (wired by the plugin\n * entry). Absent, the `models` endpoint answers an empty list — the page's\n * rule editor degrades to the empty state.\n */\n listModels?: () => Promise<CommandCodeCatalog>\n /**\n * The browser-login flow (wired by the plugin entry). Absent means the\n * login endpoints answer `idle` / reject with a plain message — the page's\n * manual paste path stays the fallback.\n */\n login?: LoginFlowFacade\n}\n\n/**\n * The registry method surface this module uses. `Context['typert']` is typed\n * as the read-only `TypertRegistryContract`; contribution registration lives\n * on the concrete registry service, so the cast is spelled out once here.\n */\ninterface TypertContributionRegistry {\n register(contribution: typeof USAGE_HOST_CONTRIBUTION): () => void | Promise<void>\n}\n\n/**\n * The Remote receiver: a Cordis service the Gateway resolves by key\n * (`commandcodeUsage`) and binds to the wire namespace (`commandcode`). The\n * base class stamps the `typertRemote` binding the Gateway validates on every\n * dispatch; no decorators are needed because the descriptor is registered\n * explicitly (strict path) rather than discovered from source markers.\n */\nexport class CommandCodeUsageService<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions>\n extends TypertRemoteService {\n private readonly deps: CommandCodeUsageDeps<C>\n\n constructor(ctx: Context, deps: CommandCodeUsageDeps<C>) {\n super(ctx, 'commandcodeUsage', { namespace: 'commandcode' })\n this.deps = deps\n }\n\n /**\n * Account, usage, and credit state for the settings page's account card —\n * one entry per pool account when the plugin entry wired `reports`, a\n * single default-account entry otherwise. Degrades per endpoint like the\n * `/commandcode` command (failures land in `report.failures`); throws\n * `MISSING_CREDENTIAL` when no key resolves, which the Gateway folds into\n * the failure branch the page renders as a hint.\n */\n async report(): Promise<CommandCodeAccountsReport> {\n if (this.deps.reports !== undefined) return this.deps.reports()\n const report = await this.deps.adapter.getUsage()\n return {\n accounts: [{\n id: 'default',\n label: 'Default',\n configured: true,\n active: true,\n mark: '',\n cooldownUntil: 0,\n report,\n }],\n }\n }\n\n /**\n * The model catalog for the settings page's routing-rule editor. The\n * browser never calls the Command Code API directly — the Host serves the\n * catalog (already fetched/cached by the adapter) so rules can be picked\n * from the live model list instead of typed by hand.\n */\n async models(): Promise<CommandCodeCatalog> {\n return this.deps.listModels?.() ?? { models: [] }\n }\n\n /**\n * Start (or rejoin) a browser-login attempt and return its fresh status —\n * `waiting` carrying the Studio URL. Rejects when the flow cannot start\n * (no free loopback port, disposed plugin); the Gateway folds the throw\n * into the failure branch the page renders.\n */\n async loginBegin(): Promise<CommandCodeLoginStatus> {\n const login = this.requireLogin()\n return login.begin()\n }\n\n /** Poll a login attempt's status. */\n async loginStatus(): Promise<CommandCodeLoginStatus> {\n return this.deps.login?.status() ?? { state: 'idle' }\n }\n\n /** Cancel a waiting attempt; returns the post-cancel status. */\n async loginCancel(): Promise<CommandCodeLoginStatus> {\n this.deps.login?.cancel()\n return this.deps.login?.status() ?? { state: 'idle' }\n }\n\n private requireLogin(): LoginFlowFacade {\n const login = this.deps.login\n if (login === undefined) {\n throw new Error('login flow is not wired in this setup; paste the API key instead')\n }\n return login\n }\n}\n\n/**\n * Provide the usage service and register its Remote descriptor. The registry\n * contribution is tied to this fiber's lifetime: the registry's own\n * `register()` effect would otherwise outlive the plugin.\n */\nexport function applyUsageRemote<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeUsageDeps<C>,\n): void {\n ctx.inject(['typert'], (remoteCtx) => {\n new CommandCodeUsageService(remoteCtx, deps)\n const registry = remoteCtx.typert as unknown as TypertContributionRegistry\n // One registration carries the report endpoint, the models endpoint, and\n // the login endpoints: the descriptors are unique per endpoint, and a\n // single contribution keeps the Host's registry bookkeeping (and the\n // Client mount) 1:1.\n const unregister = registry.register({\n ...USAGE_HOST_CONTRIBUTION,\n invocations: [...USAGE_HOST_CONTRIBUTION.invocations, MODELS_DESCRIPTOR, ...LOGIN_DESCRIPTORS],\n })\n // The registry's own effect would outlive this fiber; withdraw the\n // contribution when the plugin unloads.\n remoteCtx.effect(() => () => void unregister(), 'dsh-commandcode-provider: usage remote')\n })\n}\n","/**\n * Host half of the Command Code browser login (the loopback flow).\n *\n * Mirrors what the official `command-code login` CLI command performs\n * (reverse-engineered from `command-code@1.32.1`, `createAuthFlowController`\n * + `createAuthServer` in its bundle):\n *\n * 1. Bind a temporary HTTP server on `127.0.0.1`, first available port from\n * 5959 upward (10 attempts).\n * 2. Generate a random state token and open\n * `{studio}/studio/auth/cli?callback=http://localhost:{port}/callback&state={state}`.\n * 3. After the user signs in, the Studio page POSTs the credentials JSON\n * `{ apiKey, state, userId, userName, keyName }` to the loopback callback —\n * no OAuth code exchange, the page holds the final API key.\n * 4. The delivered key is validated against `GET {apiBase}/alpha/whoami`\n * before anything is stored.\n *\n * Server behaviour is mirrored exactly: POST-only `/callback`, a 10 KB body\n * cap, JSON responses (`{success:true}` / `{success:false,error}`), CORS for\n * the Studio origins only, and state-token equality as the anti-forgery\n * check. One deliberate hardening over the CLI build: the CORS origin is\n * echoed only when it is allowlisted (the CLI falls back to the first\n * origin), which browsers treat identically.\n *\n * Storage stays out of this module: the plugin entry supplies\n * {@link CommandCodeLoginFlowDeps.storeKey}, which writes through the dsh\n * credentials seam so the next request resolves the new key with no restart.\n * Everything external (fetch, ports, randomness, timing) is injectable for\n * node tests; the tests drive a real loopback server end to end.\n *\n * @module dsh-commandcode-provider/login\n */\n\nimport { createServer as createHttpServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http'\nimport { createServer as createNetServer } from 'node:net'\nimport { randomBytes } from 'node:crypto'\nimport { DEFAULT_API_BASE } from './adapter.ts'\nimport type { CommandCodeLoginFailureReason, CommandCodeLoginStatus } from './login-wire.ts'\n\n/** Give up on the browser after this long without a callback (mirrors the CLI). */\nexport const LOGIN_TIMEOUT_MS = 120_000\n\n/** First local port the flow tries (mirrors the CLI). */\nexport const LOGIN_START_PORT = 5959\n\n/** How many consecutive ports to try from {@link LOGIN_START_PORT}. */\nexport const LOGIN_MAX_PORT_ATTEMPTS = 10\n\n/** Reject callback bodies larger than this (mirrors the CLI). */\nexport const LOGIN_BODY_LIMIT_BYTES = 10_000\n\n/** The Studio origins allowed to POST credentials to the loopback server. */\nexport const LOGIN_ALLOWED_ORIGINS: readonly string[] = [\n 'http://localhost:3000',\n 'https://staging.commandcode.ai',\n 'https://commandcode.ai',\n]\n\n/** The Studio route that performs the browser-side login. */\nconst STUDIO_AUTH_PATH = '/studio/auth/cli'\n\n/** Credentials as delivered by the Studio's callback POST. */\nexport interface CommandCodeLoginCredentials {\n apiKey: string\n userId: string\n userName: string\n keyName: string\n}\n\n/** Outcome of validating a delivered key against `/alpha/whoami`. */\nexport type ApiKeyValidation =\n | { valid: true }\n | { valid: false; error: 'invalid_key' | 'server_error' | 'network_error' }\n\nexport interface CommandCodeLoginFlowDeps {\n /**\n * The Provider API base used for `/alpha/whoami` validation; also selects\n * the matching Studio base (staging api → staging studio). A thunk is fine:\n * it is re-read when each attempt starts, so a settings change reaches the\n * next login. Defaults to the public API base.\n */\n apiBase?: string | (() => string | undefined)\n /** Attempt timeout in millis; defaults to {@link LOGIN_TIMEOUT_MS}. */\n timeoutMs?: number\n /** First port to try; defaults to {@link LOGIN_START_PORT}. */\n startPort?: number\n /** Consecutive-port attempts; defaults to {@link LOGIN_MAX_PORT_ATTEMPTS}. */\n maxPortAttempts?: number\n /** Validation fetch seam; defaults to global `fetch`. */\n fetchImpl?: typeof fetch\n /** Randomness seam; defaults to `node:crypto` randomBytes(32) base64url. */\n randomToken?: (byteLength: number) => string\n /**\n * Receives the validated credentials after a successful login. Rejecting\n * fails the attempt with `unavailable`.\n */\n storeKey(credentials: CommandCodeLoginCredentials): Promise<void>\n}\n\n/** Compose the Studio authorization URL (pure, exported for tests). */\nexport function buildCommandAuthUrl(options: { studioBase: string; port: number; state: string }): string {\n const callback = `http://localhost:${options.port}/callback`\n return `${options.studioBase}${STUDIO_AUTH_PATH}?callback=${encodeURIComponent(callback)}&state=${encodeURIComponent(options.state)}`\n}\n\n/** Map an API base onto the Studio base the CLI pairs it with. */\nexport function studioBaseForApiBase(apiBase: string): string {\n if (/^https:\\/\\/staging-api\\.commandcode\\.ai/i.test(apiBase)) return 'https://staging.commandcode.ai'\n if (/^http:\\/\\/localhost(:\\d+)?$/i.test(apiBase)) return 'http://localhost:3000'\n return 'https://commandcode.ai'\n}\n\n/**\n * Validate one candidate key against `/alpha/whoami` (pure, exported for\n * tests). Mirrors the CLI's verdicts: 401 → invalid_key, other non-OK →\n * server_error, transport failure → network_error.\n */\nexport async function validateCommandApiKey(\n fetchImpl: typeof fetch,\n apiBase: string,\n apiKey: string,\n): Promise<ApiKeyValidation> {\n try {\n const response = await fetchImpl(`${apiBase}/alpha/whoami`, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },\n })\n if (response.status === 401) return { valid: false, error: 'invalid_key' }\n if (response.ok) return { valid: true }\n return { valid: false, error: 'server_error' }\n } catch {\n return { valid: false, error: 'network_error' }\n }\n}\n\n/** Whether one loopback port is free right now. */\nfunction checkPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const probe = createNetServer()\n probe.once('error', () => resolve(false))\n probe.once('listening', () => probe.close(() => resolve(true)))\n probe.listen(port, '127.0.0.1')\n })\n}\n\n/** Whether a callback body carries every credential field the CLI requires. */\nfunction isCallbackCredentials(value: unknown): value is CommandCodeLoginCredentials & Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Record<string, unknown>\n return typeof record.apiKey === 'string' && record.apiKey !== ''\n && typeof record.state === 'string'\n && typeof record.userId === 'string'\n && typeof record.userName === 'string'\n && typeof record.keyName === 'string'\n}\n\n/**\n * One browser-login attempt machine. Single-flight by design: `begin()` while\n * waiting returns the live attempt's status instead of starting a second one;\n * a terminal state makes the next `begin()` start fresh.\n */\nexport class CommandCodeLoginFlow {\n private readonly deps: CommandCodeLoginFlowDeps\n private readonly listeners = new Set<() => void>()\n\n private statusValue: CommandCodeLoginStatus = { state: 'idle' }\n private server: Server | undefined\n private timer: ReturnType<typeof setTimeout> | undefined\n /** Settle hooks of the live attempt's callback promise. */\n private settle: {\n resolve(credentials: CommandCodeLoginCredentials): void\n reject(failure: LoginSettleError): void\n } | undefined\n private disposed = false\n\n constructor(deps: CommandCodeLoginFlowDeps) {\n this.deps = deps\n }\n\n /** Subscribe to state transitions. @returns the disposer. */\n onChange(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** The current attempt's status face. */\n status(): CommandCodeLoginStatus {\n return this.statusValue\n }\n\n /**\n * Start an attempt (or rejoin the live one) and resolve with its status —\n * `waiting` carrying the Studio URL once the loopback server is up.\n * Rejects only when the flow cannot start at all (no free port, disposed).\n */\n async begin(): Promise<CommandCodeLoginStatus> {\n if (this.disposed) throw new Error('login flow has been disposed')\n if (this.statusValue.state === 'waiting') return this.statusValue\n this.teardown()\n\n const port = await this.findPort()\n const expectedState = this.deps.randomToken?.(32) ?? randomBytes(32).toString('base64url')\n\n // The attempt settles exactly once: fulfilled with delivered credentials,\n // rejected with a tagged failure the mapping below turns into copy.\n const settled = new Promise<CommandCodeLoginCredentials>((resolve, reject) => {\n this.settle = { resolve, reject }\n })\n // A bind failure must surface before the attempt reports `waiting`.\n await this.bindServer(port, expectedState)\n\n const apiBase = this.readApiBase()\n this.setStatus({\n state: 'waiting',\n authUrl: buildCommandAuthUrl({ studioBase: studioBaseForApiBase(apiBase), port, state: expectedState }),\n })\n\n // Watchdog mirrors the CLI's 2-minute window.\n this.timer = setTimeout(() => {\n this.teardown()\n this.setStatus({\n state: 'failed',\n reason: 'timeout',\n message: 'No browser callback arrived within the login window.',\n })\n }, this.deps.timeoutMs ?? LOGIN_TIMEOUT_MS)\n this.timer.unref?.()\n\n void settled.then(\n (credentials) => this.complete(credentials),\n (failure) => this.failFrom(failure),\n )\n return this.statusValue\n }\n\n /** Cancel a waiting attempt; terminal states are untouched. */\n cancel(): void {\n if (this.disposed || this.statusValue.state !== 'waiting') return\n this.teardown()\n this.setStatus({ state: 'failed', reason: 'cancelled' })\n }\n\n /** Stop everything; a waiting attempt ends cancelled. Idempotent. */\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n const wasWaiting = this.statusValue.state === 'waiting'\n this.teardown()\n if (wasWaiting) this.setStatus({ state: 'failed', reason: 'cancelled' })\n }\n\n // -----------------------------------------------------------------------\n // Internals\n // -----------------------------------------------------------------------\n\n private readApiBase(): string {\n const raw = typeof this.deps.apiBase === 'function' ? this.deps.apiBase() : this.deps.apiBase\n return raw ?? DEFAULT_API_BASE\n }\n\n private setStatus(next: CommandCodeLoginStatus): void {\n this.statusValue = next\n for (const listener of [...this.listeners]) listener()\n }\n\n /** First free port among the consecutive candidates. */\n private async findPort(): Promise<number> {\n const startPort = this.deps.startPort ?? LOGIN_START_PORT\n const attempts = this.deps.maxPortAttempts ?? LOGIN_MAX_PORT_ATTEMPTS\n for (let index = 0; index < attempts; index += 1) {\n const candidate = startPort + index\n if (await checkPortAvailable(candidate)) return candidate\n }\n throw new Error(`No available port found after ${attempts} attempts starting from port ${startPort}`)\n }\n\n /**\n * Bind the attempt's loopback server, resolving when the port is live.\n * Pre-bind failures reject (surfacing from `begin()`); a later server error\n * settles the live attempt as a tagged failure instead.\n */\n private bindServer(port: number, expectedState: string): Promise<void> {\n return new Promise((resolve, reject) => {\n let binding = true\n const server = createHttpServer((request, response) => this.handleCallback(request, response, expectedState))\n this.server = server\n server.once('error', (error: NodeJS.ErrnoException) => {\n if (this.server !== server) return\n this.server = undefined\n const tagged = new LoginSettleError(\n 'error',\n `Could not bind the login callback server on port ${port}: ${error.code ?? error.message}`,\n )\n if (binding) {\n binding = false\n reject(tagged)\n } else {\n this.settle?.reject(tagged)\n }\n })\n server.listen(port, '127.0.0.1', () => {\n if (!binding) return\n binding = false\n resolve()\n })\n })\n }\n\n /** One request against the attempt's callback endpoint (CLI-mirrored). */\n private handleCallback(request: IncomingMessage, response: ServerResponse, expectedState: string): void {\n // One-shot responses: the server dies with the attempt, and a client\n // pooling the connection would otherwise race its next request against\n // the close.\n response.setHeader('Connection', 'close')\n response.setHeader('Access-Control-Allow-Origin', corsOrigin(request.headers.origin))\n response.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS')\n response.setHeader('Access-Control-Allow-Headers', 'Content-Type')\n response.setHeader('Content-Type', 'application/json')\n const json = (code: number, body: Record<string, unknown>) => {\n response.writeHead(code)\n response.end(JSON.stringify(body))\n }\n if (request.method === 'OPTIONS') {\n response.writeHead(204)\n response.end()\n return\n }\n const path = request.url?.split('?')[0] ?? '/'\n if (path !== '/callback') {\n json(404, { success: false, error: 'Not found' })\n return\n }\n if (request.method !== 'POST') {\n json(405, { success: false, error: 'Method not allowed. Use POST.' })\n return\n }\n let body = ''\n request.on('data', (chunk: Buffer) => {\n body += chunk.toString()\n if (body.length > LOGIN_BODY_LIMIT_BYTES) request.destroy()\n })\n request.on('end', () => {\n let payload: unknown\n try {\n payload = JSON.parse(body)\n } catch {\n json(400, { success: false, error: 'Invalid JSON' })\n return\n }\n // The Studio reports a denied authorization as an error object.\n if (typeof payload === 'object' && payload !== null && 'error' in payload) {\n const denial = payload as Record<string, unknown>\n const description = denial.error_description ?? denial.error\n this.settleAttempt(json, 200, { success: true }, new LoginSettleError(\n denial.error === 'access_denied' ? 'denied' : 'error',\n typeof description === 'string' && description !== '' ? description : 'Authorization failed',\n ))\n return\n }\n if (!isCallbackCredentials(payload)) {\n json(400, { success: false, error: 'Missing required fields' })\n return\n }\n if (payload.state !== expectedState) {\n // Not terminal: a stale tab replaying an old state must not kill the\n // live attempt — answer 403 and keep waiting (the CLI does the same).\n json(403, { success: false, error: 'Invalid state token' })\n return\n }\n this.settleAttempt(json, 200, { success: true }, undefined, { ...payload })\n })\n request.on('error', () => {})\n }\n\n /** Answer a decisive callback, stop listening, and settle the attempt. */\n private settleAttempt(\n json: (code: number, body: Record<string, unknown>) => void,\n code: number,\n body: Record<string, unknown>,\n failure?: LoginSettleError,\n credentials?: CommandCodeLoginCredentials,\n ): void {\n json(code, body)\n // Capture the settle hooks BEFORE teardown clears them.\n const settle = this.settle\n this.teardown()\n if (settle === undefined) return\n if (failure !== undefined) settle.reject(failure)\n else if (credentials !== undefined) settle.resolve(credentials)\n }\n\n /** Post-validation completion: whoami check, then hand-off to storage. */\n private async complete(credentials: CommandCodeLoginCredentials): Promise<void> {\n if (this.disposed || this.statusValue.state !== 'waiting') return\n const validation = await validateCommandApiKey(\n this.deps.fetchImpl ?? fetch,\n this.readApiBase(),\n credentials.apiKey,\n )\n if (!validation.valid) {\n const reason: CommandCodeLoginFailureReason = validation.error === 'invalid_key'\n ? 'invalid-key'\n : validation.error === 'network_error' ? 'network' : 'error'\n this.setStatus({\n state: 'failed',\n reason,\n message: `/alpha/whoami rejected the delivered key (${validation.error}).`,\n })\n return\n }\n try {\n await this.deps.storeKey(credentials)\n } catch (error: unknown) {\n this.setStatus({\n state: 'failed',\n reason: 'unavailable',\n message: error instanceof Error ? error.message : String(error),\n })\n return\n }\n if (this.disposed) return\n this.clearTimer()\n this.setStatus({ state: 'success', userName: credentials.userName, keyName: credentials.keyName })\n }\n\n /** Map a tagged settle rejection onto the status face. */\n private failFrom(failure: unknown): void {\n if (!(failure instanceof LoginSettleError)) return\n if (this.disposed || this.statusValue.state !== 'waiting') return\n this.setStatus({ state: 'failed', reason: failure.reason, message: failure.message })\n }\n\n private clearTimer(): void {\n if (this.timer !== undefined) {\n clearTimeout(this.timer)\n this.timer = undefined\n }\n }\n\n /** Close the server and watchdog without touching the published status. */\n private teardown(): void {\n this.clearTimer()\n this.server?.close()\n this.server = undefined\n this.settle = undefined\n }\n}\n\n/** A tagged settle failure carrying the stable copy reason. */\nclass LoginSettleError extends Error {\n constructor(public readonly reason: CommandCodeLoginFailureReason, message: string) {\n super(message)\n this.name = 'LoginSettleError'\n }\n}\n\n/** Echo the Origin header only when the Studio allowlist contains it. */\nfunction corsOrigin(origin: string | undefined): string {\n return origin !== undefined && LOGIN_ALLOWED_ORIGINS.includes(origin) ? origin : ''\n}\n","/**\n * dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command\n * Code (unofficial; ported from pi-commandcode-provider@0.5.1).\n *\n * Registers the `commandcode` provider route on `ctx.llm` and declares it in\n * the configurable-provider directory, so the web Models page shows a\n * \"Command Code\" card with an API-key field and the model picker lists the\n * live Command Code model catalog. Connection facts resolve per request over\n * the optional `llm-commandcode` user-settings section and the credential\n * seam, so a changed key, endpoint, or cache path reaches the next request\n * without a restart.\n *\n * ```yaml\n * - id: llm-commandcode\n * name: \"@mars-sea/dsh-commandcode-provider\"\n * config:\n * apiKeyEnv: COMMANDCODE_API_KEY\n * ```\n *\n * The `name` is the full package specifier as installed in the profile's\n * node_modules: the loader imports it as a module, and pnpm links packages by\n * their true (scoped) name — a bare `dsh-commandcode-provider` fails to\n * resolve (ERR_MODULE_NOT_FOUND) and crashes the app on boot. The value must\n * be quoted in YAML: an unquoted scalar starting with `@` fails to parse.\n *\n * @module dsh-commandcode-provider\n */\n\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport z from '@deepseek-ai/schemastery'\nimport { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'\nimport { assertUsableApiKey, LlmError } from '@deepseek-ai/dsh-llm'\nimport { credentialRef, type CredentialRef } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\nimport type {} from '@deepseek-ai/dsh-settings'\nimport { CommandCodeAdapter, DEFAULT_API_BASE, resolveAuthFileApiKey } from './adapter.ts'\nimport { DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS } from './adapter.ts'\nimport type { CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\nimport { CommandCodeAccountPool, accountUsable, selectActiveAccount } from './accounts.ts'\nimport type { CommandCodeAccountConfig, CommandCodeAccountSlot, CommandCodeModelAccountRule } from './accounts.ts'\nimport { applyCommands } from './commands.ts'\nimport { applyUsageRemote } from './usage-remote.ts'\nimport type { CommandCodeAccountsReport, CommandCodeCatalog } from './usage-wire.ts'\nimport { CommandCodeLoginFlow } from './login.ts'\nimport type { CommandCodeLoginCredentials } from './login.ts'\nimport { pickCommandLocale, type LocaleId } from './command-locales.ts'\n\nexport {\n COMMAND_CODE_CLI_VERSION,\n DEFAULT_API_BASE,\n DEFAULT_GENERATE_MAX_TOKENS,\n DEFAULT_MAX_OUTPUT_TOKENS,\n DEFAULT_REQUEST_TIMEOUT_MS,\n DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n CommandCodeAdapter,\n KNOWN_EFFORTS,\n KNOWN_IMAGE_MODELS,\n KNOWN_THINKING_MODELS,\n KNOWN_PLANS,\n KNOWN_SUBSCRIPTION_PLANS,\n KNOWN_DEALS,\n KNOWN_PEAK_PRICING,\n PLAN_LABELS,\n PLAN_ORDER,\n BILLING_ACCESS_TTL_MS,\n capabilityDescription,\n compareByPlan,\n dealLabel,\n formatContext,\n modelVisibleInPlan,\n peakPricingLabel,\n peakPricingState,\n planLabel,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n subscriptionPlanInfo,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeBillingAccess, CommandCodeConnectionOptions, CommandCodeUsageReport, ResolveAttachments } from './adapter.ts'\nexport { applyCommands, commandDefinition } from './commands.ts'\nexport type { CommandCodeCommandDeps } from './commands.ts'\nexport { applyUsageRemote, CommandCodeUsageService } from './usage-remote.ts'\nexport type { CommandCodeUsageDeps, LoginFlowFacade } from './usage-remote.ts'\nexport { USAGE_REPORT_ENDPOINT, usageReportSchema } from './usage-wire.ts'\nexport type { CommandCodeAccountUsage, CommandCodeAccountsReport } from './usage-wire.ts'\nexport {\n LOGIN_BEGIN_ENDPOINT,\n LOGIN_STATUS_ENDPOINT,\n LOGIN_CANCEL_ENDPOINT,\n parseLoginStatus,\n loginStatusSchema,\n} from './login-wire.ts'\nexport type {\n CommandCodeLoginStatus,\n CommandCodeLoginFailureReason,\n} from './login-wire.ts'\nexport {\n LOGIN_TIMEOUT_MS,\n LOGIN_START_PORT,\n LOGIN_MAX_PORT_ATTEMPTS,\n LOGIN_BODY_LIMIT_BYTES,\n LOGIN_ALLOWED_ORIGINS,\n buildCommandAuthUrl,\n studioBaseForApiBase,\n validateCommandApiKey,\n CommandCodeLoginFlow,\n} from './login.ts'\nexport type {\n CommandCodeLoginCredentials,\n CommandCodeLoginFlowDeps,\n ApiKeyValidation,\n} from './login.ts'\nexport { CommandCodeAccountPool, accountUsable, selectActiveAccount, matchModelRule, selectAccountForModel } from './accounts.ts'\nexport type { CommandCodeAccountConfig, CommandCodeAccountSlot, CommandCodeAccountState, CommandCodeModelAccountRule } from './accounts.ts'\n\nexport const name = 'llm-commandcode'\nexport const inject = ['llm']\n\nconst NS = 'llm-commandcode'\nconst DEFAULT_API_KEY_ENV = 'COMMANDCODE_API_KEY'\n\n/** The single provider route this plugin owns. */\nexport const PROVIDER = 'commandcode'\n/** Default models cache path (mirrors the pi plugin's on-disk cache). */\nexport const DEFAULT_MODELS_CACHE_PATH = join(homedir(), '.commandcode', 'models-cache.json')\n\n/**\n * Plugin config, validated by the same-named schemastery schema and doubling\n * as the `llm-commandcode` settings-section shape. Every field is optional:\n * a missing API key resolves through {@link Config.apiKeyEnv} at each request\n * (the web Models page writes it), with the official Command Code CLI auth\n * file (`~/.commandcode/auth.json`) as the last fallback.\n */\nexport interface Config {\n /** Credential reference (environment-variable name) resolved per request; defaults to `COMMANDCODE_API_KEY`. */\n apiKeyEnv?: string\n /** Literal API key override (composition config only); takes precedence over `apiKeyEnv`. */\n apiKey?: string\n /** API base; defaults to the public Command Code Provider API. */\n apiBase?: string\n /** Working directory reported to the API; defaults to the process cwd. */\n workingDir?: string\n /** Model catalog cache path; defaults to `~/.commandcode/models-cache.json`. */\n modelsCachePath?: string\n /** Milliseconds to wait for the generate response's first byte; defaults to 60s. */\n requestTimeoutMs?: number\n /** Milliseconds a stream may stall before being treated as a dead connection; defaults to 300s. */\n streamIdleTimeoutMs?: number\n /**\n * Whether the model picker hides models above the account's subscription\n * tier; defaults to true. The filter fails open (unknown plan, billing\n * endpoint failure, or a positive on-demand credit balance all keep the\n * full catalog visible). Set false to always list every model.\n */\n filterModelsByPlan?: boolean\n /**\n * Extra accounts for multi-account rotation. The top-level\n * `apiKey`/`apiKeyEnv` (plus the CLI auth file) always form the first\n * (`default`) account; each entry here adds one more. When a request is\n * rejected pre-stream with 429 (usage window exhausted) or 401, the next\n * account's key retried transparently; when every account is exhausted the\n * request fails with a `RATE_LIMIT` error naming the earliest window\n * reset. Entries without `apiKey` or `apiKeyEnv` are ignored.\n */\n accounts?: CommandCodeAccountConfig[]\n /**\n * Manually selected active account: a slot id — `default`, or an extra\n * account's credential reference (e.g. `COMMANDCODE_API_KEY_2`). The\n * selected account serves whenever it is usable; an unknown id or an\n * exhausted selected account falls back to the first usable slot (automatic\n * rotation still applies). Unset means \"first usable account\".\n */\n activeAccount?: string\n /**\n * Model → account routing rules. Each rule lists catalog model ids to an\n * account slot id (`default`, or an extra account's credential reference).\n * When a request's model is in a rule's list and the routed account is\n * usable, that account serves — before the manual {@link activeAccount} and\n * the passive rotation order. A routed account that is exhausted or invalid\n * falls back to the normal selection, so the router is a hint, never a hard\n * gate. The first matching rule wins.\n */\n modelAccountRules?: CommandCodeModelAccountRule[]\n /**\n * Language override for the `/commandcode` Host-side command's user-facing\n * copy. Host commands cannot read the client's `ctx.locale`, so this is\n * the explicit knob: `'zh'` or `'en'`. Unset means the command reads\n * `LC_ALL`/`LANG` from the launching shell, falling back to `'zh'`. The\n * web settings page is unaffected — it follows the browser's language\n * preference on its own. Two surfaces, two independent locales. The\n * declared type is `string` (the schemastery `pattern` cannot narrow\n * literal types); an unknown value is treated as \"unset\" by\n * `pickCommandLocale`.\n */\n lang?: string\n}\n\nexport const Config: z<Config> = z.object({\n apiKeyEnv: z.string().role('credential-ref').default(DEFAULT_API_KEY_ENV),\n apiKey: z.string(),\n apiBase: z.string(),\n workingDir: z.string(),\n modelsCachePath: z.string(),\n requestTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n streamIdleTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n filterModelsByPlan: z.boolean(),\n accounts: z.array(z.object({\n label: z.string(),\n apiKeyEnv: z.string().role('credential-ref'),\n apiKey: z.string(),\n })),\n activeAccount: z.string(),\n modelAccountRules: z.array(z.object({\n models: z.array(z.string()),\n account: z.string(),\n })),\n lang: z.string().pattern(/^(zh|en)$/).default('zh' as const),\n})\n\n/** One resolution's complete request facts: connection plus credential reference. */\nexport interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {\n apiKeyEnv: CredentialRef\n}\n\n/**\n * The one explicit resolve step from raw config to validated connection\n * facts. Programmatic construction may bypass Schemastery normalization, so\n * every default is re-judged here — for the composition entry at load and for\n * each settings snapshot at its first use.\n */\nexport function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions {\n return {\n apiKeyEnv: credentialRef(config.apiKeyEnv ?? DEFAULT_API_KEY_ENV),\n apiBase: config.apiBase ?? DEFAULT_API_BASE,\n workingDir: config.workingDir ?? process.cwd(),\n modelsCachePath: config.modelsCachePath ?? DEFAULT_MODELS_CACHE_PATH,\n requestTimeoutMs: config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n streamIdleTimeoutMs: config.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n filterModelsByPlan: config.filterModelsByPlan ?? true,\n }\n}\n\nexport function apply(ctx: Context, config: Config): void {\n let current: () => Config = () => config\n let lastRaw: Config | undefined\n let lastGood: ResolvedCommandCodeOptions | undefined\n const options = (): ResolvedCommandCodeOptions => {\n const raw = current()\n if (raw === lastRaw && lastGood !== undefined) return lastGood\n const next = resolveAdapterOptions(raw)\n lastRaw = raw\n lastGood = next\n return next\n }\n options()\n\n // The account slots, rebuilt from the live config on every resolution so\n // a settings-page accounts change reaches the very next request. The\n // top-level apiKey/apiKeyEnv (+ the CLI auth file) form the default\n // account; each config.accounts entry adds one more.\n const slots = (): CommandCodeAccountSlot[] => {\n const raw = current()\n const list: CommandCodeAccountSlot[] = [{\n id: 'default',\n label: 'Default',\n ref: credentialRef(raw.apiKeyEnv ?? DEFAULT_API_KEY_ENV),\n literal: raw.apiKey,\n allowAuthFile: true,\n }]\n for (const [index, account] of (raw.accounts ?? []).entries()) {\n const refName = typeof account.apiKeyEnv === 'string' && account.apiKeyEnv.trim() !== ''\n ? account.apiKeyEnv.trim()\n : undefined\n const literal = typeof account.apiKey === 'string' && account.apiKey !== '' ? account.apiKey : undefined\n if (refName === undefined && literal === undefined) continue\n list.push({\n // Slot ids must survive account-list edits: an extra's id is its\n // credential reference (stable across reorders/removals), falling\n // back to the positional id only for literal-only composition\n // entries, which no settings document can name anyway.\n id: refName ?? `account-${index + 2}`,\n label: typeof account.label === 'string' && account.label.trim() !== ''\n ? account.label.trim()\n : `Account ${index + 2}`,\n ref: refName === undefined ? undefined : credentialRef(refName),\n literal,\n allowAuthFile: false,\n })\n }\n return list\n }\n\n // The manually selected account (settings page / config), re-read per\n // resolution like every other settings-backed fact.\n const preferredId = (): string | undefined => {\n const raw = current().activeAccount\n return typeof raw === 'string' && raw.trim() !== '' ? raw.trim() : undefined\n }\n\n const resolveRef = async (ref: ReturnType<typeof credentialRef>): Promise<string | undefined> => {\n const credentials = ctx.get('credentials')\n if (credentials !== undefined) {\n const hit = await credentials.resolve(ref)\n return hit?.value\n }\n const ambient = launchEnvironmentOf(ctx).get(ref)\n return ambient !== undefined && ambient.value.length > 0 ? ambient.value : undefined\n }\n\n // The multi-account pool: passive rotation only — a key is marked when a\n // request using it is actually rejected (429/401), and the marks are\n // re-checked against the live window limits only once every account is\n // marked, so the steady state costs zero extra API calls.\n // Explicit annotations break the pool↔adapter inference cycle (the pool's\n // probe calls the adapter; the adapter's rotation hook calls the pool).\n const pool: CommandCodeAccountPool = new CommandCodeAccountPool({\n slots,\n resolveRef,\n authFileKey: resolveAuthFileApiKey,\n // The adapter reference is assigned right below; the probe runs only at\n // request time, never during plugin startup.\n probeWindow: (apiKey: string) => adapter.probeFiveHourWindow(apiKey),\n preferredId,\n // Model → account routing rules, re-read per resolution like every\n // settings-backed fact.\n modelAccountRules: (): readonly CommandCodeModelAccountRule[] => current().modelAccountRules ?? [],\n })\n\n const resolveApiKey = async (connection: ResolvedCommandCodeOptions, model?: string): Promise<string> => {\n const resolved = await pool.resolveKey(model === undefined ? {} : { model })\n if (resolved !== undefined) {\n return assertUsableApiKey(resolved.key, 'llm-commandcode', resolved.slot.ref ?? `${resolved.slot.label} (config.apiKey)`)\n }\n const ref = connection.apiKeyEnv\n throw new LlmError(\n `llm-commandcode: no API key for provider route \"${PROVIDER}\"; store ${ref} through the`\n + ' credentials service (the web Models page writes it), export it in the launching'\n + ' environment, set config.apiKey, or run `command-code login` to write'\n + ' ~/.commandcode/auth.json',\n 'MISSING_CREDENTIAL',\n )\n }\n\n const adapter: CommandCodeAdapter<ResolvedCommandCodeOptions> = new CommandCodeAdapter({\n options,\n resolveApiKey,\n // Pre-stream 429/401: mark the rejected key and hand the adapter the next\n // account's key. When every account is exhausted the pool throws the\n // RATE_LIMIT/INVALID_CREDENTIAL error that names the earliest reset —\n // that error, not the raw 429, is what the caller sees.\n rotateApiKey: async (rejectedKey: string, rejection: 'rate-limit' | 'invalid-credential', _connection: ResolvedCommandCodeOptions, model?: string): Promise<string | undefined> => {\n pool.markRejected(rejectedKey, rejection)\n // Exclude the just-rejected key from probe-revival: a probe clearing its\n // window must not re-offer the same key within this request (the\n // adapter refuses already-tried keys); the next request picks it up.\n // The model rides along so model-routing rules pick the next account\n // for the same model.\n const resolved = await pool.resolveKey(\n model === undefined ? { exclude: rejectedKey } : { exclude: rejectedKey, model },\n )\n // Normalize like the initial resolution does: the pool keys its state\n // by the resolved key, so the adapter must send (and report back) the\n // same normalized form or the marks would miss.\n return resolved === undefined\n ? undefined\n : assertUsableApiKey(resolved.key, 'llm-commandcode', resolved.slot.ref ?? `${resolved.slot.label} (config.apiKey)`)\n },\n // The durable attachment service carries image bytes referenced by\n // ImageBlock; resolved lazily only when a request actually has images.\n resolveAttachments: () => {\n const attachments = ctx.get('attachments')\n return attachments === undefined ? undefined : attachments\n },\n })\n // The Models page card: a configurable provider with a settings address.\n // settingsPath [] means the whole `llm-commandcode` section configures it.\n ctx.llm.registerConfigurableProviders([\n { provider: PROVIDER, displayName: 'Command Code', settingsNs: NS, settingsPath: [] },\n ])\n // The live route: this is what makes models requestable under `commandcode`.\n ctx.llm.registerAdapter([PROVIDER], adapter)\n\n // Per-account usage for the /commandcode dashboard and the settings\n // page's account card: every pool account (configured or not) gets one\n // entry, each fetched with its own key so plan/credit facts never mix.\n const usageReports = async (): Promise<CommandCodeAccountsReport> => {\n // describeAccounts (not deduped) so two slots sharing one credential are\n // both reported as configured; the active badge follows the deduped\n // serving selection.\n const described = await pool.describeAccounts()\n const byId = new Map(described.map((account) => [account.slot.id, account]))\n const active = selectActiveAccount(await pool.resolvedAccounts(), preferredId())\n const entries = await Promise.all(slots().map(async (slot) => {\n const account = byId.get(slot.id)\n let report: CommandCodeUsageReport\n if (account === undefined) {\n report = { failures: [] }\n } else {\n try {\n report = await adapter.getUsage(account.key)\n } catch (error: unknown) {\n report = { failures: [error instanceof Error ? error.message : String(error)] }\n }\n }\n const state = account?.state\n // The mark mirrors servability: a usable account (never marked, or a\n // cooldown whose reset passed) shows no mark; a cooldown without a\n // known reset still shows \"rate-limit\" (it is not serving).\n const usable = accountUsable(state)\n return {\n id: slot.id,\n label: slot.label,\n configured: account !== undefined,\n active: account !== undefined && active?.slot.id === slot.id,\n mark: usable ? '' : state?.kind === 'disabled' ? 'invalid-credential' : 'rate-limit',\n cooldownUntil: !usable && state?.kind === 'cooldown' ? state.until : 0,\n report,\n }\n }))\n return { accounts: entries }\n }\n\n // The /commandcode usage command rides the optional `commands` service: a\n // child fiber injects it, so it registers whenever the profile mounts\n // dsh-commands and the fiber simply never activates when it does not.\n // The command runs Host-side and has no access to the client's locale\n // service, so its language is resolved here from `Config.lang` (explicit\n // override) and the launching shell's `LC_ALL`/`LANG` (inferred default);\n // resolved per invocation so a settings change reaches the next command\n // run without a restart.\n const commandLocale = (): LocaleId => pickCommandLocale(current().lang)\n ctx.inject(['commands'], (commandCtx) => {\n applyCommands(commandCtx, { adapter, reports: usageReports, getLocale: commandLocale })\n })\n\n // The settings page's account card: getUsage exposed to the browser through\n // the Typert Gateway (`commandcode/report`). Rides the optional `typert`\n // registry service, so profiles without the web stack never activate it.\n // The same service also exposes the browser-login flow: the Host binds a\n // loopback callback server (the official `command-code login` dance) and\n // stores the delivered key through the credentials seam under the same\n // reference the default slot resolves — no restart, no settings document.\n const loginFlow = new CommandCodeLoginFlow({\n apiBase: () => options().apiBase,\n storeKey: async ({ apiKey }: CommandCodeLoginCredentials): Promise<void> => {\n const ref = credentialRef(current().apiKeyEnv ?? DEFAULT_API_KEY_ENV)\n const credentials = ctx.get('credentials')\n if (credentials === undefined) {\n throw new Error('the credentials service is unavailable in this profile; paste the key manually')\n }\n await credentials.set(ref, apiKey)\n },\n })\n ctx.effect(() => () => loginFlow.dispose(), 'dsh-commandcode-provider: login flow')\n // The catalog for the settings page's routing-rule editor: served Host-side\n // from the adapter's cached/fetched catalog (sorted for picking), so the\n // browser never calls the Command Code API directly.\n const catalogForRules = async (): Promise<CommandCodeCatalog> => {\n const models = await adapter.listModels(PROVIDER)\n return {\n models: models.map((model) => ({ id: model.id, name: model.name.replace(/\\s*\\(CC\\)$/, '') })),\n }\n }\n applyUsageRemote(ctx, { adapter, reports: usageReports, login: loginFlow, listModels: catalogForRules })\n\n // Settings became an optional service in dsh 0.1.2. Register the section\n // through its provider when present; profiles without settings continue to\n // use the composition entry captured by `current` above.\n ctx.inject(['settings'], (settingsCtx) => {\n settingsCtx.settings.installSection(ctx, NS, Config, config, {\n setSource: (source) => {\n current = source\n },\n // Everything the adapter reads is resolved per request, so a settings\n // change needs no registration-level action.\n onChange: () => {},\n })\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["reject","createNetServer","createHttpServer"],"sources":["../src/accounts.ts","../src/adapter.ts","../src/command-locales.ts","../src/commands.ts","../src/usage-wire.ts","../src/login-wire.ts","../src/usage-remote.ts","../src/login.ts","../src/web-search.ts","../src/index.ts"],"sourcesContent":["/**\n * Multi-account pool for the Command Code provider (host side).\n *\n * One Command Code subscription (e.g. the Go plan's 5-hour window) is\n * metered; a user with several subscriptions wants a request that hits one\n * account's limit to continue on the next account without a visible failure.\n * This module owns that rotation:\n *\n * - {@link CommandCodeAccountPool.resolveKey} hands out the first account\n * whose key is not currently marked exhausted — or, when the request's\n * model matches a {@link CommandCodeModelAccountRule} and that account is\n * usable, the routed account — resolving each slot's key lazily (literal\n * config key → credential seam → launch environment → the official CLI\n * auth file for the default slot only).\n * - {@link CommandCodeAccountPool.markRejected} records a 429 (rate limit,\n * window unknown) or 401 (invalid key, disabled until the config changes)\n * against the exact API key, so several slots sharing one key share one\n * state.\n * - When every account is marked, the pool probes each key's\n * `/alpha/billing/credits` window limits (through the injected\n * {@link CommandCodeAccountPoolDeps.probeWindow}): an account whose window\n * no longer reports `exceeded` is revived, otherwise the pool throws a\n * `RATE_LIMIT` error naming the earliest reset time.\n *\n * The pool is deliberately cordis-free (like the adapter): every host fact\n * arrives through injected thunks, so node tests can drive it directly.\n *\n * @module dsh-commandcode-provider/accounts\n */\n\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { CredentialRef } from '@deepseek-ai/dsh-credentials'\n\n/**\n * Upper bound on the retry wait this pool attaches to the all-exhausted\n * `RATE_LIMIT` error. Must equal the `backoff.maxDelayMs` in the adapter's\n * `providerRetryPolicy` (which imports it from here): dsh-llm-retry honors a\n * provider-specified wait verbatim only at or below that cap — in normal mode\n * a LONGER attached wait makes the executor abandon the retry entirely\n * instead of falling back to local backoff, which would turn \"poll until the\n * window opens\" into \"fail now\".\n */\nexport const RETRY_MAX_DELAY_MS = 900_000\n\n/** One extra account's raw configuration (composition config or settings). */\nexport interface CommandCodeAccountConfig {\n /** Display label shown in the usage dashboard and settings page. */\n label?: string\n /** Credential reference (environment-variable style name) holding this account's API key. */\n apiKeyEnv?: string\n /** Literal API key (composition config only; never stored in settings). */\n apiKey?: string\n}\n\n/** One account slot after config normalization. */\nexport interface CommandCodeAccountSlot {\n /** Stable id: `default` for the implicit first account, `account-N` for extras. */\n id: string\n /** Display label (user-provided or generated). */\n label: string\n /** Credential reference resolved through the seam; undefined for literal-only slots. */\n ref?: CredentialRef | undefined\n /** Literal key from composition config. */\n literal?: string | undefined\n /** Whether the official CLI auth file may back this slot (default slot only). */\n allowAuthFile: boolean\n}\n\n/** Why a key stopped serving requests. */\nexport type AccountRejection = 'rate-limit' | 'invalid-credential'\n\n/** One key's rotation state. */\nexport interface CommandCodeAccountState {\n kind:\n /** Marked by a 429; the window's reset time is unknown until probed. */\n | 'unknown'\n /** Probed (or marked with a known reset): unusable until `until` (millis). */\n | 'cooldown'\n /** Marked by a 401: skipped until the stored credential changes. */\n | 'disabled'\n /** Human-readable reason for the mark (e.g. `rate limited (429)`). */\n reason: string\n /** Cooldown end in millis; 0 for the other kinds. */\n until: number\n}\n\n/** A slot paired with its resolved key (both pool-internal and UI-facing). */\nexport interface ResolvedAccount {\n slot: CommandCodeAccountSlot\n key: string\n /** The key's current rotation state; undefined means usable. */\n state: CommandCodeAccountState | undefined\n}\n\n/** Five-hour window facts probed from `/alpha/billing/credits`. */\nexport interface FiveHourWindowProbe {\n exceeded: boolean\n resetAt: number\n}\n\n/** Everything the pool needs from the host; all seams are injected. */\nexport interface CommandCodeAccountPoolDeps {\n /** The current account slots, re-read per resolution so settings changes apply live. */\n slots(): readonly CommandCodeAccountSlot[]\n /** Resolve one credential reference through the credentials service or the launch environment. */\n resolveRef(ref: CredentialRef): Promise<string | undefined>\n /** The official CLI auth-file key (`~/.commandcode/auth.json`); default slot only. */\n authFileKey(): string | undefined\n /** Probe one key's five-hour window; undefined when the probe itself failed. */\n probeWindow(apiKey: string): Promise<FiveHourWindowProbe | undefined>\n /**\n * The manually selected account (a slot id, e.g. `default` or an extra's\n * credential reference), re-read per resolution. The preferred account\n * serves whenever it is usable; an unknown id or an exhausted preferred\n * account falls back to the first usable slot.\n */\n preferredId?(): string | undefined\n /**\n * Model → account routing rules, re-read per resolution so settings changes\n * apply live. Each rule lists catalog model ids (see\n * {@link CommandCodeModelAccountRule}) to an account slot id. When the\n * request's model matches a rule and that account is usable, it serves\n * before the preferred/rotation selection; an unusable routed account falls\n * back to the normal selection (the router is a hint, never a hard gate).\n */\n modelAccountRules?(): readonly CommandCodeModelAccountRule[]\n}\n\n/**\n * One \"route these models to that account\" rule. `models` lists catalog ids\n * (`deepseek/deepseek-v4-pro`, …); `account` is a slot id (`default` or an\n * extra account's credential reference). A request whose model id is in the\n * list routes to that account. The first matching rule in list order wins.\n */\nexport interface CommandCodeModelAccountRule {\n /** Catalog model ids to match against the request's model. */\n models: string[]\n /** Account slot id to prefer for matching models. */\n account: string\n}\n\n/** A labeled, human-readable clock reading for error messages. */\nfunction clockLabel(ms: number): string {\n return new Date(ms).toLocaleString()\n}\n\n/**\n * Whether an account with this rotation state can serve a request right now.\n * `undefined` (never rejected) is usable; a cooldown becomes usable again\n * once its reset time passes; `unknown` (429, reset unprobed) and\n * `disabled` (401) are not.\n */\nexport function accountUsable(state: CommandCodeAccountState | undefined): boolean {\n if (state === undefined) return true\n if (state.kind === 'cooldown') return state.until > 0 && Date.now() >= state.until\n return false\n}\n\n/**\n * Pick the account that should serve now: the manually preferred slot when it\n * is usable, otherwise the first usable account in rotation order; undefined\n * when no account is usable. Shared by the pool (request path) and the plugin\n * entry (the usage view's active badge) so both always agree.\n */\nexport function selectActiveAccount(\n accounts: readonly ResolvedAccount[],\n preferredId: string | undefined,\n): ResolvedAccount | undefined {\n const usable = accounts.filter((account) => accountUsable(account.state))\n if (preferredId !== undefined) {\n const preferred = usable.find((account) => account.slot.id === preferredId)\n if (preferred !== undefined) return preferred\n }\n return usable[0]\n}\n\n/**\n * The first routing rule whose model list contains the request's model id.\n * Undefined when no rule matches.\n */\nexport function matchModelRule(\n model: string,\n rules: readonly CommandCodeModelAccountRule[] | undefined,\n): CommandCodeModelAccountRule | undefined {\n if (model === '' || rules === undefined || rules.length === 0) return undefined\n for (const rule of rules) {\n if (rule.models.includes(model)) return rule\n }\n return undefined\n}\n\n/**\n * The routed account for a request's model: the first usable account whose\n * slot id matches the first matching rule's target. Undefined when no rule\n * matches or the routed account is not usable (the caller then falls back to\n * the normal preferred/rotation selection).\n */\nexport function selectAccountForModel(\n accounts: readonly ResolvedAccount[],\n model: string,\n rules: readonly CommandCodeModelAccountRule[] | undefined,\n): ResolvedAccount | undefined {\n const rule = matchModelRule(model, rules)\n if (rule === undefined) return undefined\n return accounts.find((account) => account.slot.id === rule.account && accountUsable(account.state))\n}\n\n/**\n * The account pool. Rotation state is keyed by API key (never logged), so two\n * slots resolving to the same credential share one mark, and a key changed in\n * the credentials service starts with a clean slate.\n */\nexport class CommandCodeAccountPool {\n /** Rotation state by API key. */\n private readonly states = new Map<string, CommandCodeAccountState>()\n constructor(private readonly deps: CommandCodeAccountPoolDeps) {}\n\n /**\n * Resolve every slot's key, deduplicated by key (first slot wins). Slots\n * without any resolvable key are omitted — they still appear in the\n * settings page as unconfigured, they just cannot serve requests.\n */\n async resolvedAccounts(): Promise<ResolvedAccount[]> {\n const out: ResolvedAccount[] = []\n const seen = new Set<string>()\n for (const slot of this.deps.slots()) {\n const key = await this.resolveSlotKey(slot)\n if (key === undefined || seen.has(key)) continue\n seen.add(key)\n out.push({ slot, key, state: this.states.get(key) })\n }\n return out\n }\n\n /**\n * Every slot paired with its resolved key and rotation state — NOT\n * deduplicated: two slots sharing one credential both appear (the usage\n * view reports them individually), while slots without any resolvable key\n * are omitted. The serving path uses {@link resolvedAccounts} instead.\n */\n async describeAccounts(): Promise<ResolvedAccount[]> {\n const out: ResolvedAccount[] = []\n for (const slot of this.deps.slots()) {\n const key = await this.resolveSlotKey(slot)\n if (key === undefined) continue\n out.push({ slot, key, state: this.states.get(key) })\n }\n return out\n }\n\n /**\n * Hand out the key for a request: the model-routed account when the\n * request's model matches a rule (and that account is usable), else the\n * manually preferred account when usable, else the first usable account in\n * rotation order. Returns `undefined` when no account resolves any key at\n * all (the caller then reports the missing credential). Throws\n * `RATE_LIMIT` — naming the earliest window reset — or\n * `INVALID_CREDENTIAL` when accounts exist but none can serve.\n *\n * `options.model` is the request's model id; routing rules re-read per\n * resolution, so a settings change applies live.\n *\n * `options.exclude` skips one key during the probe-revival pass: the\n * rotation hook excludes the just-rejected key so a probe that clears its\n * window cannot re-offer the same key within the same request (the adapter\n * refuses already-tried keys; the next request picks the revived key up).\n */\n async resolveKey(options?: { exclude?: string; model?: string }): Promise<{ key: string; slot: CommandCodeAccountSlot } | undefined> {\n const accounts = await this.resolvedAccounts()\n if (accounts.length === 0) {\n return undefined\n }\n const routed = selectAccountForModel(accounts, options?.model ?? '', this.deps.modelAccountRules?.())\n if (routed !== undefined) return this.pick(routed)\n const chosen = selectActiveAccount(accounts, this.deps.preferredId?.())\n if (chosen !== undefined) return this.pick(chosen)\n\n // Every key is marked: probe the real windows before giving up. Disabled\n // (401) keys are not probed — an invalid key stays invalid.\n await Promise.all(accounts.map(async (account) => {\n if (account.state?.kind === 'disabled') return\n if (options?.exclude !== undefined && account.key === options.exclude) return\n const probe = await this.deps.probeWindow(account.key)\n if (probe === undefined) return\n if (!probe.exceeded) {\n this.states.delete(account.key)\n } else {\n this.states.set(account.key, {\n kind: 'cooldown',\n reason: account.state?.reason ?? 'rate limited (429)',\n until: probe.resetAt,\n })\n }\n }))\n\n const revived = selectActiveAccount(await this.resolvedAccounts(), this.deps.preferredId?.())\n if (revived !== undefined) return this.pick(revived)\n\n const latest = await this.resolvedAccounts()\n const disabled = latest.filter((account) => account.state?.kind === 'disabled')\n if (disabled.length === latest.length) {\n // Bilingual: the harness UI renders this message verbatim inside its\n // (already localized) retry/turn-error chrome, so both languages ride\n // in one string — English first, then the Chinese reading.\n throw new LlmError(\n `llm-commandcode: every configured Command Code account (${latest.length}) was rejected with 401`\n + ' — check the stored API keys (Models page / settings) or the auth file'\n + `;已配置的 ${latest.length} 个 Command Code 账户密钥均被拒绝(401)`\n + '——请在设置页检查存储的 API 密钥,或重新运行 command-code login',\n 'INVALID_CREDENTIAL',\n )\n }\n const resets = latest\n .map((account) => account.state)\n .filter((state): state is CommandCodeAccountState => state !== undefined && state.kind === 'cooldown' && state.until > 0)\n .map((state) => state.until)\n const earliest = resets.length > 0 ? Math.min(...resets) : 0\n // Hand dsh-llm-retry the exact wait until the earliest known reset so the\n // retry policy sleeps through the window instead of polling at its\n // backoff cadence. Capped at RETRY_MAX_DELAY_MS: the executor honors a\n // provider wait verbatim only at or below the policy's maxDelayMs — a\n // LONGER attached wait makes it abandon the retry entirely (normal mode),\n // which would turn \"poll until the window opens\" into \"fail now\". Longer\n // resets simply ride the capped local backoff and the probe revival.\n const wait = earliest > 0 ? Math.max(1000, earliest - Date.now()) : 0\n throw new LlmError(\n `llm-commandcode: all ${latest.length} Command Code account(s) have exhausted their usage window`\n + (earliest > 0 ? `; the earliest window resets at ${clockLabel(earliest)}` : '')\n + ' — requests will succeed again after the reset (or add another account)'\n + `;已用尽全部 ${latest.length} 个 Command Code 账户的用量窗口`\n + (earliest > 0 ? `,最早的重置时间为 ${clockLabel(earliest)}` : '')\n + '——窗口重置后请求会自动恢复(也可以添加更多账户)',\n 'RATE_LIMIT',\n wait > 0 && wait <= RETRY_MAX_DELAY_MS ? { providerRetryAfterMs: wait } : undefined,\n )\n }\n\n /**\n * Record a rejection against one key. `rate-limit` (429) marks the key\n * exhausted with an unknown reset (probed lazily at the next resolution\n * once every account is marked); `invalid-credential` (401) disables the\n * key until the stored credential changes.\n */\n markRejected(apiKey: string, rejection: AccountRejection): void {\n if (rejection === 'invalid-credential') {\n this.states.set(apiKey, { kind: 'disabled', reason: 'invalid API key (401)', until: 0 })\n } else {\n this.states.set(apiKey, { kind: 'unknown', reason: 'rate limited (429)', until: 0 })\n }\n }\n\n /** One account's key: literal → credential seam → auth file (default slot). */\n private async resolveSlotKey(slot: CommandCodeAccountSlot): Promise<string | undefined> {\n if (slot.literal !== undefined && slot.literal !== '') return slot.literal\n if (slot.ref !== undefined) {\n const hit = await this.deps.resolveRef(slot.ref)\n if (hit !== undefined && hit !== '') return hit\n }\n if (slot.allowAuthFile) {\n const fromFile = this.deps.authFileKey()\n if (fromFile !== undefined && fromFile !== '') return fromFile\n }\n return undefined\n }\n\n /** Hand out the chosen account's key. */\n private pick(account: ResolvedAccount): { key: string; slot: CommandCodeAccountSlot } {\n return { key: account.key, slot: account.slot }\n }\n}\n","/**\n * DeepSeek Harness LLM adapter for the Command Code Provider API.\n *\n * Ported from pi-commandcode-provider@0.5.1 (MIT). This is an unofficial,\n * community-maintained integration; you need your own Command Code account\n * and API key or subscription, and Command Code's terms apply.\n *\n * Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;\n * re-verified against command-code@1.39.2 — endpoints, request shape, and\n * stream events unchanged):\n * POST {apiBase}/alpha/generate\n * body: { config, memory, taste, skills, params: { model, messages, tools,\n * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }\n * SSE-ish JSONL events: text-delta | reasoning-start/delta/end | tool-call\n * | tool-result | finish | error\n * Model catalog: GET {apiBase}/provider/v1/models -> { object: 'list', data: [...] }\n *\n * The adapter is deliberately free of cordis/schemastery: it receives a\n * per-request options thunk and an API-key resolver from the plugin entry\n * (src/index.ts), so a settings change reaches the very next request.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { randomUUID } from 'node:crypto'\n\nimport type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\n\nimport {\n attributionHeaders,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\n ToolCallId,\n errorChain,\n resolveRetryPolicy,\n type ResolvedRetryPolicy,\n type ContentBlock,\n type FinishReason,\n type GenerateOptions,\n type LlmModelInfo,\n type LlmProviderInfo,\n type LlmResolvedModelInfo,\n type Message,\n type StreamChunk,\n type TokenUsage,\n} from '@deepseek-ai/dsh-llm'\nimport { RETRY_MAX_DELAY_MS } from './accounts.ts'\n\n// ---------------------------------------------------------------------------\n// Static capability snapshot (from the official command-code@1.39.2 bundled\n// model catalog, dist/cli.mjs). The Provider API does not expose reasoning\n// metadata; models omitted here let Command Code choose their reasoning\n// depth, matching the official CLI.\n// ---------------------------------------------------------------------------\n\nexport const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>> = {\n // Re-verified against the authoritative command-code@1.39.2 bundled model\n // table (dist/cli.mjs, the provider effort map): exactly these models carry\n // selectable efforts. Models marked 'reasoning:!0' without efforts\n // (e.g. Kimi K3, MiniMax M3, Muse Spark 1.1, Tencent Hy3, GLM-5/5.1/5.2-Fast)\n // think automatically and are absent here - the CLI omits\n // 'reasoning_effort' for them, so the picker must not offer a selector. Do\n // NOT add entries from the OAuth provider tables (anthropic/openai) - only\n // the Provider-API table is authoritative for this plugin's route.\n // `stealth/ox-alpha` (['low', 'high', 'max']) was removed in\n // command-code@1.34.0 when its preview ended; its successor,\n // `z-ai/glm-5.3-flash`, ships the same effort set.\n // `tencent/hy4-preview` gained ['low', 'medium', 'high'] in\n // command-code@1.38.0 (it previously thought automatically with no\n // selectable levels).\n 'Qwen/Qwen3.8-Max': ['low', 'medium', 'xhigh'],\n 'Qwen/Qwen3.8-27B': ['low', 'medium', 'xhigh'],\n 'Qwen/Qwen3.8-Flash': ['low', 'medium', 'xhigh'],\n 'claude-fable-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-7': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-8': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-4-6': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n // `deepseek/deepseek-v4-flash-fast` joined in command-code@1.39.0\n // (\"Add DeepSeek V4 Flash Fast\"); 1.39.1 dropped `medium` for it, and\n // the 1.39.2 table ships ['low', 'high', 'max'].\n 'deepseek/deepseek-v4-flash-fast': ['low', 'high', 'max'],\n 'deepseek/deepseek-v4-flash': ['high', 'max'],\n 'deepseek/deepseek-v4-flash-vision-exp': ['high', 'max'],\n 'deepseek/deepseek-v4-pro': ['high', 'max'],\n 'google/gemini-3.1-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.6-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.7-flash': ['low', 'medium', 'high'],\n 'gpt-5.3-codex': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4-mini': ['low', 'medium', 'high'],\n 'gpt-5.5': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.6-luna': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-sol': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-terra': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'sakana/fugu-ultra': ['high', 'xhigh'],\n 'tencent/hy4-preview': ['low', 'medium', 'high'],\n 'xai/grok-4.5': ['low', 'medium', 'high'],\n 'xai/grok-4.6': ['low', 'medium', 'high', 'xhigh'],\n 'z-ai/glm-5.3-flash': ['low', 'high', 'max'],\n 'zai-org/GLM-5.2': ['high', 'max'],\n 'zai-org/GLM-5.3': ['low', 'high', 'max'],\n}\n\n/**\n * Models whose Capabilities include Vision, per the official Command Code\n * model registry (`https://commandcode.ai/docs/reference/cli/models`, generated\n * from the same registry as `cmd --list-models` / the `/model` picker).\n *\n * The Provider API does not expose modality metadata, so this snapshot is the\n * source of truth for image-input gating. Command Code's own CLI falls back to\n * a client-side VISION side-call for text-only models; this adapter does not\n * reproduce that interactive feature, so images sent to a model outside this\n * list are refused loudly (`UNSUPPORTED_CONTENT`) instead of being dropped or\n * sent to a model that cannot read them.\n *\n * Keep in sync with the official registry when new models ship (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_IMAGE_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Plus',\n 'Qwen/Qwen3.8-27B',\n 'Qwen/Qwen3.8-Flash',\n 'Qwen/Qwen3.8-Max',\n 'claude-fable-5',\n 'claude-haiku-4-5-20251001',\n 'claude-opus-4-7',\n 'claude-opus-4-8',\n 'claude-opus-5',\n 'claude-sonnet-4-6',\n 'claude-sonnet-5',\n 'deepseek/deepseek-v4-flash-vision-exp',\n 'google/gemini-3.1-flash-lite',\n 'google/gemini-3.5-flash',\n 'google/gemini-3.5-flash-lite',\n 'google/gemini-3.6-flash',\n 'google/gemini-3.7-flash',\n 'gpt-5.3-codex',\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.5',\n 'gpt-5.6-luna',\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n 'minimax/minimax-m3-free',\n 'moonshotai/Kimi-K2.5',\n 'moonshotai/Kimi-K2.6',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'moonshotai/Kimi-K3',\n 'sakana/fugu-ultra',\n 'stepfun/Step-3.7-Flash',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'xai/grok-4.5',\n 'xiaomi/mimo-v2.5',\n 'z-ai/glm-5.3-flash',\n])\n\n/**\n * Models the official CLI's model table (command-code@1.39.2) marks\n * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they\n * think automatically, with Command Code driving the depth. This is the\n * authoritative \"thinks, effort not adjustable\" set: `KNOWN_EFFORTS` (which\n * mirrors the CLI's effort map exactly) stays the sole source for selectable\n * effort levels, and this snapshot is not surfaced in the picker's compact\n * description — it exists for programmatic consumers.\n *\n * Source: the command-code@1.39.2 bundled model table (dist/cli.mjs),\n * cross-checked with https://commandcode.ai/docs/reference/cli/models.\n * (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it\n * selectable `['low', 'high', 'max']` efforts; the preview then ended in\n * 1.34.0, removing the model from the catalog entirely. `tencent/hy4-preview`\n * joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M\n * context, routed through OpenRouter — then gained selectable\n * `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to\n * `KNOWN_EFFORTS`.)\n * Keep in sync via the dsh-commandcode-upstream skill.\n */\nexport const KNOWN_THINKING_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Max-Preview',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Max',\n 'Qwen/Qwen3.7-Plus',\n 'minimax/minimax-m3-free',\n 'moonshotai/Kimi-K3',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'stepfun/Step-3.5-Flash',\n 'stepfun/Step-3.7-Flash',\n 'tencent/hy3-paid',\n 'nvidia/nemotron-3-ultra-550b-a55b',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'poolside/laguna-s-2.1-free',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n])\n\n/**\n * The minimum subscription plan a model is included in, per the official plan\n * pages (`/docs/plans/go`, `/docs/plans/goat`, `/docs/plans/pro`, `/docs/plans/max`\n * and `/docs/resources/pricing-limits`). Each plan's model list is a superset of\n * the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max. Models absent from every\n * plan list (Claude Opus/Fable, Fugu Ultra) are Provider-tier.\n *\n * The Provider API exposes no plan metadata, so this snapshot is the source of\n * truth for the picker's plan annotation — it answers \"which plan do I need to\n * actually use this model?\" at a glance. Plan labels use the official tier\n * names (`Go`, `GOAT`, `Pro`, `Provider`), with `Max` implying Provider.\n *\n * Keep in sync with the official plan pages when they change (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_PLANS: Readonly<Record<string, string>> = {\n // --- Go (42) ---\n 'MiniMaxAI/MiniMax-M2.5': 'go',\n 'MiniMaxAI/MiniMax-M2.7': 'go',\n 'MiniMaxAI/MiniMax-M3': 'go',\n 'Qwen/Qwen3.6-Max-Preview': 'go',\n 'Qwen/Qwen3.6-Plus': 'go',\n 'Qwen/Qwen3.7-Flash': 'go',\n 'Qwen/Qwen3.7-Max': 'go',\n 'Qwen/Qwen3.7-Plus': 'go',\n 'Qwen/Qwen3.8-27B': 'go',\n 'Qwen/Qwen3.8-Flash': 'go',\n 'Qwen/Qwen3.8-Max': 'go',\n // command-code@1.39.0 added DeepSeek V4 Flash Fast; it is a Go-tier model\n // alongside the rest of the DeepSeek V4 family.\n 'deepseek/deepseek-v4-flash-fast': 'go',\n 'deepseek/deepseek-v4-flash': 'go',\n 'deepseek/deepseek-v4-flash-vision-exp': 'go',\n 'deepseek/deepseek-v4-pro': 'go',\n 'gpt-5.6-luna': 'go',\n 'inclusionai/ling-3.0-flash-free': 'go',\n 'meta/muse-spark-1.2-contributor': 'go',\n 'minimax/minimax-m2.7-free': 'go',\n 'minimax/minimax-m3-free': 'go',\n 'moonshotai/Kimi-K2.5': 'go',\n 'moonshotai/Kimi-K2.6': 'go',\n 'moonshotai/Kimi-K2.7-Code': 'go',\n 'moonshotai/Kimi-K2.7-Code-Highspeed': 'go',\n 'moonshotai/Kimi-K3': 'go',\n 'nvidia/nemotron-3-ultra-550b-a55b': 'go',\n 'poolside/laguna-s-2.1-free': 'go',\n 'stepfun/Step-3.5-Flash': 'go',\n 'stepfun/Step-3.7-Flash': 'go',\n 'tencent/Hy3': 'go',\n 'tencent/hy3-paid': 'go',\n 'tencent/hy4-preview': 'go',\n 'thinkingmachines/inkling': 'go',\n 'thinkingmachines/inkling-small': 'go',\n 'xai/grok-4.5': 'go',\n 'xiaomi/mimo-v2.5': 'go',\n 'xiaomi/mimo-v2.5-pro': 'go',\n 'z-ai/glm-5.3-flash': 'go',\n 'zai-org/GLM-5': 'go',\n 'zai-org/GLM-5.1': 'go',\n 'zai-org/GLM-5.2': 'go',\n 'zai-org/GLM-5.2-Fast': 'go',\n 'zai-org/GLM-5.3': 'go',\n // --- GOAT (4 more) ---\n 'google/gemini-3.7-flash': 'goat',\n 'gpt-5.6-sol': 'goat',\n 'meta/muse-spark-1.2': 'goat',\n 'xai/grok-4.6': 'goat',\n // --- Pro (13 more) ---\n 'claude-haiku-4-5-20251001': 'pro',\n 'claude-sonnet-4-6': 'pro',\n 'claude-sonnet-5': 'pro',\n 'google/gemini-3.1-flash-lite': 'pro',\n 'google/gemini-3.5-flash': 'pro',\n 'google/gemini-3.5-flash-lite': 'pro',\n 'google/gemini-3.6-flash': 'pro',\n 'gpt-5.3-codex': 'pro',\n 'gpt-5.4': 'pro',\n 'gpt-5.4-mini': 'pro',\n 'gpt-5.5': 'pro',\n 'gpt-5.6-terra': 'pro',\n 'meta/muse-spark-1.1': 'pro',\n // --- Provider / Max (5) ---\n 'claude-fable-5': 'provider',\n 'claude-opus-4-7': 'provider',\n 'claude-opus-4-8': 'provider',\n 'claude-opus-5': 'provider',\n 'sakana/fugu-ultra': 'provider',\n}\n\n/** Official display labels for each plan tier. */\nexport const PLAN_LABELS: Readonly<Record<string, string>> = {\n go: 'Go',\n goat: 'GOAT',\n pro: 'Pro',\n provider: 'Provider',\n max: 'Max',\n}\n\n/**\n * Plan-tier sort weights, low to high. Models outside the snapshot (unknown\n * plans) sort after every known tier, keeping known models predictable.\n */\nexport const PLAN_ORDER: Readonly<Record<string, number>> = {\n go: 0,\n goat: 1,\n pro: 2,\n provider: 3,\n max: 4,\n}\n\n/**\n * Whether a model is free (requests cost no credits), per the pricing page's\n * deals (`KNOWN_DEALS` `free: true`). Free models lead the picker regardless\n * of tier — they are usable by every account, so they are the best default\n * candidates.\n */\nexport function isFreeModel(modelId: string): boolean {\n return KNOWN_DEALS[modelId]?.free === true\n}\n\n/**\n * Comparator for the model picker: free models first (zero credit cost, usable\n * by every account), then by plan tier (lowest first), then by model name,\n * then by id as a tiebreak. Models with no known plan sort last.\n */\nexport function compareByPlan(\n a: { id: string; name: string },\n b: { id: string; name: string },\n): number {\n const freeDelta = Number(isFreeModel(b.id)) - Number(isFreeModel(a.id))\n if (freeDelta !== 0) return freeDelta\n const pa = PLAN_ORDER[KNOWN_PLANS[a.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n const pb = PLAN_ORDER[KNOWN_PLANS[b.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n if (pa !== pb) return pa - pb\n const nameDiff = a.name.localeCompare(b.name)\n if (nameDiff !== 0) return nameDiff\n return a.id.localeCompare(b.id)\n}\n\n/**\n * Subscription plan table, synced from the official CLI bundle's plan maps\n * (`Nn`/`$n` in command-code@1.31.0 `dist/cli.mjs`, re-verified unchanged\n * against 1.32.2 where they appear as `Zn`/`er`): subscription `planId`\n * prefix → display name and the plan's monthly credit total. This is the\n * account's own subscription (from `/alpha/billing/subscriptions`) — distinct\n * from {@link KNOWN_PLANS}, which maps catalog models to their minimum tier.\n *\n * `tierWeight` is plugin-added (not from the CLI maps): the plan's rank on\n * the {@link PLAN_ORDER} scale, used by the picker's plan filter\n * ({@link modelVisibleInPlan}) to hide models above the account's tier.\n */\nexport const KNOWN_SUBSCRIPTION_PLANS: Readonly<Record<string, { name: string; monthlyCredits: number; tierWeight: number }>> = {\n 'individual-go': { name: 'Go', monthlyCredits: 10, tierWeight: 0 },\n 'individual-goat': { name: 'GOAT', monthlyCredits: 70, tierWeight: 1 },\n 'individual-pro': { name: 'Pro', monthlyCredits: 30, tierWeight: 2 },\n 'individual-pro-v1': { name: 'Pro', monthlyCredits: 80, tierWeight: 2 },\n 'individual-provider': { name: 'Provider', monthlyCredits: 15, tierWeight: 3 },\n 'individual-max': { name: 'Max', monthlyCredits: 150, tierWeight: 4 },\n 'individual-ultra': { name: 'Ultra', monthlyCredits: 300, tierWeight: 4 },\n 'teams-pro': { name: 'Teams Pro', monthlyCredits: 40, tierWeight: 2 },\n}\n\n/** Plan-id prefixes, longest first — the CLI's prefix-match order. */\nconst SUBSCRIPTION_PLAN_PREFIXES = Object.keys(KNOWN_SUBSCRIPTION_PLANS).sort((a, b) => b.length - a.length)\n\n/**\n * Resolve a subscription `planId` (e.g. `individual-pro-v1`) to its display\n * name and monthly credit total, mirroring the CLI's `getPlanInfo`:\n * normalize (lowercase, `_` → `-`), then longest-prefix match so\n * `individual-pro-v1` wins over `individual-pro`. Unknown ids return\n * `undefined`.\n */\nexport function subscriptionPlanInfo(planId: string): { name: string; monthlyCredits: number; tierWeight: number } | undefined {\n const normalized = planId.toLowerCase().replace(/_/g, '-')\n const prefix = SUBSCRIPTION_PLAN_PREFIXES.find((candidate) => normalized.startsWith(candidate))\n return prefix === undefined ? undefined : KNOWN_SUBSCRIPTION_PLANS[prefix]\n}\n\n/**\n * The billing facts the picker's plan filter needs, fetched by mirroring the\n * CLI's `createBilling` flow (whoami → orgId, then `/alpha/billing/subscriptions`\n * for the plan id and `/alpha/billing/credits` for the on-demand balances).\n */\nexport interface CommandCodeBillingAccess {\n /** Account plan tier weight on the {@link PLAN_ORDER} scale; undefined when the plan is unknown. */\n tierWeight: number | undefined\n /**\n * Purchased + free on-demand credit balance. The official access model\n * (`evaluateModelAccess` in the CLI) allows every model when the account\n * holds any on-demand credits — the plan gate only applies at zero balance.\n */\n onDemandCredits: number\n}\n\n/**\n * Whether the picker lists `modelId` for an account with the given billing\n * access. Fails open at every uncertainty: no billing data, an unknown plan,\n * or a model outside {@link KNOWN_PLANS} all keep the model visible — the\n * server remains the final gate (`403 MODEL_NOT_IN_PLAN`).\n */\nexport function modelVisibleInPlan(modelId: string, access: CommandCodeBillingAccess | undefined): boolean {\n if (access === undefined) return true\n if (access.onDemandCredits > 0) return true\n if (access.tierWeight === undefined) return true\n const tier = KNOWN_PLANS[modelId]\n if (tier === undefined) return true\n const weight = PLAN_ORDER[tier]\n if (weight === undefined) return true\n return weight <= access.tierWeight\n}\n\n/**\n * Active pricing deals per the official pricing page\n * (`/docs/resources/pricing-limits#deals`). Each entry records the model's\n * promotional label and — critically — when it expires, so the picker never\n * shows a stale discount after the plugin's snapshot has gone out of date.\n *\n * - `expiresAt` is an ISO timestamp. When it is in the past (checked at\n * render time against `Date.now()`), the deal label is hidden until the\n * snapshot is refreshed from the official page. `undefined` means\n * \"no expiry\" (permanent).\n * - `free` marks models whose requests cost no credits (Laguna S 2.1), shown\n * as a `FREE` badge; it degrades to a plain discount once the deal lapses.\n *\n * Keep in sync with the official pricing page when deals change (see the\n * dsh-commandcode-upstream skill).\n */\nexport interface KnownDeal {\n /** Promotional label, e.g. \"50% off\" or \"2× usage\". */\n label: string\n /** Deal end date (ISO). `undefined` = permanent / no expiry. */\n expiresAt?: string\n /** Model is free (requests cost no credits). */\n free?: boolean\n}\n\nexport const KNOWN_DEALS: Readonly<Record<string, KnownDeal>> = {\n // Gemini 3.7 Flash's 50% off deal was retired from the official pricing\n // page's #deals section (command-code@1.38.2 sync); the model now shows at\n // full price.\n 'MiniMaxAI/MiniMax-M3': { label: '50% off' },\n 'xiaomi/mimo-v2.5-pro': { label: '99% off' },\n 'xiaomi/mimo-v2.5': { label: '98% off' },\n // The MiniMax M3 / M2.7 FREE promo variants were retired in\n // command-code@1.39.2 (\"Retire MiniMax free models\"): the official CLI hides\n // them and the pricing page no longer lists them as free, so the free\n // entries that shipped through 1.38.2 (with a 2026-09-05 expiry) are removed\n // here rather than left to lapse on schedule. The paid MiniMax M3 / M2.7\n // rows keep their own rates.\n 'poolside/laguna-s-2.1-free': { label: 'FREE', free: true },\n}\n\n/**\n * Models with time-of-day (peak/off-peak) pricing, per the official pricing\n * page (`/docs/resources/pricing-limits`). Since 2026-08-16 16:00 UTC, DeepSeek\n * charges by the hour: peak hours are 01:00–04:00 and 06:00–10:00 UTC (7h/day,\n * full price); the other 17 hours are off-peak at half price. The V4 Flash\n * Vision (exp) variant (command-code@1.32.0) shares the V4 Flash windows and\n * peak prices ($0.44/$1.32) — each row's hover annotation states exactly 2×\n * that row's displayed off-peak prices. The picker shows the\n * *current* state as a compact\n * label (`Peak`/`Half`) matching the English noun style of the other markers\n * (`Image`, `FREE`), so a developer can tell at a glance whether calling the\n * model right now is cheap or expensive.\n *\n * Extraction caution: in the page's HTML each annotation div sits inside its\n * OWN row's container, immediately before the NEXT row starts — flattening\n * the page to text makes every annotation look like it belongs to the model\n * printed after it. Verify membership against the enclosing row and the 2×\n * price relation, not the flat-text neighbor.\n *\n * Keep in sync with the official pricing page when the model set or the peak\n * windows change (see the dsh-commandcode-upstream skill).\n */\nexport const KNOWN_PEAK_PRICING: ReadonlySet<string> = new Set([\n 'deepseek/deepseek-v4-pro',\n 'deepseek/deepseek-v4-flash',\n 'deepseek/deepseek-v4-flash-vision-exp',\n // Added in command-code@1.39.0: DeepSeek V4 Flash Fast shares the V4 Flash\n // peak windows and peak prices ($0.44 / $1.32 per the pricing page's\n // off-peak annotation).\n 'deepseek/deepseek-v4-flash-fast',\n])\n\n/** Peak hours (UTC, hour-of-day range end-exclusive): 01–03 and 06–09. */\nconst PEAK_HOUR_RANGES: ReadonlyArray<readonly [number, number]> = [\n [1, 4],\n [6, 10],\n]\n\n/**\n * Whether `now` (defaults to `Date.now()`) falls in a peak-pricing hour for\n * time-of-day-priced models. `undefined` for models outside the snapshot.\n */\nexport function peakPricingState(\n modelId: string,\n now: number = Date.now(),\n): 'peak' | 'off-peak' | undefined {\n if (!KNOWN_PEAK_PRICING.has(modelId)) return undefined\n const hour = new Date(now).getUTCHours()\n const inPeak = PEAK_HOUR_RANGES.some(([start, end]) => hour >= start && hour < end)\n return inPeak ? 'peak' : 'off-peak'\n}\n\n/**\n * Compact label for the current peak/off-peak state: `Peak` (full price) or\n * `Half` (off-peak, half price). These English nouns match the picker's other\n * markers (`Go`, `Image`, `FREE`), and since they appear only on time-of-day\n * priced models they double as a \"priced by the hour\" signal. Returns undefined\n * for models without time-of-day pricing.\n */\nexport function peakPricingLabel(\n modelId: string,\n now: number = Date.now(),\n): string | undefined {\n const state = peakPricingState(modelId, now)\n if (state === undefined) return undefined\n return state === 'peak' ? 'Peak' : 'Half'\n}\n\nexport const COMMAND_CODE_CLI_VERSION = '1.39.2'\nexport const DEFAULT_API_BASE = 'https://api.commandcode.ai'\nexport const DEFAULT_GENERATE_MAX_TOKENS = 64_000\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 65_536\nexport const MODELS_TIMEOUT_MS = 10_000\n/** How long the picker's plan-filter billing facts stay cached before refetching. */\nexport const BILLING_ACCESS_TTL_MS = 5 * 60_000\n\n/**\n * Subscription statuses the CLI treats as live (`Mr` in command-code's\n * cli.mjs): the plan gate applies only under one of these.\n */\nconst ACTIVE_SUBSCRIPTION_STATUSES: ReadonlySet<string> = new Set(['active', 'trialing', 'past_due'])\n/** Head-of-request timeout: how long to wait for the first response byte. */\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 60_000\n/** Stream idle timeout: a generation that stalls this long is a dead connection. */\nexport const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000\nconst MODEL_CACHE_VERSION = 1\n\n// ---------------------------------------------------------------------------\n// Small helpers (ported from converters.ts / models.ts)\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Official display label for a model's minimum plan, or undefined for models\n * outside the snapshot (e.g. future catalog additions).\n */\nexport function planLabel(modelId: string): string | undefined {\n const plan = KNOWN_PLANS[modelId]\n return plan === undefined ? undefined : PLAN_LABELS[plan]\n}\n\n/**\n * The active deal label for a model, or undefined when the model has no deal\n * or the deal has expired. Expiry is judged against `now` (defaults to\n * `Date.now()`), so a snapshot that has gone stale stops showing its discount\n * the moment the official end date passes — the user never believes a lapsed\n * deal is still live. Permanent deals (no `expiresAt`) never lapse.\n */\nexport function dealLabel(modelId: string, now: number = Date.now()): string | undefined {\n const deal = KNOWN_DEALS[modelId]\n if (deal === undefined) return undefined\n if (deal.expiresAt !== undefined && now >= Date.parse(deal.expiresAt)) return undefined\n return deal.label\n}\n\n/**\n * Compact human-readable context window, e.g. `1_000_000 -> \"1M\"`,\n * `256_000 -> \"256K\"`, `262_144 -> \"256K\"` (floor to the nearest K).\n * Returns undefined for unknown/absent sizes.\n */\nexport function formatContext(contextWindow: number | undefined): string | undefined {\n if (contextWindow === undefined || !Number.isFinite(contextWindow) || contextWindow <= 0) {\n return undefined\n }\n if (contextWindow >= 1_000_000) {\n const m = contextWindow / 1_000_000\n // Round to one decimal only when it adds information: 1_048_576 -> \"1M\",\n // 1_050_000 -> \"1.1M\".\n const rounded = Math.round(m * 10) / 10\n return `${Number.isInteger(rounded) ? rounded : rounded.toFixed(1)}M`\n }\n return `${Math.floor(contextWindow / 1_000)}K`\n}\n\n/**\n * Compact one-line summary for the model picker: plan tier, then any active\n * deal (discount or FREE), then the current peak/off-peak state (`Peak`/`Half`)\n * for time-of-day-priced models, then `Image` for Vision-capable models, then\n * the context window. Text-only models simply omit the Image marker — \"Text\n * only\" adds nothing the picker needs to show.\n */\nexport function capabilityDescription(\n modelId: string,\n contextWindow?: number,\n now: number = Date.now(),\n): string {\n const parts: string[] = []\n const plan = planLabel(modelId)\n if (plan !== undefined) parts.push(plan)\n const deal = dealLabel(modelId, now)\n if (deal !== undefined) parts.push(deal)\n const peak = peakPricingLabel(modelId, now)\n if (peak !== undefined) parts.push(peak)\n if (KNOWN_IMAGE_MODELS.has(modelId)) parts.push('Image')\n const ctx = formatContext(contextWindow)\n if (ctx !== undefined) parts.push(ctx)\n return parts.join(' · ')\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\nfunction booleanValue(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined\n}\n\n/** Parse a billing-period timestamp (ISO string or millis) into millis; 0 when absent/invalid. */\nfunction periodEndValue(value: unknown): number {\n const asNumber = numberValue(value)\n if (asNumber !== undefined) return asNumber\n const asString = stringValue(value)\n if (asString === undefined) return 0\n const parsed = Date.parse(asString)\n return Number.isNaN(parsed) ? 0 : parsed\n}\n\n/**\n * Terminal stream-error markers from the official CLI (`Xw` in command-code's\n * cli.mjs): these always mean \"retrying cannot succeed\", so the adapter must\n * not classify them as transient server errors.\n */\nconst TERMINAL_STREAM_ERROR_MARKERS = [\n 'premium_credits_exhausted',\n 'model_not_in_plan',\n 'insufficient credits',\n]\n\nfunction hasTerminalStreamMarker(message: string): boolean {\n const lower = message.toLowerCase()\n return TERMINAL_STREAM_ERROR_MARKERS.some((marker) => lower.includes(marker))\n}\n\nfunction recordOrEmpty(value: unknown): Record<string, unknown> {\n if (isRecord(value)) return value\n if (typeof value === 'string') {\n try {\n const parsed: unknown = JSON.parse(value)\n if (isRecord(parsed)) return parsed\n } catch {\n // Some providers stream incomplete JSON argument fragments.\n }\n }\n return {}\n}\n\nexport function projectSlugFromPath(pathName: string): string {\n const slug = pathName\n .toLowerCase()\n .replace(/^[a-z]:/i, '')\n .replace(/[^a-z0-9]+/g, '-')\n // Trim leading/trailing separators. This must stay linear: the classic\n // `/^-+|-+$/` form is ambiguous — on `a<200k dashes>b` the unanchored\n // `-+$` retries every start position, giving O(n^2) matching (CodeQL\n // js/polynomial-redos). The negative lookbehind `(?<!-)` restricts `-+$`\n // to the first dash of the trailing run, so only one start position is\n // tried. Verified empirically: ~14.5s -> ~0ms on a 200k-dash input.\n .replace(/^-+|(?<!-)-+$/g, '')\n return slug || 'project'\n}\n\nfunction parseStreamEventLine(line: string): unknown | undefined {\n let trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(':') || trimmed.startsWith('event:')) return undefined\n if (trimmed.startsWith('data:')) trimmed = trimmed.slice(5).trim()\n if (!trimmed || trimmed === '[DONE]') return undefined\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return undefined\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential fallback from the official Command Code CLI auth file. Used as\n// the last fallback by the plugin entry, so a user who already logged in with\n// `command-code login` can reuse that credential. Only the official CLI's own\n// file is read — pi/OMP auth files are intentionally not scanned, so their\n// credentials and formats cannot surprise this adapter.\n// ---------------------------------------------------------------------------\n\n/** Extract the key from the CLI's nested credential records (`command-code`). */\nfunction apiKeyFromCredentialRecord(value: unknown): string | undefined {\n if (!isRecord(value)) return undefined\n const type = stringValue(value.type)\n if (type === 'api') return stringValue(value.key)\n if (type === 'oauth') return stringValue(value.access)\n return stringValue(value.key) ?? stringValue(value.access)\n}\n\n/** Read a usable Command Code credential from the official CLI auth file. */\nexport function resolveAuthFileApiKey(): string | undefined {\n const authPath = join(homedir(), '.commandcode', 'auth.json')\n try {\n if (!existsSync(authPath)) return undefined\n const parsed: unknown = JSON.parse(readFileSync(authPath, 'utf-8'))\n if (!isRecord(parsed)) return undefined\n const direct = stringValue(parsed.apiKey) ?? stringValue(parsed.commandcode)\n if (direct) return direct\n const nested =\n apiKeyFromCredentialRecord(parsed.commandcode) ??\n apiKeyFromCredentialRecord(parsed['command-code'])\n return nested\n } catch {\n // Ignore malformed or unreadable auth file.\n }\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog discovery with on-disk cache fallback (ported from models.ts)\n// ---------------------------------------------------------------------------\n\ninterface CommandCodeModel {\n id: string\n name: string\n contextWindow: number\n maxTokens: number\n}\n\nfunction parseCatalogResponse(value: unknown): CommandCodeModel[] {\n if (!isRecord(value) || value.object !== 'list' || !Array.isArray(value.data)) {\n throw new LlmError('Unexpected Command Code models response shape', 'PROVIDER_PROTOCOL_ERROR')\n }\n const models: CommandCodeModel[] = []\n for (const entry of value.data) {\n if (!isRecord(entry)) continue\n const id = stringValue(entry.id)\n const name = stringValue(entry.name)\n const contextLength = numberValue(entry.context_length)\n if (!id || !name || !contextLength || contextLength <= 0) continue\n models.push({\n id,\n name,\n contextWindow: contextLength,\n maxTokens: Math.min(contextLength, DEFAULT_MAX_OUTPUT_TOKENS),\n })\n }\n if (models.length === 0) {\n throw new LlmError('Command Code returned an empty model catalog', 'PROVIDER_PROTOCOL_ERROR')\n }\n return models\n}\n\nasync function readModelsCache(cachePath: string): Promise<CommandCodeModel[]> {\n const parsed: unknown = JSON.parse(await readFile(cachePath, 'utf-8'))\n if (!isRecord(parsed) || parsed.version !== MODEL_CACHE_VERSION || !Array.isArray(parsed.models)) {\n throw new Error(`Invalid model cache at ${cachePath}`)\n }\n return parsed.models as CommandCodeModel[]\n}\n\nasync function writeModelsCache(cachePath: string, models: CommandCodeModel[]): Promise<void> {\n await mkdir(dirname(cachePath), { recursive: true })\n const tmp = `${cachePath}.${process.pid}.tmp`\n try {\n await writeFile(tmp, `${JSON.stringify({ version: MODEL_CACHE_VERSION, models }, null, 2)}\\n`, {\n encoding: 'utf-8',\n mode: 0o600,\n })\n await rename(tmp, cachePath)\n } finally {\n await rm(tmp, { force: true }).catch(() => undefined)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message conversion: harness Message[] -> Command Code wire messages.\n// Reasoning blocks are intentionally NOT replayed (matches the pi plugin and\n// the official CLI: prior private reasoning must not leak into later turns).\n// Only tool calls with a paired tool result are replayed.\n// ---------------------------------------------------------------------------\n\n/**\n * Collect the tool calls that have a paired tool result, plus each call's\n * name. The name map feeds the `toolName` of replayed tool results: some\n * backends (e.g. Google Gemini `functionResponse`) reject a result whose\n * function name is empty, so the real name must round-trip (the official\n * CLI does the same via its `tool_use_id -> toolName` map).\n */\nfunction pairedToolCalls(messages: readonly Message[]): {\n ids: Set<string>\n names: Map<string, string>\n} {\n const callIds = new Set<string>()\n const names = new Map<string, string>()\n const resultIds = new Set<string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (message.role === 'assistant' && block.type === 'tool-call') {\n callIds.add(block.id)\n names.set(block.id, block.name)\n }\n if (block.type === 'tool-result') resultIds.add(block.toolCallId)\n }\n }\n return { ids: new Set([...callIds].filter((id) => resultIds.has(id))), names }\n}\n\nfunction blockText(block: ContentBlock): string {\n return block.type === 'text' || block.type === 'reasoning' ? block.text : ''\n}\n\nfunction toolResultText(block: Extract<ContentBlock, { type: 'tool-result' }>): string {\n return block.content.map(blockText).filter(Boolean).join('\\n')\n}\n\nfunction hasImageContent(message: Message): boolean {\n const check = (blocks: readonly ContentBlock[]): boolean =>\n blocks.some(\n (b) => b.type === 'image' || (b.type === 'tool-result' && check(b.content)),\n )\n return check(message.content)\n}\n\n/**\n * Convert one image reference to the Command Code wire format, as the official\n * CLI does: `{ type: 'image', source: { type: 'base64', media_type, data } }`.\n * Bytes come from the durable attachment service; the media type is the one\n * verified at save time.\n */\nasync function imageToCommandCode(\n ref: ImageAttachmentRef,\n readImage: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<{ type: 'image'; source: { type: 'base64'; media_type: string; data: string } }> {\n const data = await readImage(ref)\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: ref.mediaType,\n data: Buffer.from(data).toString('base64'),\n },\n }\n}\n\nasync function messagesToCC(\n messages: readonly Message[],\n readImage?: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<unknown[]> {\n const out: unknown[] = []\n const { ids: paired, names: toolNames } = pairedToolCalls(messages)\n\n for (const message of messages) {\n if (message.role === 'system') continue // folded into params.system by the caller\n\n if (message.role === 'user' && message.source.kind !== 'tool') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') parts.push({ type: 'text', text: block.text })\n if (block.type === 'image') {\n // The caller (stream) has already gated image input on model\n // capability and attachment-service availability, so reaching this\n // branch with no resolver is an internal contract violation.\n if (!readImage) {\n throw new LlmError(\n 'Image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n parts.push(await imageToCommandCode(block.attachment, readImage))\n }\n }\n out.push({ role: 'user', content: parts })\n continue\n }\n\n if (message.role === 'assistant') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') {\n parts.push({ type: 'text', text: block.text })\n } else if (block.type === 'tool-call' && paired.has(block.id)) {\n parts.push({\n type: 'tool-call',\n toolCallId: block.id,\n toolName: block.name,\n input: recordOrEmpty(block.arguments),\n })\n }\n // reasoning blocks: skipped by design (see header comment)\n }\n if (parts.length > 0) out.push({ role: 'assistant', content: parts })\n continue\n }\n\n // tool-result message (user role, single tool-result block)\n if (message.role === 'user' && message.source.kind === 'tool') {\n const block = message.content[0]\n if (!block || block.type !== 'tool-result' || !paired.has(block.toolCallId)) continue\n out.push({\n role: 'tool',\n content: [\n {\n type: 'tool-result',\n toolCallId: block.toolCallId,\n // `paired` guarantees a call with this id exists, so the map\n // always hits; `|| 'unknown'` also guards an empty call name\n // (matches the official CLI's `?? \"unknown\"` fallback).\n toolName: toolNames.get(block.toolCallId) || 'unknown',\n output: block.isError\n ? { type: 'error-text', value: toolResultText(block) }\n : { type: 'text', value: toolResultText(block) },\n },\n ],\n })\n }\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Adapter\n// ---------------------------------------------------------------------------\n/** Connection facts resolved fresh per request by the plugin entry. */\nexport interface CommandCodeConnectionOptions {\n /** API base; the Provider API lives under it (`/alpha/generate`, `/provider/v1/models`). */\n apiBase: string\n /** Working directory reported to the API (project slug, config block). */\n workingDir: string\n /** Model catalog cache path. */\n modelsCachePath: string\n /**\n * Milliseconds to wait for generate response headers / first byte (default 60s).\n * Must not bound the subsequent body stream — long generations are gated by\n * {@link streamIdleTimeoutMs} and the caller AbortSignal instead.\n */\n requestTimeoutMs: number\n /** Milliseconds a stream may stall before it is treated as a dead connection (default 300s). */\n streamIdleTimeoutMs: number\n /**\n * Whether the picker hides models above the account's subscription tier\n * (default true). The filter fails open: unknown plan, billing-endpoint\n * failure, a positive on-demand credit balance, or an unmapped model all\n * keep the full catalog visible. Set false to always list every model.\n */\n filterModelsByPlan?: boolean\n}\n\n/**\n * Resolve the durable attachment service, or undefined when the host does not\n * provide one. Called lazily only when a request actually carries images, so a\n * text-only request never depends on the attachment seam.\n */\nexport type ResolveAttachments = () => AttachmentStore | undefined\n\n/** Everything the adapter needs beyond the request itself. */\nexport interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** Resolve the current connection facts (fresh per request, settings-aware). */\n options: () => C\n /**\n * Resolve a usable API key for the given connection facts and the request's\n * model id, or throw `MISSING_CREDENTIAL`. The model is optional: hosts\n * without model-aware routing ignore it.\n */\n resolveApiKey: (connection: C, model?: string) => Promise<string>\n /**\n * Multi-account rotation hook: the request sent with `rejectedKey` was\n * refused with 429 (`rate-limit`) or 401 (`invalid-credential`) before\n * any response body streamed. The host marks that key and returns the next\n * account's key to retry with, or `undefined` to surface the failure.\n * Only pre-stream rejections rotate — a mid-stream failure never replays a\n * partially consumed generation against another account.\n */\n rotateApiKey?: (rejectedKey: string, rejection: 'rate-limit' | 'invalid-credential', connection: C, model?: string) => Promise<string | undefined>\n /** HTTP transport override (tests); defaults to the global `fetch`. */\n fetchImpl?: typeof fetch\n /** Resolve the optional durable attachment service for image input (tests); defaults to none. */\n resolveAttachments?: ResolveAttachments\n}\n\n/** Account identity from `/alpha/whoami`. */\nexport interface CommandCodeAccount {\n id: string\n name: string\n userName: string\n}\n\n/** Usage summary from `/alpha/usage/summary`. */\nexport interface CommandCodeUsage {\n totalCount: number\n totalCost: number\n successRate: number\n completedCount: number\n failedCount: number\n totalTokensIn: number\n totalTokensOut: number\n totalCredits: number\n periodBasis: string\n}\n\n/** Credit/limit state from `/alpha/billing/credits`. */\nexport interface CommandCodeCredits {\n monthlyCredits: number\n purchasedCredits: number\n freeCredits: number\n /** Five-hour rolling window limits. */\n fiveHour: { used: number; cap: number; exceeded: boolean; resetAt: number }\n /** Weekly window limits. */\n weekly: { used: number; cap: number; exceeded: boolean; resetAt: number }\n}\n\n/** Subscription plan state from `/alpha/billing/subscriptions`. */\nexport interface CommandCodePlan {\n /** Raw subscription plan id (e.g. `individual-pro`); empty when unreported. */\n planId: string\n /** Display name (e.g. `Pro`); falls back to the raw id for unknown plans. */\n name: string\n /** Raw subscription status (`active`, `trialing`, `past_due`, …); empty when unreported. */\n status: string\n /** The plan's monthly credit total per {@link KNOWN_SUBSCRIPTION_PLANS}; null for unknown plans. */\n monthlyCredits: number | null\n /** Billing period end in millis; 0 when the endpoint did not report one. */\n currentPeriodEnd: number\n}\n\n/**\n * Why every account endpoint failed at once (the report then carries no data\n * at all, so the degraded per-endpoint view would hide the root cause behind\n * a generic \"partial data\" note). Undefined for partial failures.\n */\nexport type UsageBlockReason = 'invalid-key' | 'service-unavailable' | 'network'\n\n/** Account endpoints fetched by one `getUsage()` run (see the classification there). */\nconst USAGE_ENDPOINT_COUNT = 4\n\n/** Everything the usage endpoints report, fetched together. */\nexport interface CommandCodeUsageReport {\n account?: CommandCodeAccount\n usage?: CommandCodeUsage\n credits?: CommandCodeCredits\n plan?: CommandCodePlan\n /** Endpoint failures degrade the report instead of failing it. */\n failures: string[]\n /**\n * The single reason every endpoint failed, when they all did: `invalid-key`\n * (every call rejected with 401 — the stored key is wrong or expired),\n * `service-unavailable` (every call answered 5xx), or `network` (no HTTP\n * response at all). Undefined when any endpoint succeeded.\n */\n blocked?: UsageBlockReason\n}\n\nexport class CommandCodeAdapter<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> extends LlmAdapter {\n private catalog: CommandCodeModel[] = []\n private readonly fetchImpl: typeof fetch\n private readonly resolveAttachments: ResolveAttachments | undefined\n // Billing facts are per account: with a multi-account pool each key has its\n // own subscription tier, so the cache and the in-flight dedupe are keyed by\n // the resolved API key (process-local only, never logged).\n private readonly billingAccess = new Map<string, { value: CommandCodeBillingAccess | undefined; at: number }>()\n private readonly billingAccessInflight = new Map<string, Promise<CommandCodeBillingAccess | undefined>>()\n\n constructor(private readonly deps: CommandCodeAdapterDeps<C>) {\n super()\n this.fetchImpl = deps.fetchImpl ?? fetch\n this.resolveAttachments = deps.resolveAttachments\n }\n\n /**\n * Display metadata for the picker's provider group header. The base class\n * returns the raw route id (`commandcode`, all lowercase) as the name, which\n * is what the model selector shows as this group's sticky title; return the\n * proper display name instead, matching the Models settings page card (the\n * configurable-provider `displayName`). The id must stay equal to the route.\n */\n override providerInfo(provider: string): LlmProviderInfo {\n return { id: provider, name: 'Command Code' }\n }\n\n /**\n * Near-unbounded retry for transient failures only (`mode: 'normal'` with\n * an explicit 1000-attempt cap — opencode-style persistence without the\n * unbounded loop): `RATE_LIMIT`/`SERVER`/`TIMEOUT`/`TRANSPORT`/\n * `EMPTY_RESPONSE` retry up to 1000 times with waits doubling from 500 ms\n * and capping at 15 minutes (±10% jitter), so an exhausted 5-hour window\n * recovers in-session instead of failing after two tries. Permanent\n * failures (an invalid key's `INVALID_CREDENTIAL`, `UNSUPPORTED_CONTENT`,\n * plan rejections) are absent from the whitelist and surface immediately\n * instead of looping. Waits the pool/adapter attach as\n * `providerRetryAfterMs` are honored verbatim at or below the 15-minute\n * cap and never attached above it (in normal mode a longer attached wait\n * makes the executor abandon the retry outright — see RETRY_MAX_DELAY_MS).\n *\n * Captured once at route registration (dsh-llm snapshots this value), so a\n * future config knob for it would apply on profile restart, not per request.\n */\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return resolveRetryPolicy(\n {\n mode: 'normal',\n maxRetries: 1000,\n retryableCodes: ['EMPTY_RESPONSE', 'RATE_LIMIT', 'SERVER', 'TIMEOUT', 'TRANSPORT'],\n backoff: { initialDelayMs: 500, maxDelayMs: RETRY_MAX_DELAY_MS, jitterRatio: 0.1 },\n },\n 'llm-commandcode: retryPolicy',\n )\n }\n\n /** Refresh the catalog (live fetch, cache fallback) and return it. */\n private async loadCatalog(signal?: AbortSignal): Promise<CommandCodeModel[]> {\n const { apiBase, modelsCachePath } = this.deps.options()\n try {\n const response = await this.fetchImpl(`${apiBase}/provider/v1/models`, {\n headers: { accept: 'application/json', ...attributionHeaders() },\n signal: signal ?? AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n throw new Error(`models endpoint returned ${response.status}`)\n }\n this.catalog = parseCatalogResponse(await response.json())\n await writeModelsCache(modelsCachePath, this.catalog).catch(() => undefined)\n } catch (error) {\n if (signal?.aborted) throw error\n // A catalog refresh failure is a degradation, not a request failure:\n // fall back to the last successful catalog on disk (or the in-memory\n // one from an earlier successful load). The adapter still serves any\n // model the user names; only the advisory selector loses entries.\n this.catalog = await readModelsCache(modelsCachePath).catch(() => this.catalog)\n }\n return this.catalog\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n const catalog = await this.loadCatalog()\n // Plan filter: hide models above the account's subscription tier. Fails\n // open — a billing-fetch problem, an unknown plan, or a positive\n // on-demand balance all keep the full catalog visible, and the server\n // remains the final gate (403 MODEL_NOT_IN_PLAN). The catalog itself is\n // never filtered: resolveModel still serves every model.\n const access = this.deps.options().filterModelsByPlan === false\n ? undefined\n : await this.loadBillingAccess()\n return catalog\n .filter((model) => modelVisibleInPlan(model.id, access))\n .map((model) => {\n const vision = KNOWN_IMAGE_MODELS.has(model.id)\n return {\n provider,\n id: model.id,\n name: `${model.name} (CC)`,\n // The picker renders `description` under the model name: plan tier,\n // active deal, Image marker for Vision models, and context window.\n description: capabilityDescription(model.id, model.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n }\n })\n // The picker renders rows in the order returned: sort by plan tier\n // (Go first, … Provider last) so the models a Go-plan user can actually\n // use lead the list, then alphabetically within each tier.\n .sort(compareByPlan)\n }\n\n override async resolveModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<LlmResolvedModelInfo> {\n const entry =\n this.catalog.find((m) => m.id === model) ??\n (await this.loadCatalog(signal)).find((m) => m.id === model)\n\n const efforts = KNOWN_EFFORTS[model]\n const vision = KNOWN_IMAGE_MODELS.has(model)\n return {\n provider,\n id: model,\n name: entry ? `${entry.name} (CC)` : model,\n description: capabilityDescription(model, entry?.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n ...(entry\n ? {\n context: { contextWindow: entry.contextWindow },\n defaultMaxTokens: Math.min(entry.maxTokens, DEFAULT_GENERATE_MAX_TOKENS),\n }\n : {}),\n // Omit `reasoning` entirely for models without known effort support:\n // the harness then treats the model as having no selectable efforts.\n ...(efforts\n ? {\n reasoning: {\n efforts: efforts.map((effort) => ({\n id: ReasoningEffortId(effort),\n name: effort,\n })),\n },\n }\n : {}),\n }\n }\n\n /** The headers every authenticated account endpoint shares. */\n private async accountHeaders(apiKey?: string): Promise<Record<string, string>> {\n const connection = this.deps.options()\n const key = apiKey ?? (await this.deps.resolveApiKey(connection))\n return {\n Authorization: `Bearer ${key}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n }\n }\n\n /**\n * The billing facts behind the picker's plan filter, cached for\n * {@link BILLING_ACCESS_TTL_MS} and shared across concurrent callers.\n * `undefined` means \"unknown — show everything\" (fail-open).\n */\n private async loadBillingAccess(): Promise<CommandCodeBillingAccess | undefined> {\n let apiKey: string\n try {\n apiKey = await this.deps.resolveApiKey(this.deps.options())\n } catch {\n return undefined\n }\n const cached = this.billingAccess.get(apiKey)\n if (cached !== undefined && Date.now() - cached.at < BILLING_ACCESS_TTL_MS) return cached.value\n const existing = this.billingAccessInflight.get(apiKey)\n if (existing !== undefined) return existing\n const inflight = this.fetchBillingAccess(apiKey)\n .then((value) => {\n this.billingAccess.set(apiKey, { value, at: Date.now() })\n return value\n })\n .finally(() => {\n this.billingAccessInflight.delete(apiKey)\n })\n this.billingAccessInflight.set(apiKey, inflight)\n return inflight\n }\n\n /**\n * The billing facts behind the picker's plan filter, mirroring the CLI's\n * `createBilling` flow: whoami yields the org id, then the subscriptions\n * and credits endpoints answer in parallel. The plan id is honored only\n * when the subscription reports an active-ish status (the CLI's rule); when\n * the subscriptions endpoint fails entirely, `credits.planId` is the\n * fallback (the CLI stamps plan identity from it too). Any failure resolves\n * to `undefined` (fail-open) rather than breaking the picker.\n */\n private async fetchBillingAccess(apiKey: string): Promise<CommandCodeBillingAccess | undefined> {\n try {\n const connection = this.deps.options()\n const headers = await this.accountHeaders(apiKey)\n const base = connection.apiBase\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n const response = await this.fetchImpl(`${base}${path}`, {\n headers,\n // A hung billing connection must not stall the picker forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) return undefined\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n }\n const whoami = await getJson('/alpha/whoami')\n const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\n const [subscription, credits] = await Promise.all([\n getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`),\n getJson('/alpha/billing/credits'),\n ])\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n if (subData === undefined && creditsData === undefined) return undefined\n let planId: string | undefined\n if (subData !== undefined) {\n const status = stringValue(subData.status)\n if (status !== undefined && ACTIVE_SUBSCRIPTION_STATUSES.has(status)) planId = stringValue(subData.planId)\n } else {\n planId = stringValue(creditsData?.planId)\n }\n return {\n tierWeight: planId === undefined ? undefined : subscriptionPlanInfo(planId)?.tierWeight,\n onDemandCredits: (numberValue(creditsData?.purchasedCredits) ?? 0) + (numberValue(creditsData?.freeCredits) ?? 0),\n }\n } catch {\n return undefined\n }\n }\n\n /**\n * Fetch account, usage, credit, and subscription state from the Command\n * Code account endpoints (`/alpha/whoami`, `/alpha/usage/summary`,\n * `/alpha/billing/credits`, `/alpha/billing/subscriptions`).\n * Each endpoint degrades independently: a failed one lands in `failures`\n * while the rest still report, so a transient outage never blanks the whole\n * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).\n * Pass `apiKey` to report on a specific account of a multi-account pool;\n * the default resolves the currently active account.\n */\n async getUsage(apiKey?: string): Promise<CommandCodeUsageReport> {\n const connection = this.deps.options()\n const base = connection.apiBase\n const headers = await this.accountHeaders(apiKey)\n const failures: string[] = []\n // HTTP status per failed endpoint (undefined for transport failures), in\n // failure order — the all-failed classification below reads it.\n const failedStatuses: Array<number | undefined> = []\n\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n try {\n const response = await this.fetchImpl(`${base}${path}`, {\n headers,\n // A hung account endpoint degrades into `failures` instead of\n // stalling the usage card / command forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n failures.push(`${path}: HTTP ${response.status}`)\n failedStatuses.push(response.status)\n return undefined\n }\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n } catch (error: unknown) {\n failures.push(`${path}: ${error instanceof Error ? error.message : String(error)}`)\n failedStatuses.push(undefined)\n return undefined\n }\n }\n\n const report: CommandCodeUsageReport = { failures }\n\n // whoami -> account identity (+ org id for the billing endpoints).\n const whoami = await getJson('/alpha/whoami')\n const whoamiData = whoami && isRecord(whoami.user) ? whoami.user : undefined\n if (whoamiData) {\n report.account = {\n id: stringValue(whoamiData.id) ?? '',\n name: stringValue(whoamiData.name) ?? '',\n userName: stringValue(whoamiData.userName) ?? '',\n }\n }\n const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\n\n // usage/summary -> totals.\n const usage = await getJson('/alpha/usage/summary')\n if (usage) {\n report.usage = {\n totalCount: numberValue(usage.totalCount) ?? 0,\n totalCost: numberValue(usage.totalCost) ?? 0,\n successRate: numberValue(usage.successRate) ?? 0,\n completedCount: numberValue(usage.completedCount) ?? 0,\n failedCount: numberValue(usage.failedCount) ?? 0,\n totalTokensIn: numberValue(usage.totalTokensIn) ?? 0,\n totalTokensOut: numberValue(usage.totalTokensOut) ?? 0,\n totalCredits: numberValue(usage.totalCredits) ?? 0,\n periodBasis: stringValue(usage.periodBasis) ?? 'billing-period',\n }\n }\n\n // billing/credits -> credit + window limits.\n const credits = await getJson('/alpha/billing/credits')\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n const windowLimits = credits && isRecord(credits.windowLimits) ? credits.windowLimits : undefined\n const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : undefined\n const weekly = windowLimits && isRecord(windowLimits.weekly) ? windowLimits.weekly : undefined\n if (creditsData || fiveHour || weekly) {\n report.credits = {\n monthlyCredits: numberValue(creditsData?.monthlyCredits) ?? 0,\n purchasedCredits: numberValue(creditsData?.purchasedCredits) ?? 0,\n freeCredits: numberValue(creditsData?.freeCredits) ?? 0,\n fiveHour: {\n used: numberValue(fiveHour?.used) ?? 0,\n cap: numberValue(fiveHour?.cap) ?? 0,\n exceeded: fiveHour?.exceeded === true,\n resetAt: numberValue(fiveHour?.resetAt) ?? 0,\n },\n weekly: {\n used: numberValue(weekly?.used) ?? 0,\n cap: numberValue(weekly?.cap) ?? 0,\n exceeded: weekly?.exceeded === true,\n resetAt: numberValue(weekly?.resetAt) ?? 0,\n },\n }\n }\n\n // billing/subscriptions -> plan identity + billing period. The credits\n // response may also carry a planId; it is the fallback when the\n // subscriptions endpoint fails. Mirrors the CLI: orgId rides as a query\n // param when whoami reported one.\n const subscription = await getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`)\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const planId = stringValue(subData?.planId) ?? stringValue(creditsData?.planId)\n if (subData !== undefined || planId !== undefined) {\n const info = planId === undefined ? undefined : subscriptionPlanInfo(planId)\n report.plan = {\n planId: planId ?? '',\n name: info?.name ?? planId ?? '',\n status: stringValue(subData?.status) ?? '',\n monthlyCredits: info?.monthlyCredits ?? null,\n currentPeriodEnd: periodEndValue(subData?.currentPeriodEnd),\n }\n }\n\n // Classify a TOTAL failure: when every endpoint failed with one class of\n // error, the degraded per-endpoint view would hide the root cause behind\n // a generic \"partial data\" note — name it instead. Four endpoints are\n // fetched (whoami, usage/summary, billing/credits, billing/subscriptions;\n // the last may carry an orgId query, so classification counts, not paths).\n if (failures.length === USAGE_ENDPOINT_COUNT) {\n const codes = failedStatuses.filter((status): status is number => status !== undefined)\n if (codes.length === USAGE_ENDPOINT_COUNT && codes.every((code) => code === 401)) {\n report.blocked = 'invalid-key'\n } else if (codes.length === USAGE_ENDPOINT_COUNT && codes.every((code) => code >= 500)) {\n report.blocked = 'service-unavailable'\n } else if (codes.length === 0) {\n report.blocked = 'network'\n }\n }\n\n return report\n }\n\n /**\n * Probe one account's five-hour window from `/alpha/billing/credits`. The\n * multi-account pool calls this when every account is marked exhausted: an\n * account whose window no longer reports `exceeded` is revived, and the\n * `resetAt` values feed the \"earliest reset\" error message. Returns\n * `undefined` when the probe itself failed (transport, non-200, or a\n * payload without window limits) — a failed probe never changes pool state.\n */\n async probeFiveHourWindow(apiKey: string): Promise<{ exceeded: boolean; resetAt: number } | undefined> {\n try {\n const connection = this.deps.options()\n const response = await this.fetchImpl(`${connection.apiBase}/alpha/billing/credits`, {\n headers: await this.accountHeaders(apiKey),\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) return undefined\n const parsed: unknown = await response.json()\n if (!isRecord(parsed)) return undefined\n const windowLimits = isRecord(parsed.windowLimits) ? parsed.windowLimits : undefined\n const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : undefined\n if (fiveHour === undefined) return undefined\n return { exceeded: fiveHour.exceeded === true, resetAt: numberValue(fiveHour.resetAt) ?? 0 }\n } catch {\n return undefined\n }\n }\n\n async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n if (options.stop?.length) {\n // The Command Code wire format has no documented stop field; refuse\n // loudly instead of silently dropping a request field.\n throw new LlmError('Command Code adapter does not support stop sequences', 'UNSUPPORTED_OPTION')\n }\n const hasImages = options.messages.some(hasImageContent)\n // Per-call image byte resolver, set only when this request carries images.\n // Local, not an instance field: concurrent streams must never read each\n // other's resolver.\n let readImage: ((ref: ImageAttachmentRef) => Promise<Uint8Array>) | undefined\n if (hasImages) {\n // Model-capability gate: only models the official registry lists with\n // Vision accept images natively. Command Code's own CLI falls back to a\n // client-side VISION side-call for text-only models; this adapter does\n // not reproduce that interactive feature, so it refuses loudly instead\n // of sending bytes to a model that cannot read them.\n if (!KNOWN_IMAGE_MODELS.has(options.model)) {\n throw new LlmError(\n `Command Code model \"${options.model}\" does not support image input;`\n + ' switch to a Vision-capable model (see the model registry)',\n 'UNSUPPORTED_CONTENT',\n )\n }\n // Attachment seam: images arrive as durable references; resolving them\n // requires the host's attachment service.\n const attachments = this.resolveAttachments?.()\n if (attachments === undefined) {\n throw new LlmError(\n 'Command Code image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n readImage = (ref) => attachments.readImage(ref).then((stored) => stored.data)\n }\n\n const connection = this.deps.options()\n // The model id reaches key resolution so hosts with model→account routing\n // rules can pick the account that covers this model.\n let apiKey = await this.deps.resolveApiKey(connection, options.model)\n const entry = this.catalog.find((m) => m.id === options.model)\n const modelMax = entry?.maxTokens ?? DEFAULT_MAX_OUTPUT_TOKENS\n const maxTokens = Math.min(\n options.maxTokens ?? modelMax,\n modelMax,\n DEFAULT_GENERATE_MAX_TOKENS,\n )\n\n const effort = options.reasoningEffort as string | undefined\n const supported = KNOWN_EFFORTS[options.model]\n const reasoningEffort =\n effort && effort !== 'off' && supported?.includes(effort) ? effort : undefined\n\n const systemText = [\n options.system ?? '',\n ...options.messages\n .filter((m) => m.role === 'system')\n .map((m) => m.content.map(blockText).filter(Boolean).join('\\n')),\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const body = {\n config: {\n workingDir: connection.workingDir,\n date: new Date().toISOString().split('T')[0],\n environment: `${process.platform}-${process.arch}, Node.js ${process.version}`,\n structure: [],\n isGitRepo: false,\n currentBranch: '',\n mainBranch: '',\n gitStatus: '',\n recentCommits: [],\n },\n memory: null,\n taste: null,\n skills: null,\n params: {\n model: options.model,\n messages: await messagesToCC(options.messages, readImage),\n tools: (options.tools ?? []).map((tool) => ({\n type: 'function',\n name: tool.name,\n description: tool.description,\n input_schema: tool.parameters,\n })),\n system: systemText,\n max_tokens: maxTokens,\n temperature: options.temperature ?? 0.3,\n stream: true,\n ...(reasoningEffort ? { reasoning_effort: reasoningEffort } : {}),\n },\n threadId: randomUUID(),\n }\n\n // requestTimeoutMs must only bound the wait for response headers.\n // Passing AbortSignal.timeout() straight into fetch() also aborts a healthy\n // body after that duration, which cuts long reasoning/generation mid-stream\n // and surfaces as \"failed while reading: aborted due to timeout\". After\n // headers arrive, only the caller signal and streamIdleTimeoutMs may abort.\n //\n // One connect attempt per account key: a pre-stream 429/401 hands the key\n // to the multi-account rotation hook (when the host wired one) and retries\n // with the next account — the request body is account-independent and\n // nothing has streamed yet, so the switch is invisible to the caller.\n const connect = async (\n key: string,\n ): Promise<{ response: Response; cleanup: () => void } | { status: number; errText: string; retryAfterMs?: number }> => {\n const connectAbort = new AbortController()\n let connectTimedOut = false\n const connectTimer = setTimeout(() => {\n connectTimedOut = true\n connectAbort.abort(\n new DOMException(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`,\n 'TimeoutError',\n ),\n )\n }, connection.requestTimeoutMs)\n const onCallerAbort = () => {\n connectAbort.abort(options.signal?.reason)\n }\n if (options.signal) {\n if (options.signal.aborted) {\n onCallerAbort()\n } else {\n options.signal.addEventListener('abort', onCallerAbort, { once: true })\n }\n }\n // On success the caller-abort listener must outlive the connect phase\n // (it aborts a stalled body read), so the streaming tail calls cleanup;\n // every failure path cleans up before returning or throwing.\n const cleanup = () => {\n clearTimeout(connectTimer)\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n }\n\n let response: Response\n try {\n response = await this.fetchImpl(`${connection.apiBase}/alpha/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${key}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n 'x-project-slug': projectSlugFromPath(connection.workingDir),\n 'x-taste-learning': 'true',\n 'x-co-flag': 'false',\n ...attributionHeaders(),\n },\n body: JSON.stringify(body),\n signal: connectAbort.signal,\n })\n clearTimeout(connectTimer)\n } catch (error: unknown) {\n cleanup()\n if (options.signal?.aborted) {\n throw error\n }\n if (connectTimedOut || (error instanceof DOMException && error.name === 'TimeoutError')) {\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`\n + `: ${errorChain(error)}`\n + `;Command Code API 请求在 ${connection.requestTimeoutMs} 毫秒内未收到响应——通常是网络或代理问题,请检查后重试`,\n 'TIMEOUT',\n { cause: error },\n )\n }\n // fetch wraps every transport failure (DNS, refused connection, TLS,\n // proxy, reset) in a bare `TypeError: fetch failed` whose actionable\n // detail lives on `cause`. Include the full chain so the failure reason\n // shown in the web UI (which renders only the message, not `cause`)\n // names the real root cause instead of a generic wrapper.\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate failed: ${errorChain(error)}`\n + ';Command Code API 请求连接失败——通常是网络或代理问题,请检查网络或代理设置后重试',\n 'TRANSPORT',\n { cause: error },\n )\n }\n\n if (!response.ok) {\n const errText = await response.text().catch(() => '')\n cleanup()\n const retryAfterMs = parseRetryAfterMs(response.headers.get('retry-after'))\n // exactOptionalPropertyTypes: the key must be absent, not undefined.\n return retryAfterMs === undefined\n ? { status: response.status, errText }\n : { status: response.status, errText, retryAfterMs }\n }\n return { response, cleanup }\n }\n\n // Account rotation loop: the first attempt uses the pool's active key; a\n // pre-stream 429/401 rotates to the next account (at most one attempt per\n // distinct key, hard-capped so a misbehaving hook cannot loop forever).\n const tried = new Set<string>()\n let connected: { response: Response; cleanup: () => void } | undefined\n for (;;) {\n tried.add(apiKey)\n const attempt = await connect(apiKey)\n if ('response' in attempt) {\n connected = attempt\n break\n }\n const rotate = this.deps.rotateApiKey\n if (\n (attempt.status === 429 || attempt.status === 401)\n && rotate !== undefined\n && options.signal?.aborted !== true\n && tried.size < MAX_ACCOUNT_ROTATIONS\n ) {\n const next = await rotate(apiKey, attempt.status === 429 ? 'rate-limit' : 'invalid-credential', connection, options.model)\n if (next !== undefined && !tried.has(next)) {\n apiKey = next\n continue\n }\n }\n throw generateHttpError(attempt.status, attempt.errText, attempt.retryAfterMs)\n }\n const { response, cleanup } = connected\n if (!response.body) {\n cleanup()\n throw new LlmError('Command Code API returned no response body', 'PROVIDER_PROTOCOL_ERROR')\n }\n\n // --- SSE/JSONL event stream -> harness StreamChunk protocol ---\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n // Stream idle watchdog: a generation that stalls this long has a dead\n // connection (the API keeps the socket open between reasoning/text\n // bursts). The default (300s) is deliberately generous: frontier\n // reasoning models (xhigh/max effort) can legitimately stay silent for\n // minutes while thinking, and the official CLI sets no idle cap at all —\n // an aggressive cap turns long thinking into spurious TIMEOUTs and\n // retries. reader.cancel() unblocks a pending read(), which the loop then\n // turns into a TIMEOUT failure instead of hanging forever.\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n let idleFired = false\n const armIdle = () => {\n if (idleTimer !== undefined) clearTimeout(idleTimer)\n idleTimer = setTimeout(() => {\n idleFired = true\n void reader.cancel().catch(() => undefined)\n }, connection.streamIdleTimeoutMs)\n }\n const clearIdle = () => {\n if (idleTimer !== undefined) {\n clearTimeout(idleTimer)\n idleTimer = undefined\n }\n }\n\n // Block assembly state: at most one text block and one reasoning block\n // are open at a time (same assumption as the pi plugin).\n let nextIndex = 0\n let textIndex = -1\n let textContent = ''\n let reasoningIndex = -1\n let reasoningContent = ''\n let sawContent = false\n\n const closeText = function* (): Generator<StreamChunk> {\n if (textIndex < 0) return\n yield {\n type: 'block-end',\n index: textIndex,\n block: { type: 'text', text: textContent },\n }\n textIndex = -1\n textContent = ''\n }\n const closeReasoning = function* (): Generator<StreamChunk> {\n if (reasoningIndex < 0) return\n yield {\n type: 'block-end',\n index: reasoningIndex,\n block: { type: 'reasoning', text: reasoningContent },\n }\n reasoningIndex = -1\n reasoningContent = ''\n }\n\n const handleEvent = (event: unknown): StreamChunk[] => {\n const chunks: StreamChunk[] = []\n if (!isRecord(event)) return chunks\n\n switch (event.type) {\n case 'text-delta': {\n chunks.push(...closeReasoning())\n if (textIndex < 0) {\n textIndex = nextIndex++\n chunks.push({ type: 'block-start', index: textIndex, blockType: 'text' })\n }\n const delta = stringValue(event.text) ?? ''\n textContent += delta\n sawContent = true\n chunks.push({ type: 'text-delta', index: textIndex, text: delta })\n break\n }\n case 'reasoning-delta': {\n chunks.push(...closeText())\n if (reasoningIndex < 0) {\n reasoningIndex = nextIndex++\n chunks.push({ type: 'block-start', index: reasoningIndex, blockType: 'reasoning' })\n }\n const delta = stringValue(event.text) ?? ''\n reasoningContent += delta\n chunks.push({ type: 'reasoning-delta', index: reasoningIndex, text: delta })\n break\n }\n case 'reasoning-start':\n chunks.push(...closeText())\n break\n case 'reasoning-end':\n chunks.push(...closeReasoning())\n break\n case 'tool-call': {\n chunks.push(...closeText(), ...closeReasoning())\n const id = stringValue(event.toolCallId) ?? randomUUID()\n const name = stringValue(event.toolName) ?? ''\n const args = JSON.stringify(recordOrEmpty(event.input ?? event.args ?? event.arguments))\n const index = nextIndex++\n sawContent = true\n chunks.push(\n { type: 'block-start', index, blockType: 'tool-call' },\n { type: 'tool-call-delta', index, id: ToolCallId(id), name, argumentsDelta: args },\n {\n type: 'block-end',\n index,\n block: { type: 'tool-call', id: ToolCallId(id), name, arguments: args },\n },\n )\n break\n }\n case 'finish': {\n chunks.push(...closeText(), ...closeReasoning())\n const usage = isRecord(event.totalUsage) ? event.totalUsage : undefined\n if (usage) {\n const details = isRecord(usage.inputTokenDetails) ? usage.inputTokenDetails : undefined\n const totalInput = numberValue(usage.inputTokens) ?? 0\n const cacheRead = numberValue(details?.cacheReadTokens) ?? 0\n const cacheWrite = numberValue(details?.cacheWriteTokens) ?? 0\n // Harness TokenUsage counts are disjoint: uncached input only.\n const tokenUsage: TokenUsage = {\n inputTokens:\n numberValue(details?.noCacheTokens) ?? Math.max(0, totalInput - cacheRead - cacheWrite),\n outputTokens: numberValue(usage.outputTokens) ?? 0,\n cacheReadTokens: cacheRead,\n cacheWriteTokens: cacheWrite,\n }\n chunks.push({ type: 'usage', usage: tokenUsage })\n }\n chunks.push({ type: 'finish', reason: mapFinishReason(event.finishReason) })\n break\n }\n case 'error': {\n // Mirror the official CLI's stream-error classification\n // (readStreamErrorEvent + isStreamErrorRetryable in command-code's\n // cli.mjs): a stream error that is explicitly non-retryable, carries\n // a terminal marker (quota/plan/credits), or reports a non-retryable\n // HTTP status is a hard failure; anything else is a transient\n // mid-stream drop that the harness's default retry policy should\n // retry (SERVER is in the default retryable set, PROVIDER_STREAM_ERROR\n // is not). Without this, a server-side blip that the official CLI\n // silently recovers from fails the whole turn.\n const err = isRecord(event.error) ? event.error : undefined\n const detail = isRecord(event.error)\n ? (stringValue(event.error.message) ?? JSON.stringify(event.error))\n : (stringValue(event.error) ?? stringValue(event.message) ?? 'Stream error')\n const statusCode = err ? numberValue(err.statusCode) : undefined\n const isRetryable = err ? booleanValue(err.isRetryable) : undefined\n const retryableStatus = statusCode !== undefined && (statusCode === 429 || statusCode >= 500)\n const terminal = hasTerminalStreamMarker(detail)\n const retryable = isRetryable === true\n || (statusCode !== undefined ? retryableStatus : (isRetryable !== false && !terminal))\n if (!retryable) {\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'PROVIDER_STREAM_ERROR',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'SERVER',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n }\n return chunks\n }\n\n try {\n let finished = false\n for (;;) {\n let read: ReadableStreamReadResult<Uint8Array>\n armIdle()\n try {\n read = await reader.read()\n } catch (error: unknown) {\n // A mid-stream transport failure (connection reset, TLS teardown)\n // surfaces here. Caller cancellation propagates as-is.\n if (options.signal?.aborted) throw error\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} failed while reading: ${errorChain(error)}`\n + ';Command Code API 流式响应中途断开——网络波动所致,重试通常可恢复',\n 'TRANSPORT',\n { cause: error },\n )\n } finally {\n clearIdle()\n }\n const { done, value } = read\n if (done) {\n // The idle watchdog cancels the reader to unblock a stalled read;\n // cancel() resolves a pending read() as done, so a done here after\n // the watchdog fired is a timeout, not a normal stream end.\n if (idleFired) {\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} was idle for ${connection.streamIdleTimeoutMs}ms`\n + ' (no events) and was treated as a dead connection'\n + `;Command Code API 流式响应已 ${connection.streamIdleTimeoutMs} 毫秒无任何事件,被判定为死连接——长思考模型可在设置中调大流空闲超时`,\n 'TIMEOUT',\n )\n }\n if (buffer.trim()) for (const chunk of handleEvent(parseStreamEventLine(buffer))) yield chunk\n break\n }\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n const chunks = handleEvent(parseStreamEventLine(line))\n for (const chunk of chunks) {\n yield chunk\n if (chunk.type === 'finish') finished = true\n }\n }\n if (finished) break\n }\n if (!finished) {\n // Stream ended without a finish event: close open blocks and\n // terminate according to the adapter contract (usage, then finish).\n yield* closeText()\n yield* closeReasoning()\n if (!sawContent) {\n throw new LlmError('Command Code returned an empty response;Command Code 返回了空响应,重试通常可恢复', 'EMPTY_RESPONSE')\n }\n yield { type: 'finish', reason: { kind: 'stop' } }\n }\n } finally {\n clearIdle()\n cleanup()\n await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n }\n}\n\n/** Hard cap on account rotations within one request (one attempt per distinct key). */\nconst MAX_ACCOUNT_ROTATIONS = 16\n\n/**\n * Map a pre-stream generate HTTP failure onto a stable LlmError. Command\n * Code folds several business rejections into 403 (plan limits, CLI version,\n * model access): prefer the machine-readable `error.code` when present; the\n * status alone cannot distinguish them. A 429's `Retry-After` rides along as\n * `providerRetryAfterMs` so dsh-llm-retry can wait exactly that long instead\n * of guessing at the backoff cadence — capped at RETRY_MAX_DELAY_MS, because\n * in normal mode a longer attached wait makes the executor abandon the retry\n * outright instead of falling back to local backoff.\n */\nfunction generateHttpError(status: number, errText: string, retryAfterMs?: number): LlmError {\n let providerCode: string | undefined\n try {\n const parsed: unknown = JSON.parse(errText)\n if (isRecord(parsed) && isRecord(parsed.error)) {\n providerCode = stringValue(parsed.error.code)\n }\n } catch {\n // Plain-text bodies: rely on the status mapping below.\n }\n const detail = providerCode ?? `HTTP ${status}`\n if (status === 401) {\n // An invalid or missing credential is a config problem, not a\n // transport failure: retrying it identically cannot succeed. Bilingual —\n // the harness UI renders this message verbatim in its retry chrome.\n return new LlmError(\n `Command Code API error 401 (${detail}): the API key is missing or invalid — check the`\n + ' key stored for COMMANDCODE_API_KEY (Models page) or the auth file'\n + ';Command Code API 返回 401:API 密钥缺失或无效——请在设置页检查 COMMANDCODE_API_KEY 存储的密钥,或检查 auth 文件',\n 'INVALID_CREDENTIAL',\n { status: 401 },\n )\n }\n return new LlmError(\n `Command Code API error ${status}${detail === `HTTP ${status}` ? '' : ` (${detail})`}: ${errText.slice(0, 500)}`,\n status === 429 ? 'RATE_LIMIT' : 'PROVIDER_HTTP_ERROR',\n {\n status,\n ...(retryAfterMs !== undefined && retryAfterMs > 0 && retryAfterMs <= RETRY_MAX_DELAY_MS\n ? { providerRetryAfterMs: retryAfterMs }\n : {}),\n },\n )\n}\n\n/**\n * Parse an HTTP `Retry-After` value (delay-seconds or an HTTP-date) into\n * milliseconds; undefined when absent or unparseable. An HTTP-date in the\n * past yields 0, which the caller drops (LlmError wants a positive delay).\n * A delay-seconds value whose millisecond product is not finite (e.g. `1e308`)\n * also yields undefined: LlmError validates its options and would otherwise\n * replace the provider failure with an internal construction error.\n */\nfunction parseRetryAfterMs(value: string | null | undefined, now = Date.now()): number | undefined {\n if (value === undefined || value === null) return undefined\n const trimmed = value.trim()\n if (trimmed === '') return undefined\n const seconds = Number(trimmed)\n if (Number.isFinite(seconds) && seconds >= 0) {\n const ms = seconds * 1000\n return Number.isFinite(ms) ? Math.round(ms) : undefined\n }\n const date = Date.parse(trimmed)\n if (!Number.isNaN(date)) return Math.max(0, date - now)\n return undefined\n}\n\nfunction mapFinishReason(reason: unknown): FinishReason {\n if (reason === 'tool-calls') return { kind: 'tool-calls' }\n if (\n reason === 'length' ||\n reason === 'max_tokens' ||\n reason === 'max-tokens' ||\n reason === 'max_output_tokens'\n ) {\n return { kind: 'max-tokens' }\n }\n return { kind: 'stop' }\n}\n","/**\n * Locale copy for the `/commandcode` usage command and the friendly\n * image-gate error rewrite. Distinct from `./client/locales.ts` (the\n * settings-page namespace `settings.commandcode`): the command runs on the\n * Host and has no access to the client's `ctx.locale`, so the dictionaries\n * are exposed as plain constants for direct lookup; the resolver lives in\n * `pickCommandLocale()`. The image-gate wrapper also lives on the client\n * but is reached from a non-React path that has no `t` in scope, so the\n * same dictionaries serve both surfaces.\n *\n * zh is the source of truth for the key set; en must carry the exact same\n * keys — a mismatch is a compile error at the lookup site.\n */\n\n/** Active locale id recognized by the command and the image-gate wrapper. */\nexport type LocaleId = 'zh' | 'en'\n\n/** Dictionary keys used by the `/commandcode` command and the image-gate wrapper. */\nexport type CommandCodeCommandKey =\n | 'title' // top heading of a single-account report\n | 'accountTitle' // per-account heading in the multi-account view\n | 'accountSeparator' // rule between accounts in the multi-account view\n | 'activeBadge' // \"currently serving\" badge\n | 'invalidCredentialBadge' // mark for an account whose key is invalid\n | 'cooldownBadge' // mark for an account in rate-limit cooldown\n | 'rateLimitBadge' // mark when the pool has marked a key rate-limited\n | 'unconfigured' // one-account row when the slot has no key\n | 'blockedInvalidKey' // top-of-report block when the whole account is 401\n | 'blockedServiceUnavailable' // 5xx\n | 'blockedNetwork' // network unreachable\n | 'planLine' // \" 📦 套餐 {name}{status}{period}\"\n | 'planPeriodSuffix' // \" · 账期截止 {date}\" / \" · period ends {date}\"\n | 'usageHeader' // \"── 请求 ─────...\"\n | 'requestsLine' // \" 💬 请求 {n} 次 / 失败 {f} 成功率 {r}%\"\n | 'costLine' // \" 💰 花费 {money} ({credits} credits)\"\n | 'tokensLine' // \" 🔤 Token {in} 入 / {out} 出\"\n | 'creditsHeader' // \"── 信用 ─────...\"\n | 'monthlyLine' // \" 💳 月额度 {monthly} (已购 {purchased} / 赠送 {free})\"\n | 'barLine' // \" └ {bar} {pct}%\"\n | 'windowsHeader' // \"── 窗口用量 ─────...\"\n | 'fiveHourLine' // \" ⏱ 5 小时 {used} / {cap}{warn}\"\n | 'weeklyLine' // \" 📅 每周 {used} / {cap}{warn}\"\n | 'windowBarLine' // \" └ {bar} 重置 {when}\"\n | 'exceededWarning' // the trailing \" ⚠️ 超限!\" / \" ⚠️ exceeded!\"\n | 'resetSuffix' // \"重置 {when}\" (the suffix after the bar)\n | 'partialFailures' // \"⚠️ 部分端点失败: {list}\"\n | 'noData' // \"(no data — check your API key)\"\n | 'errorText' // \"Could not fetch Command Code usage: {message}\"\n | 'imageGate' // image-gate rejection rewrite (with {model})\n\nexport const commandcodeCommand: Record<LocaleId, Record<CommandCodeCommandKey, string>> = {\n zh: {\n title: '📊 Command Code 用量{account}',\n accountTitle: '📊 {label}{badges}',\n accountSeparator: '────────────────────',\n activeBadge: ' ✅ 当前使用',\n invalidCredentialBadge: ' ⛔ 密钥无效',\n cooldownBadge: ' ⏳ 限额冷却中,重置 {when}',\n rateLimitBadge: ' ⏳ 已达限额(等待窗口探测)',\n unconfigured: ' (未配置 API 密钥)',\n blockedInvalidKey:\n '⛔ API 密钥无效或已过期 — 服务端拒绝了全部请求(401),请检查该账户的密钥配置',\n blockedServiceUnavailable:\n '⚠️ Command Code 服务暂时不可用(5xx),稍后重试',\n blockedNetwork:\n '⚠️ 无法连接 Command Code 服务 — 请检查网络或 API 地址',\n planLine: ' 📦 套餐 {name}{status}{period}',\n planPeriodSuffix: ' · 账期截止 {date}',\n usageHeader: '── 请求 ──────────────────────────────',\n requestsLine: ' 💬 请求 {n} 次 / 失败 {f} 成功率 {r}%',\n costLine: ' 💰 花费 {money} ({credits} credits)',\n tokensLine: ' 🔤 Token {in} 入 / {out} 出',\n creditsHeader: '── 信用 ──────────────────────────────',\n monthlyLine: ' 💳 月额度 {monthly} (已购 {purchased} / 赠送 {free})',\n barLine: ' └ {bar} {pct}%',\n windowsHeader: '── 窗口用量 ──────────────────────────',\n fiveHourLine: ' ⏱ 5 小时 {used} / {cap}{warn}',\n weeklyLine: ' 📅 每周 {used} / {cap}{warn}',\n windowBarLine: ' └ {bar} 重置 {when}',\n exceededWarning: ' ⚠️ 超限!',\n resetSuffix: '重置 {when}',\n partialFailures: '⚠️ 部分端点失败: {list}',\n noData: '(no data — check your API key)',\n errorText: 'Could not fetch Command Code usage: {message}',\n imageGate:\n '当前会话已包含图片,而模型 {model} 不支持图片输入;'\n + '请选择支持图片的模型,或先移除会话中的图片。',\n },\n en: {\n title: '📊 Command Code usage{account}',\n accountTitle: '📊 {label}{badges}',\n accountSeparator: '────────────────────',\n activeBadge: ' ✅ active',\n invalidCredentialBadge: ' ⛔ invalid key',\n cooldownBadge: ' ⏳ cooling down, resets {when}',\n rateLimitBadge: ' ⏳ rate-limited (waiting for window probe)',\n unconfigured: ' (no API key configured)',\n blockedInvalidKey:\n '⛔ API key invalid or expired — the server rejected every request (401); check the key configured for this account',\n blockedServiceUnavailable:\n '⚠️ Command Code service temporarily unavailable (5xx); try again later',\n blockedNetwork:\n '⚠️ could not reach the Command Code service — check your network or the API base setting',\n planLine: ' 📦 Plan {name}{status}{period}',\n planPeriodSuffix: ' · period ends {date}',\n usageHeader: '── Requests ──────────────────────────',\n requestsLine: ' 💬 Requests {n} / failed {f} success rate {r}%',\n costLine: ' 💰 Spend {money} ({credits} credits)',\n tokensLine: ' 🔤 Tokens {in} in / {out} out',\n creditsHeader: '── Credits ───────────────────────────',\n monthlyLine: ' 💳 Monthly {monthly} (purchased {purchased} / free {free})',\n barLine: ' └ {bar} {pct}%',\n windowsHeader: '── Window usage ──────────────────────',\n fiveHourLine: ' ⏱ 5-hour {used} / {cap}{warn}',\n weeklyLine: ' 📅 Weekly {used} / {cap}{warn}',\n windowBarLine: ' └ {bar} resets {when}',\n exceededWarning: ' ⚠️ exceeded!',\n resetSuffix: 'resets {when}',\n partialFailures: '⚠️ some endpoints failed: {list}',\n noData: '(no data — check your API key)',\n errorText: 'Could not fetch Command Code usage: {message}',\n imageGate:\n 'This session already contains images, and model {model} does not accept'\n + ' image input; please select an image-capable model, or remove the'\n + ' images from the session first.',\n },\n}\n\n/**\n * Resolve the active locale for a Host-side command run.\n *\n * Priority: explicit `override` (from `Config.lang`) → `LC_ALL` → `LANG` →\n * the conventional fallback (`'zh'`, matching the existing single-language\n * behavior so unconfigured deployments keep their current output).\n *\n * The values are matched on the leading tag only — `zh_CN.UTF-8`,\n * `zh-Hans`, `zh` all map to `'zh'`; everything starting with `en` maps to\n * `'en'`; anything else falls back to `'zh'` (a non-`en` shell that\n * already has Chinese in the terminal is the closest sensible default;\n * a Western shell that happens to be neither keeps the existing Chinese\n * output rather than swapping to half-translated English).\n */\nexport function pickCommandLocale(\n override: string | undefined,\n env: Readonly<Record<string, string | undefined>> = process.env as Record<string, string | undefined>,\n): LocaleId {\n if (override === 'zh' || override === 'en') return override\n const raw = env.LC_ALL ?? env.LANG ?? ''\n const tag = raw.toLowerCase().split(/[._-]/)[0] ?? ''\n if (tag === 'en') return 'en'\n return 'zh'\n}\n\n/** Look up a key in the active locale, with an internal en fallback. */\nexport function commandCopy(locale: LocaleId, key: CommandCodeCommandKey): string {\n return commandcodeCommand[locale][key] ?? commandcodeCommand.en[key] ?? key\n}\n","/**\n * `/commandcode` slash command — account usage dashboard.\n *\n * /commandcode show account, usage, and credit state\n * /commandcode status same as bare `/commandcode`\n *\n * Backed by the Command Code account endpoints the official CLI uses\n * (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`),\n * exposed through `CommandCodeAdapter.getUsage()`.\n *\n * The command is Host-side and has no access to the client's `ctx.locale`;\n * the active locale is resolved through `deps.getLocale()` (supplied by the\n * plugin entry from `Config.lang` and the shell's `LC_ALL`/`LANG`). All\n * user-facing copy lives in `./command-locales.ts`; the dictionaries\n * resolve to identical keys, so a missing or unknown locale falls back to\n * `en` rather than dropping text.\n *\n * @module dsh-commandcode-provider/commands\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n// Type-only import that loads the module augmentation (`ctx.commands`).\nimport type { CommandDefinition } from '@deepseek-ai/dsh-commands'\nimport { CommandCodeAdapter } from './adapter.ts'\nimport type { CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\nimport type { CommandCodeAccountUsage, CommandCodeAccountsReport } from './usage-wire.ts'\nimport { commandCopy, type LocaleId } from './command-locales.ts'\n\n/** Everything the command needs beyond the adapter itself. */\nexport interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage / listModels). */\n adapter: CommandCodeAdapter<C>\n /**\n * Multi-account report source (wired by the plugin entry). Absent in\n * programmatic setups, the command falls back to a single\n * `adapter.getUsage()` report.\n */\n reports?: () => Promise<CommandCodeAccountsReport>\n /**\n * Resolve the active locale for one command run. The plugin entry wires\n * this from `Config.lang` and the shell's `LC_ALL`/`LANG`. Absent in\n * programmatic setups (notably the existing test), the command renders\n * with the default locale (`'zh'`) — historically the only language the\n * command ever shipped in.\n */\n getLocale?: () => LocaleId\n}\n\n// ---------------------------------------------------------------------------\n// Number / time formatting (locale-independent; the locale only changes\n// the surrounding labels)\n// ---------------------------------------------------------------------------\n\n/** Format a dollar amount. */\nfunction money(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\n/** Format a dollar amount compactly (2 decimals). */\nfunction moneyShort(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\n/** Format a large token count compactly (1.9M style). */\nfunction tokensCompact(value: number): string {\n if (value >= 1e9) return `${(value / 1e9).toFixed(1)}B`\n if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`\n if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`\n return String(value)\n}\n\n/** Format a millis timestamp as a local date; `n/a` when unset. */\nfunction resetLabel(ms: number): string {\n if (ms <= 0) return 'n/a'\n return new Date(ms).toLocaleString()\n}\n\n/**\n * A 10-cell horizontal bar: `██████████` for 100%, `███░░░░░░░` for ~33%.\n * Handles caps of 0 (no limit) and out-of-range values.\n */\nfunction bar(used: number, cap: number): string {\n if (cap <= 0) return '—'\n const ratio = Math.max(0, Math.min(1, used / cap))\n const filled = Math.round(ratio * 10)\n return '█'.repeat(filled) + '░'.repeat(10 - filled)\n}\n\n// ---------------------------------------------------------------------------\n// Report rendering\n// ---------------------------------------------------------------------------\n\n/** Render one account's rotation mark / cooldown as a short badge. */\nfunction markLabel(entry: CommandCodeAccountUsage, locale: LocaleId): string {\n if (entry.mark === 'invalid-credential') return commandCopy(locale, 'invalidCredentialBadge')\n if (entry.cooldownUntil > 0) {\n return commandCopy(locale, 'cooldownBadge').replace('{when}', resetLabel(entry.cooldownUntil))\n }\n if (entry.mark === 'rate-limit') return commandCopy(locale, 'rateLimitBadge')\n return ''\n}\n\n/** Render the usage report as a structured, aligned, bar-chart text view. */\nfunction renderReport(report: CommandCodeUsageReport, locale: LocaleId, title?: string): string {\n const lines: string[] = []\n const account = report.account ? ` (${report.account.userName || report.account.name})` : ''\n\n lines.push(\n title ?? commandCopy(locale, 'title').replace('{account}', account),\n '',\n )\n\n // A total failure names its cause up front; the per-endpoint failure list\n // at the bottom would bury it.\n if (report.blocked === 'invalid-key') {\n lines.push(commandCopy(locale, 'blockedInvalidKey'), '')\n } else if (report.blocked === 'service-unavailable') {\n lines.push(commandCopy(locale, 'blockedServiceUnavailable'), '')\n } else if (report.blocked === 'network') {\n lines.push(commandCopy(locale, 'blockedNetwork'), '')\n }\n\n if (report.plan && report.plan.name !== '') {\n const p = report.plan\n const status = p.status !== '' && p.status !== 'active' ? ` (${p.status})` : ''\n const period = p.currentPeriodEnd > 0\n ? commandCopy(locale, 'planPeriodSuffix').replace('{date}', new Date(p.currentPeriodEnd).toLocaleDateString())\n : ''\n lines.push(commandCopy(locale, 'planLine')\n .replace('{name}', p.name)\n .replace('{status}', status)\n .replace('{period}', period), '')\n }\n\n if (report.usage) {\n const u = report.usage\n lines.push(\n commandCopy(locale, 'usageHeader'),\n commandCopy(locale, 'requestsLine')\n .replace('{n}', String(u.completedCount))\n .replace('{f}', String(u.failedCount))\n .replace('{r}', String(u.successRate)),\n commandCopy(locale, 'costLine')\n .replace('{money}', money(u.totalCost))\n .replace('{credits}', moneyShort(u.totalCredits)),\n commandCopy(locale, 'tokensLine')\n .replace('{in}', tokensCompact(u.totalTokensIn))\n .replace('{out}', tokensCompact(u.totalTokensOut)),\n '',\n )\n }\n\n if (report.credits) {\n const c = report.credits\n const monthlyPct = c.monthlyCredits > 0\n ? `${((c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits)) * 100).toFixed(0)}%`\n : '—'\n lines.push(\n commandCopy(locale, 'creditsHeader'),\n commandCopy(locale, 'monthlyLine')\n .replace('{monthly}', moneyShort(c.monthlyCredits))\n .replace('{purchased}', moneyShort(c.purchasedCredits))\n .replace('{free}', moneyShort(c.freeCredits)),\n commandCopy(locale, 'barLine')\n .replace('{bar}', bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits))\n .replace('{pct}', monthlyPct),\n '',\n commandCopy(locale, 'windowsHeader'),\n commandCopy(locale, 'fiveHourLine')\n .replace('{used}', moneyShort(c.fiveHour.used))\n .replace('{cap}', moneyShort(c.fiveHour.cap))\n .replace('{warn}', c.fiveHour.exceeded ? commandCopy(locale, 'exceededWarning') : ''),\n commandCopy(locale, 'windowBarLine')\n .replace('{bar}', bar(c.fiveHour.used, c.fiveHour.cap))\n .replace('{when}', resetLabel(c.fiveHour.resetAt)),\n commandCopy(locale, 'weeklyLine')\n .replace('{used}', moneyShort(c.weekly.used))\n .replace('{cap}', moneyShort(c.weekly.cap))\n .replace('{warn}', c.weekly.exceeded ? commandCopy(locale, 'exceededWarning') : ''),\n commandCopy(locale, 'windowBarLine')\n .replace('{bar}', bar(c.weekly.used, c.weekly.cap))\n .replace('{when}', resetLabel(c.weekly.resetAt)),\n '',\n )\n }\n\n if (report.failures.length > 0) {\n lines.push(commandCopy(locale, 'partialFailures').replace('{list}', report.failures.join('; ')), '')\n }\n if (!report.account && !report.usage && !report.credits) {\n lines.push(commandCopy(locale, 'noData'), '')\n }\n\n return lines.join('\\n').trimEnd()\n}\n\n/** The one registered `/commandcode` command. */\nexport function commandDefinition<C extends CommandCodeConnectionOptions>(\n deps: CommandCodeCommandDeps<C>,\n): CommandDefinition {\n const { adapter } = deps\n return {\n name: 'commandcode',\n description: 'Command Code account usage dashboard',\n input: { hint: '[status]' },\n handler: async () => {\n const locale: LocaleId = deps.getLocale?.() ?? 'zh'\n try {\n if (deps.reports !== undefined) {\n const { accounts } = await deps.reports()\n const sections = accounts.map((entry) => {\n const badges = `${entry.active ? commandCopy(locale, 'activeBadge') : ''}${markLabel(entry, locale)}`\n const title = commandCopy(locale, 'accountTitle')\n .replace('{label}', entry.label)\n .replace('{badges}', badges)\n if (!entry.configured) return `${title}\\n\\n${commandCopy(locale, 'unconfigured')}`\n return renderReport(entry.report, locale, title)\n })\n return { kind: 'success', text: sections.join(`\\n\\n${commandCopy(locale, 'accountSeparator')}\\n\\n`) }\n }\n const report = await adapter.getUsage()\n return { kind: 'success', text: renderReport(report, locale) }\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n kind: 'error',\n text: commandCopy(locale, 'errorText').replace('{message}', message),\n }\n }\n },\n }\n}\n\n/** Register the command on `ctx.commands` (called from the plugin entry). */\nexport function applyCommands<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeCommandDeps<C>,\n): void {\n ctx.commands.register(commandDefinition(deps))\n}\n","/**\n * Wire contract for the Command Code account-usage Remote\n * (`commandcode/report`).\n *\n * The settings page renders the same account/usage/credit facts the\n * `/commandcode` command prints, but the browser never holds the API key —\n * the report must be produced Host-side and cross the Connection RPC carrier.\n * The harness exposes plugin-defined Host methods through the Typert Gateway:\n * the Host half registers a strict invocation descriptor against a Cordis\n * service (`src/usage-remote.ts`), and the browser half mounts the matching\n * Remote contribution on `ctx.remote` (`src/client/index.ts`).\n *\n * This module is the single source both halves share: the result validator\n * (a hand-rolled {@link TypertSchema}, so neither half needs a schema library)\n * and the exact descriptor object, so the endpoint can never drift apart.\n * It is deliberately dependency-free — the client bundle inlines it, and only\n * `import type` edges leave it (erased at build).\n *\n * @module dsh-commandcode-provider/usage-wire\n */\n\nimport type { CommandCodeUsageReport, UsageBlockReason } from './adapter.ts'\n\nexport type { CommandCodeUsageReport, UsageBlockReason }\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\n\n/** One account's usage entry in the multi-account report. */\nexport interface CommandCodeAccountUsage {\n /** Stable slot id (`default`, `account-2`, …). */\n id: string\n /** Display label (user-provided or generated). */\n label: string\n /** Whether an API key resolved for this account. */\n configured: boolean\n /** Whether this account currently serves requests (first usable slot). */\n active: boolean\n /** Rotation mark: `''` (usable), `'rate-limit'`, or `'invalid-credential'`. */\n mark: string\n /** Known cooldown end in millis; 0 when unknown or not cooling down. */\n cooldownUntil: number\n /** The per-account report; `failures`-only when the fetch itself failed. */\n report: CommandCodeUsageReport\n}\n\n/** The settings page's account card data: one entry per configured account. */\nexport interface CommandCodeAccountsReport {\n accounts: CommandCodeAccountUsage[]\n}\n\n/** The npm package identity both contribution registrations claim. */\nexport const USAGE_REMOTE_PACKAGE = '@mars-sea/dsh-commandcode-provider'\n\n/** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */\nexport const USAGE_REPORT_ENDPOINT = 'commandcode/report'\n\n/** Reject one boundary value with a field-naming error. */\nfunction reject(field: string): never {\n throw new TypeError(`commandcode/report result: invalid ${field}`)\n}\n\n/** Read one required finite number field (`field` is the dotted error label). */\nfunction numberField(source: Record<string, unknown>, key: string, field: string): number {\n const value = source[key]\n if (typeof value !== 'number' || !Number.isFinite(value)) reject(field)\n return value\n}\n\n/** Read one required string field (`field` is the dotted error label). */\nfunction stringField(source: Record<string, unknown>, key: string, field: string): string {\n const value = source[key]\n if (typeof value !== 'string') reject(field)\n return value\n}\n\n/** Read one required boolean field (`field` is the dotted error label). */\nfunction booleanField(source: Record<string, unknown>, key: string, field: string): boolean {\n const value = source[key]\n if (typeof value !== 'boolean') reject(field)\n return value\n}\n\n/** Narrow an unknown value to a plain record, or reject. */\nfunction record(value: unknown, field: string): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) reject(field)\n return value as Record<string, unknown>\n}\n\n/** Validate one window-limit block (`fiveHour` / `weekly`). */\nfunction windowLimit(value: unknown, field: string): { used: number; cap: number; exceeded: boolean; resetAt: number } {\n const source = record(value, field)\n return {\n used: numberField(source, 'used', `${field}.used`),\n cap: numberField(source, 'cap', `${field}.cap`),\n exceeded: booleanField(source, 'exceeded', `${field}.exceeded`),\n resetAt: numberField(source, 'resetAt', `${field}.resetAt`),\n }\n}\n\n/**\n * Parse one untrusted boundary value into a {@link CommandCodeUsageReport}.\n * Optional sections stay optional; every present field is shape-checked so a\n * malformed frame fails the boundary instead of rendering garbage.\n */\nfunction parseUsageReport(value: unknown): CommandCodeUsageReport {\n const source = record(value, 'report')\n const failures = source.failures\n if (!Array.isArray(failures) || failures.some((entry) => typeof entry !== 'string')) reject('failures')\n const report: CommandCodeUsageReport = { failures: failures as string[] }\n\n if (source.blocked !== undefined) {\n const blocked = source.blocked\n if (blocked !== 'invalid-key' && blocked !== 'service-unavailable' && blocked !== 'network') reject('blocked')\n report.blocked = blocked\n }\n\n if (source.account !== undefined) {\n const account = record(source.account, 'account')\n report.account = {\n id: stringField(account, 'id', 'account.id'),\n name: stringField(account, 'name', 'account.name'),\n userName: stringField(account, 'userName', 'account.userName'),\n }\n }\n\n if (source.usage !== undefined) {\n const usage = record(source.usage, 'usage')\n report.usage = {\n totalCount: numberField(usage, 'totalCount', 'usage.totalCount'),\n totalCost: numberField(usage, 'totalCost', 'usage.totalCost'),\n successRate: numberField(usage, 'successRate', 'usage.successRate'),\n completedCount: numberField(usage, 'completedCount', 'usage.completedCount'),\n failedCount: numberField(usage, 'failedCount', 'usage.failedCount'),\n totalTokensIn: numberField(usage, 'totalTokensIn', 'usage.totalTokensIn'),\n totalTokensOut: numberField(usage, 'totalTokensOut', 'usage.totalTokensOut'),\n totalCredits: numberField(usage, 'totalCredits', 'usage.totalCredits'),\n periodBasis: stringField(usage, 'periodBasis', 'usage.periodBasis'),\n }\n }\n\n if (source.credits !== undefined) {\n const credits = record(source.credits, 'credits')\n report.credits = {\n monthlyCredits: numberField(credits, 'monthlyCredits', 'credits.monthlyCredits'),\n purchasedCredits: numberField(credits, 'purchasedCredits', 'credits.purchasedCredits'),\n freeCredits: numberField(credits, 'freeCredits', 'credits.freeCredits'),\n fiveHour: windowLimit(credits.fiveHour, 'credits.fiveHour'),\n weekly: windowLimit(credits.weekly, 'credits.weekly'),\n }\n }\n\n if (source.plan !== undefined) {\n const plan = record(source.plan, 'plan')\n const monthly = plan.monthlyCredits\n if (monthly !== null && (typeof monthly !== 'number' || !Number.isFinite(monthly))) reject('plan.monthlyCredits')\n report.plan = {\n planId: stringField(plan, 'planId', 'plan.planId'),\n name: stringField(plan, 'name', 'plan.name'),\n status: stringField(plan, 'status', 'plan.status'),\n monthlyCredits: monthly as number | null,\n currentPeriodEnd: numberField(plan, 'currentPeriodEnd', 'plan.currentPeriodEnd'),\n }\n }\n\n return report\n}\n\n/** Parse one untrusted boundary value into a {@link CommandCodeAccountUsage}. */\nfunction parseAccountUsage(value: unknown): CommandCodeAccountUsage {\n const source = record(value, 'account')\n return {\n id: stringField(source, 'id', 'account.id'),\n label: stringField(source, 'label', 'account.label'),\n configured: booleanField(source, 'configured', 'account.configured'),\n active: booleanField(source, 'active', 'account.active'),\n mark: stringField(source, 'mark', 'account.mark'),\n cooldownUntil: numberField(source, 'cooldownUntil', 'account.cooldownUntil'),\n report: parseUsageReport(source.report),\n }\n}\n\n/** Parse the wire result into a {@link CommandCodeAccountsReport}. */\nfunction parseAccountsReport(value: unknown): CommandCodeAccountsReport {\n const source = record(value, 'result')\n const accounts = source.accounts\n if (!Array.isArray(accounts)) reject('accounts')\n return { accounts: accounts.map(parseAccountUsage) }\n}\n\n/**\n * The strict result codec both halves attach to the descriptor. Hand-rolled:\n * the client bundle may not require a schema library, and `TypertSchema` is\n * deliberately minimal so one `parse` function satisfies it.\n */\nexport const usageReportSchema: TypertSchema<CommandCodeAccountsReport> = {\n parse: parseAccountsReport,\n}\n\n/**\n * The one invocation descriptor, shared verbatim by the Host registration and\n * the Client mount. `service` names the Cordis key the Gateway resolves the\n * receiver from; `namespace`/`method` name the wire endpoint.\n */\nexport const USAGE_REPORT_DESCRIPTOR: InvocationDescriptor = {\n id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method: 'report',\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`,\n schema: usageReportSchema,\n },\n}\n\n/** The Host-face contribution registered on `ctx.typert`. */\nexport const USAGE_HOST_CONTRIBUTION = {\n package: USAGE_REMOTE_PACKAGE,\n face: 'host' as const,\n schemas: [],\n // 0.1.2's Typert registry requires every Host contribution to carry its\n // reflection model. This hand-written Remote deliberately has no generated\n // reflection exports, so use the official empty-model form rather than a\n // cast that leaves registry inspection with `model: undefined`.\n model: { services: [], events: [], objects: [] },\n invocations: [USAGE_REPORT_DESCRIPTOR],\n}\n\n/** The Client-face contribution mounted on `ctx.remote`. */\nexport const USAGE_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [USAGE_REPORT_DESCRIPTOR],\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog Remote (`commandcode/models`)\n// ---------------------------------------------------------------------------\n\n/** One catalog entry the settings page's routing-rule editor offers. */\nexport interface CommandCodeCatalogModel {\n /** Catalog model id (e.g. `deepseek/deepseek-v4-pro`). */\n id: string\n /** Display name from the catalog. */\n name: string\n}\n\n/** The model-catalog Remote result: the full catalog, sorted for picking. */\nexport interface CommandCodeCatalog {\n models: CommandCodeCatalogModel[]\n}\n\n/** Canonical `<namespace>/<method>` endpoint of the model-catalog Remote. */\nexport const MODELS_ENDPOINT = 'commandcode/models'\n\n/** Parse one untrusted boundary value into a {@link CommandCodeCatalogModel}. */\nfunction parseCatalogModel(value: unknown): CommandCodeCatalogModel {\n const source = record(value, 'model')\n return {\n id: stringField(source, 'id', 'model.id'),\n name: stringField(source, 'name', 'model.name'),\n }\n}\n\n/** Parse the wire result into a {@link CommandCodeCatalog}. */\nfunction parseCatalog(value: unknown): CommandCodeCatalog {\n const source = record(value, 'result')\n const models = source.models\n if (!Array.isArray(models)) reject('models')\n return { models: models.map(parseCatalogModel) }\n}\n\n/** The strict result codec for the model-catalog Remote. */\nexport const modelsSchema: TypertSchema<CommandCodeCatalog> = {\n parse: parseCatalog,\n}\n\n/**\n * The model-catalog invocation descriptor, sharing the same `commandcodeUsage`\n * service and `commandcode` namespace as the usage report.\n */\nexport const MODELS_DESCRIPTOR: InvocationDescriptor = {\n id: `${USAGE_REMOTE_PACKAGE}#${MODELS_ENDPOINT}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method: 'models',\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`,\n schema: modelsSchema,\n },\n}\n\n/** The Client-face contribution for the model-catalog endpoint. */\nexport const MODELS_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [MODELS_DESCRIPTOR],\n}\n","/**\n * Wire contract for the Command Code login Remote endpoints\n * (`commandcode/loginBegin`, `commandcode/loginStatus`,\n * `commandcode/loginCancel`).\n *\n * The settings page can start a browser login against the official Command\n * Code Studio (the same loopback flow `command-code login` performs) instead\n * of pasting an API key. The loopback server must live in the Host half — it\n * binds a local port and receives the key — so the page drives it through the\n * Typert Gateway exactly like the usage report.\n *\n * This module is the single source both halves share, deliberately\n * dependency-free (`import type` edges only): the strict status validator the\n * client trusts, the three descriptors both halves register, and the two\n * contribution objects. The state shape mirrors the Host-only flow machine in\n * `src/login.ts` as plain JSON.\n *\n * @module dsh-commandcode-provider/login-wire\n */\n\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\nimport { USAGE_REMOTE_PACKAGE } from './usage-wire.ts'\n\n/** Why a login attempt ended in `failed` (stable across versions for copy). */\nexport type CommandCodeLoginFailureReason =\n /** The Studio page reported the authorization was denied by the user. */\n | 'denied'\n /** No callback arrived within the flow's timeout window. */\n | 'timeout'\n /** The delivered key failed `/alpha/whoami` validation (401). */\n | 'invalid-key'\n /** The validation request could not reach the API. */\n | 'network'\n /** The key could not be stored (credentials seam unavailable). */\n | 'unavailable'\n /** The attempt was cancelled by the user or torn down with the plugin. */\n | 'cancelled'\n /** Anything else. */\n | 'error'\n\n/** One login attempt's full state face, as carried over the wire. */\nexport interface CommandCodeLoginStatus {\n /**\n * `idle` — no attempt; `waiting` — the loopback server is up and the\n * Studio URL is live; `success` — the key validated and was stored;\n * `failed` — see `reason`/`message`.\n */\n state: 'idle' | 'waiting' | 'success' | 'failed'\n /** The Studio authorization URL while `waiting`. */\n authUrl?: string\n /** The account display name reported by the Studio, on `success`. */\n userName?: string\n /** The key's label from the Studio, on `success`. */\n keyName?: string\n /** Why the attempt failed, when `failed`. */\n reason?: CommandCodeLoginFailureReason\n /** Human-readable failure detail, when `failed` (secondary to `reason`). */\n message?: string\n}\n\n/** The canonical endpoint paths of the three login Remotes. */\nexport const LOGIN_BEGIN_ENDPOINT = 'commandcode/loginBegin'\nexport const LOGIN_STATUS_ENDPOINT = 'commandcode/loginStatus'\nexport const LOGIN_CANCEL_ENDPOINT = 'commandcode/loginCancel'\n\nconst REASONS: readonly CommandCodeLoginFailureReason[] = [\n 'denied', 'timeout', 'invalid-key', 'network', 'unavailable', 'cancelled', 'error',\n]\n\n/** Reject one boundary value with a field-naming error. */\nfunction reject(field: string): never {\n throw new TypeError(`commandcode/login result: invalid ${field}`)\n}\n\n/**\n * Parse one untrusted boundary value into a {@link CommandCodeLoginStatus}.\n * Every field is shape-checked so a malformed frame fails the boundary\n * instead of leaking into the page.\n */\nexport function parseLoginStatus(value: unknown): CommandCodeLoginStatus {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) reject('status')\n const source = value as Record<string, unknown>\n const state = source.state\n if (state !== 'idle' && state !== 'waiting' && state !== 'success' && state !== 'failed') {\n reject('state')\n }\n const status: CommandCodeLoginStatus = { state }\n if (source.authUrl !== undefined) {\n if (typeof source.authUrl !== 'string') reject('authUrl')\n status.authUrl = source.authUrl\n }\n if (source.userName !== undefined) {\n if (typeof source.userName !== 'string') reject('userName')\n status.userName = source.userName\n }\n if (source.keyName !== undefined) {\n if (typeof source.keyName !== 'string') reject('keyName')\n status.keyName = source.keyName\n }\n if (source.reason !== undefined) {\n if (!REASONS.includes(source.reason as CommandCodeLoginFailureReason)) reject('reason')\n status.reason = source.reason as CommandCodeLoginFailureReason\n }\n if (source.message !== undefined) {\n if (typeof source.message !== 'string') reject('message')\n status.message = source.message\n }\n return status\n}\n\n/** The strict result codec shared by all three login endpoints. */\nexport const loginStatusSchema: TypertSchema<CommandCodeLoginStatus> = {\n parse: parseLoginStatus,\n}\n\n/** Build one login invocation descriptor (uniform result, no parameters). */\nfunction loginDescriptor(endpoint: string, method: string): InvocationDescriptor {\n return {\n id: `${USAGE_REMOTE_PACKAGE}#${endpoint}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method,\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeLoginStatus`,\n schema: loginStatusSchema,\n },\n }\n}\n\n/** The three login descriptors, shared verbatim by Host registration and Client mount. */\nexport const LOGIN_DESCRIPTORS: readonly InvocationDescriptor[] = [\n loginDescriptor(LOGIN_BEGIN_ENDPOINT, 'loginBegin'),\n loginDescriptor(LOGIN_STATUS_ENDPOINT, 'loginStatus'),\n loginDescriptor(LOGIN_CANCEL_ENDPOINT, 'loginCancel'),\n]\n\n/** The Host-face contribution fragment registered on `ctx.typert`. */\nexport const LOGIN_HOST_CONTRIBUTION = {\n package: USAGE_REMOTE_PACKAGE,\n face: 'host' as const,\n schemas: [],\n invocations: LOGIN_DESCRIPTORS,\n}\n\n/** The Client-face contribution fragment mounted on `ctx.remote`. */\nexport const LOGIN_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: LOGIN_DESCRIPTORS,\n}\n","/**\n * Host half of the account-usage Remote (`commandcode/report`).\n *\n * The settings page's account card needs the same report the `/commandcode`\n * command prints, but the browser never holds the API key — the fetch must\n * run Host-side. This module exposes `adapter.getUsage()` through the Typert\n * Gateway: a `TypertRemoteService` provides the receiver the Gateway resolves,\n * and the shared strict descriptor (`src/usage-wire.ts`) is registered on the\n * `typert` registry so the Gateway claims the `commandcode/report` endpoint.\n *\n * The whole wiring rides an optional `ctx.inject(['typert'], ...)` fiber: a\n * profile without the web stack (no Typert registry, no Gateway) simply never\n * activates it, exactly like the `/commandcode` command rides `commands`.\n *\n * @module dsh-commandcode-provider/usage-remote\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport type { CommandCodeAdapter, CommandCodeConnectionOptions } from './adapter.ts'\nimport { USAGE_HOST_CONTRIBUTION } from './usage-wire.ts'\nimport { MODELS_DESCRIPTOR } from './usage-wire.ts'\nimport type { CommandCodeAccountsReport, CommandCodeCatalog } from './usage-wire.ts'\nimport { LOGIN_DESCRIPTORS } from './login-wire.ts'\nimport type { CommandCodeLoginStatus } from './login-wire.ts'\n\n/**\n * The browser-login face the usage service exposes (`commandcode/login*`).\n * Backed by the Host-half {@link !CommandCodeLoginFlow} when the plugin entry\n * wired one; absent, the methods degrade to a no-op status so an old client\n * against a fresh page still answers instead of hanging.\n */\nexport interface LoginFlowFacade {\n /** Start (or rejoin) an attempt; rejects when it cannot start at all. */\n begin(): Promise<CommandCodeLoginStatus>\n /** The current attempt's status. */\n status(): CommandCodeLoginStatus\n /** Cancel a waiting attempt. */\n cancel(): void\n}\n\n/** Everything the usage service needs beyond its Cordis context. */\nexport interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage). */\n adapter: CommandCodeAdapter<C>\n /**\n * Multi-account report source (wired by the plugin entry). Absent in\n * programmatic setups, the service falls back to a single default-account\n * entry around `adapter.getUsage()`.\n */\n reports?: () => Promise<CommandCodeAccountsReport>\n /**\n * Model-catalog source for the routing-rule editor (wired by the plugin\n * entry). Absent, the `models` endpoint answers an empty list — the page's\n * rule editor degrades to the empty state.\n */\n listModels?: () => Promise<CommandCodeCatalog>\n /**\n * The browser-login flow (wired by the plugin entry). Absent means the\n * login endpoints answer `idle` / reject with a plain message — the page's\n * manual paste path stays the fallback.\n */\n login?: LoginFlowFacade\n}\n\n/**\n * The registry method surface this module uses. `Context['typert']` is typed\n * as the read-only `TypertRegistryContract`; contribution registration lives\n * on the concrete registry service, so the cast is spelled out once here.\n */\ninterface TypertContributionRegistry {\n register(contribution: typeof USAGE_HOST_CONTRIBUTION): () => void | Promise<void>\n}\n\n/**\n * The Remote receiver: a Cordis service the Gateway resolves by key\n * (`commandcodeUsage`) and binds to the wire namespace (`commandcode`). The\n * base class stamps the `typertRemote` binding the Gateway validates on every\n * dispatch; no decorators are needed because the descriptor is registered\n * explicitly (strict path) rather than discovered from source markers.\n */\nexport class CommandCodeUsageService<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions>\n extends TypertRemoteService {\n private readonly deps: CommandCodeUsageDeps<C>\n\n constructor(ctx: Context, deps: CommandCodeUsageDeps<C>) {\n super(ctx, 'commandcodeUsage', { namespace: 'commandcode' })\n this.deps = deps\n }\n\n /**\n * Account, usage, and credit state for the settings page's account card —\n * one entry per pool account when the plugin entry wired `reports`, a\n * single default-account entry otherwise. Degrades per endpoint like the\n * `/commandcode` command (failures land in `report.failures`); throws\n * `MISSING_CREDENTIAL` when no key resolves, which the Gateway folds into\n * the failure branch the page renders as a hint.\n */\n async report(): Promise<CommandCodeAccountsReport> {\n if (this.deps.reports !== undefined) return this.deps.reports()\n const report = await this.deps.adapter.getUsage()\n return {\n accounts: [{\n id: 'default',\n label: 'Default',\n configured: true,\n active: true,\n mark: '',\n cooldownUntil: 0,\n report,\n }],\n }\n }\n\n /**\n * The model catalog for the settings page's routing-rule editor. The\n * browser never calls the Command Code API directly — the Host serves the\n * catalog (already fetched/cached by the adapter) so rules can be picked\n * from the live model list instead of typed by hand.\n */\n async models(): Promise<CommandCodeCatalog> {\n return this.deps.listModels?.() ?? { models: [] }\n }\n\n /**\n * Start (or rejoin) a browser-login attempt and return its fresh status —\n * `waiting` carrying the Studio URL. Rejects when the flow cannot start\n * (no free loopback port, disposed plugin); the Gateway folds the throw\n * into the failure branch the page renders.\n */\n async loginBegin(): Promise<CommandCodeLoginStatus> {\n const login = this.requireLogin()\n return login.begin()\n }\n\n /** Poll a login attempt's status. */\n async loginStatus(): Promise<CommandCodeLoginStatus> {\n return this.deps.login?.status() ?? { state: 'idle' }\n }\n\n /** Cancel a waiting attempt; returns the post-cancel status. */\n async loginCancel(): Promise<CommandCodeLoginStatus> {\n this.deps.login?.cancel()\n return this.deps.login?.status() ?? { state: 'idle' }\n }\n\n private requireLogin(): LoginFlowFacade {\n const login = this.deps.login\n if (login === undefined) {\n throw new Error('login flow is not wired in this setup; paste the API key instead')\n }\n return login\n }\n}\n\n/**\n * Provide the usage service and register its Remote descriptor. The registry\n * contribution is tied to this fiber's lifetime: the registry's own\n * `register()` effect would otherwise outlive the plugin.\n */\nexport function applyUsageRemote<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeUsageDeps<C>,\n): void {\n ctx.inject(['typert'], (remoteCtx) => {\n new CommandCodeUsageService(remoteCtx, deps)\n const registry = remoteCtx.typert as unknown as TypertContributionRegistry\n // One registration carries the report endpoint, the models endpoint, and\n // the login endpoints: the descriptors are unique per endpoint, and a\n // single contribution keeps the Host's registry bookkeeping (and the\n // Client mount) 1:1.\n const unregister = registry.register({\n ...USAGE_HOST_CONTRIBUTION,\n invocations: [...USAGE_HOST_CONTRIBUTION.invocations, MODELS_DESCRIPTOR, ...LOGIN_DESCRIPTORS],\n })\n // The registry's own effect would outlive this fiber; withdraw the\n // contribution when the plugin unloads.\n remoteCtx.effect(() => () => void unregister(), 'dsh-commandcode-provider: usage remote')\n })\n}\n","/**\n * Host half of the Command Code browser login (the loopback flow).\n *\n * Mirrors what the official `command-code login` CLI command performs\n * (reverse-engineered from `command-code@1.32.1`, `createAuthFlowController`\n * + `createAuthServer` in its bundle):\n *\n * 1. Bind a temporary HTTP server on `127.0.0.1`, first available port from\n * 5959 upward (10 attempts).\n * 2. Generate a random state token and open\n * `{studio}/studio/auth/cli?callback=http://localhost:{port}/callback&state={state}`.\n * 3. After the user signs in, the Studio page POSTs the credentials JSON\n * `{ apiKey, state, userId, userName, keyName }` to the loopback callback —\n * no OAuth code exchange, the page holds the final API key.\n * 4. The delivered key is validated against `GET {apiBase}/alpha/whoami`\n * before anything is stored.\n *\n * Server behaviour is mirrored exactly: POST-only `/callback`, a 10 KB body\n * cap, JSON responses (`{success:true}` / `{success:false,error}`), CORS for\n * the Studio origins only, and state-token equality as the anti-forgery\n * check. One deliberate hardening over the CLI build: the CORS origin is\n * echoed only when it is allowlisted (the CLI falls back to the first\n * origin), which browsers treat identically.\n *\n * Storage stays out of this module: the plugin entry supplies\n * {@link CommandCodeLoginFlowDeps.storeKey}, which writes through the dsh\n * credentials seam so the next request resolves the new key with no restart.\n * Everything external (fetch, ports, randomness, timing) is injectable for\n * node tests; the tests drive a real loopback server end to end.\n *\n * @module dsh-commandcode-provider/login\n */\n\nimport { createServer as createHttpServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http'\nimport { createServer as createNetServer } from 'node:net'\nimport { randomBytes } from 'node:crypto'\nimport { DEFAULT_API_BASE } from './adapter.ts'\nimport type { CommandCodeLoginFailureReason, CommandCodeLoginStatus } from './login-wire.ts'\n\n/** Give up on the browser after this long without a callback (mirrors the CLI). */\nexport const LOGIN_TIMEOUT_MS = 120_000\n\n/** First local port the flow tries (mirrors the CLI). */\nexport const LOGIN_START_PORT = 5959\n\n/** How many consecutive ports to try from {@link LOGIN_START_PORT}. */\nexport const LOGIN_MAX_PORT_ATTEMPTS = 10\n\n/** Reject callback bodies larger than this (mirrors the CLI). */\nexport const LOGIN_BODY_LIMIT_BYTES = 10_000\n\n/** The Studio origins allowed to POST credentials to the loopback server. */\nexport const LOGIN_ALLOWED_ORIGINS: readonly string[] = [\n 'http://localhost:3000',\n 'https://staging.commandcode.ai',\n 'https://commandcode.ai',\n]\n\n/** The Studio route that performs the browser-side login. */\nconst STUDIO_AUTH_PATH = '/studio/auth/cli'\n\n/** Credentials as delivered by the Studio's callback POST. */\nexport interface CommandCodeLoginCredentials {\n apiKey: string\n userId: string\n userName: string\n keyName: string\n}\n\n/** Outcome of validating a delivered key against `/alpha/whoami`. */\nexport type ApiKeyValidation =\n | { valid: true }\n | { valid: false; error: 'invalid_key' | 'server_error' | 'network_error' }\n\nexport interface CommandCodeLoginFlowDeps {\n /**\n * The Provider API base used for `/alpha/whoami` validation; also selects\n * the matching Studio base (staging api → staging studio). A thunk is fine:\n * it is re-read when each attempt starts, so a settings change reaches the\n * next login. Defaults to the public API base.\n */\n apiBase?: string | (() => string | undefined)\n /** Attempt timeout in millis; defaults to {@link LOGIN_TIMEOUT_MS}. */\n timeoutMs?: number\n /** First port to try; defaults to {@link LOGIN_START_PORT}. */\n startPort?: number\n /** Consecutive-port attempts; defaults to {@link LOGIN_MAX_PORT_ATTEMPTS}. */\n maxPortAttempts?: number\n /** Validation fetch seam; defaults to global `fetch`. */\n fetchImpl?: typeof fetch\n /** Randomness seam; defaults to `node:crypto` randomBytes(32) base64url. */\n randomToken?: (byteLength: number) => string\n /**\n * Receives the validated credentials after a successful login. Rejecting\n * fails the attempt with `unavailable`.\n */\n storeKey(credentials: CommandCodeLoginCredentials): Promise<void>\n}\n\n/** Compose the Studio authorization URL (pure, exported for tests). */\nexport function buildCommandAuthUrl(options: { studioBase: string; port: number; state: string }): string {\n const callback = `http://localhost:${options.port}/callback`\n return `${options.studioBase}${STUDIO_AUTH_PATH}?callback=${encodeURIComponent(callback)}&state=${encodeURIComponent(options.state)}`\n}\n\n/** Map an API base onto the Studio base the CLI pairs it with. */\nexport function studioBaseForApiBase(apiBase: string): string {\n if (/^https:\\/\\/staging-api\\.commandcode\\.ai/i.test(apiBase)) return 'https://staging.commandcode.ai'\n if (/^http:\\/\\/localhost(:\\d+)?$/i.test(apiBase)) return 'http://localhost:3000'\n return 'https://commandcode.ai'\n}\n\n/**\n * Validate one candidate key against `/alpha/whoami` (pure, exported for\n * tests). Mirrors the CLI's verdicts: 401 → invalid_key, other non-OK →\n * server_error, transport failure → network_error.\n */\nexport async function validateCommandApiKey(\n fetchImpl: typeof fetch,\n apiBase: string,\n apiKey: string,\n): Promise<ApiKeyValidation> {\n try {\n const response = await fetchImpl(`${apiBase}/alpha/whoami`, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },\n })\n if (response.status === 401) return { valid: false, error: 'invalid_key' }\n if (response.ok) return { valid: true }\n return { valid: false, error: 'server_error' }\n } catch {\n return { valid: false, error: 'network_error' }\n }\n}\n\n/** Whether one loopback port is free right now. */\nfunction checkPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const probe = createNetServer()\n probe.once('error', () => resolve(false))\n probe.once('listening', () => probe.close(() => resolve(true)))\n probe.listen(port, '127.0.0.1')\n })\n}\n\n/** Whether a callback body carries every credential field the CLI requires. */\nfunction isCallbackCredentials(value: unknown): value is CommandCodeLoginCredentials & Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Record<string, unknown>\n return typeof record.apiKey === 'string' && record.apiKey !== ''\n && typeof record.state === 'string'\n && typeof record.userId === 'string'\n && typeof record.userName === 'string'\n && typeof record.keyName === 'string'\n}\n\n/**\n * One browser-login attempt machine. Single-flight by design: `begin()` while\n * waiting returns the live attempt's status instead of starting a second one;\n * a terminal state makes the next `begin()` start fresh.\n */\nexport class CommandCodeLoginFlow {\n private readonly deps: CommandCodeLoginFlowDeps\n private readonly listeners = new Set<() => void>()\n\n private statusValue: CommandCodeLoginStatus = { state: 'idle' }\n private server: Server | undefined\n private timer: ReturnType<typeof setTimeout> | undefined\n /** Settle hooks of the live attempt's callback promise. */\n private settle: {\n resolve(credentials: CommandCodeLoginCredentials): void\n reject(failure: LoginSettleError): void\n } | undefined\n private disposed = false\n\n constructor(deps: CommandCodeLoginFlowDeps) {\n this.deps = deps\n }\n\n /** Subscribe to state transitions. @returns the disposer. */\n onChange(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** The current attempt's status face. */\n status(): CommandCodeLoginStatus {\n return this.statusValue\n }\n\n /**\n * Start an attempt (or rejoin the live one) and resolve with its status —\n * `waiting` carrying the Studio URL once the loopback server is up.\n * Rejects only when the flow cannot start at all (no free port, disposed).\n */\n async begin(): Promise<CommandCodeLoginStatus> {\n if (this.disposed) throw new Error('login flow has been disposed')\n if (this.statusValue.state === 'waiting') return this.statusValue\n this.teardown()\n\n const port = await this.findPort()\n const expectedState = this.deps.randomToken?.(32) ?? randomBytes(32).toString('base64url')\n\n // The attempt settles exactly once: fulfilled with delivered credentials,\n // rejected with a tagged failure the mapping below turns into copy.\n const settled = new Promise<CommandCodeLoginCredentials>((resolve, reject) => {\n this.settle = { resolve, reject }\n })\n // A bind failure must surface before the attempt reports `waiting`.\n await this.bindServer(port, expectedState)\n\n const apiBase = this.readApiBase()\n this.setStatus({\n state: 'waiting',\n authUrl: buildCommandAuthUrl({ studioBase: studioBaseForApiBase(apiBase), port, state: expectedState }),\n })\n\n // Watchdog mirrors the CLI's 2-minute window.\n this.timer = setTimeout(() => {\n this.teardown()\n this.setStatus({\n state: 'failed',\n reason: 'timeout',\n message: 'No browser callback arrived within the login window.',\n })\n }, this.deps.timeoutMs ?? LOGIN_TIMEOUT_MS)\n this.timer.unref?.()\n\n void settled.then(\n (credentials) => this.complete(credentials),\n (failure) => this.failFrom(failure),\n )\n return this.statusValue\n }\n\n /** Cancel a waiting attempt; terminal states are untouched. */\n cancel(): void {\n if (this.disposed || this.statusValue.state !== 'waiting') return\n this.teardown()\n this.setStatus({ state: 'failed', reason: 'cancelled' })\n }\n\n /** Stop everything; a waiting attempt ends cancelled. Idempotent. */\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n const wasWaiting = this.statusValue.state === 'waiting'\n this.teardown()\n if (wasWaiting) this.setStatus({ state: 'failed', reason: 'cancelled' })\n }\n\n // -----------------------------------------------------------------------\n // Internals\n // -----------------------------------------------------------------------\n\n private readApiBase(): string {\n const raw = typeof this.deps.apiBase === 'function' ? this.deps.apiBase() : this.deps.apiBase\n return raw ?? DEFAULT_API_BASE\n }\n\n private setStatus(next: CommandCodeLoginStatus): void {\n this.statusValue = next\n for (const listener of [...this.listeners]) listener()\n }\n\n /** First free port among the consecutive candidates. */\n private async findPort(): Promise<number> {\n const startPort = this.deps.startPort ?? LOGIN_START_PORT\n const attempts = this.deps.maxPortAttempts ?? LOGIN_MAX_PORT_ATTEMPTS\n for (let index = 0; index < attempts; index += 1) {\n const candidate = startPort + index\n if (await checkPortAvailable(candidate)) return candidate\n }\n throw new Error(`No available port found after ${attempts} attempts starting from port ${startPort}`)\n }\n\n /**\n * Bind the attempt's loopback server, resolving when the port is live.\n * Pre-bind failures reject (surfacing from `begin()`); a later server error\n * settles the live attempt as a tagged failure instead.\n */\n private bindServer(port: number, expectedState: string): Promise<void> {\n return new Promise((resolve, reject) => {\n let binding = true\n const server = createHttpServer((request, response) => this.handleCallback(request, response, expectedState))\n this.server = server\n server.once('error', (error: NodeJS.ErrnoException) => {\n if (this.server !== server) return\n this.server = undefined\n const tagged = new LoginSettleError(\n 'error',\n `Could not bind the login callback server on port ${port}: ${error.code ?? error.message}`,\n )\n if (binding) {\n binding = false\n reject(tagged)\n } else {\n this.settle?.reject(tagged)\n }\n })\n server.listen(port, '127.0.0.1', () => {\n if (!binding) return\n binding = false\n resolve()\n })\n })\n }\n\n /** One request against the attempt's callback endpoint (CLI-mirrored). */\n private handleCallback(request: IncomingMessage, response: ServerResponse, expectedState: string): void {\n // One-shot responses: the server dies with the attempt, and a client\n // pooling the connection would otherwise race its next request against\n // the close.\n response.setHeader('Connection', 'close')\n response.setHeader('Access-Control-Allow-Origin', corsOrigin(request.headers.origin))\n response.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS')\n response.setHeader('Access-Control-Allow-Headers', 'Content-Type')\n response.setHeader('Content-Type', 'application/json')\n const json = (code: number, body: Record<string, unknown>) => {\n response.writeHead(code)\n response.end(JSON.stringify(body))\n }\n if (request.method === 'OPTIONS') {\n response.writeHead(204)\n response.end()\n return\n }\n const path = request.url?.split('?')[0] ?? '/'\n if (path !== '/callback') {\n json(404, { success: false, error: 'Not found' })\n return\n }\n if (request.method !== 'POST') {\n json(405, { success: false, error: 'Method not allowed. Use POST.' })\n return\n }\n let body = ''\n request.on('data', (chunk: Buffer) => {\n body += chunk.toString()\n if (body.length > LOGIN_BODY_LIMIT_BYTES) request.destroy()\n })\n request.on('end', () => {\n let payload: unknown\n try {\n payload = JSON.parse(body)\n } catch {\n json(400, { success: false, error: 'Invalid JSON' })\n return\n }\n // The Studio reports a denied authorization as an error object.\n if (typeof payload === 'object' && payload !== null && 'error' in payload) {\n const denial = payload as Record<string, unknown>\n const description = denial.error_description ?? denial.error\n this.settleAttempt(json, 200, { success: true }, new LoginSettleError(\n denial.error === 'access_denied' ? 'denied' : 'error',\n typeof description === 'string' && description !== '' ? description : 'Authorization failed',\n ))\n return\n }\n if (!isCallbackCredentials(payload)) {\n json(400, { success: false, error: 'Missing required fields' })\n return\n }\n if (payload.state !== expectedState) {\n // Not terminal: a stale tab replaying an old state must not kill the\n // live attempt — answer 403 and keep waiting (the CLI does the same).\n json(403, { success: false, error: 'Invalid state token' })\n return\n }\n this.settleAttempt(json, 200, { success: true }, undefined, { ...payload })\n })\n request.on('error', () => {})\n }\n\n /** Answer a decisive callback, stop listening, and settle the attempt. */\n private settleAttempt(\n json: (code: number, body: Record<string, unknown>) => void,\n code: number,\n body: Record<string, unknown>,\n failure?: LoginSettleError,\n credentials?: CommandCodeLoginCredentials,\n ): void {\n json(code, body)\n // Capture the settle hooks BEFORE teardown clears them.\n const settle = this.settle\n this.teardown()\n if (settle === undefined) return\n if (failure !== undefined) settle.reject(failure)\n else if (credentials !== undefined) settle.resolve(credentials)\n }\n\n /** Post-validation completion: whoami check, then hand-off to storage. */\n private async complete(credentials: CommandCodeLoginCredentials): Promise<void> {\n if (this.disposed || this.statusValue.state !== 'waiting') return\n const validation = await validateCommandApiKey(\n this.deps.fetchImpl ?? fetch,\n this.readApiBase(),\n credentials.apiKey,\n )\n if (!validation.valid) {\n const reason: CommandCodeLoginFailureReason = validation.error === 'invalid_key'\n ? 'invalid-key'\n : validation.error === 'network_error' ? 'network' : 'error'\n this.setStatus({\n state: 'failed',\n reason,\n message: `/alpha/whoami rejected the delivered key (${validation.error}).`,\n })\n return\n }\n try {\n await this.deps.storeKey(credentials)\n } catch (error: unknown) {\n this.setStatus({\n state: 'failed',\n reason: 'unavailable',\n message: error instanceof Error ? error.message : String(error),\n })\n return\n }\n if (this.disposed) return\n this.clearTimer()\n this.setStatus({ state: 'success', userName: credentials.userName, keyName: credentials.keyName })\n }\n\n /** Map a tagged settle rejection onto the status face. */\n private failFrom(failure: unknown): void {\n if (!(failure instanceof LoginSettleError)) return\n if (this.disposed || this.statusValue.state !== 'waiting') return\n this.setStatus({ state: 'failed', reason: failure.reason, message: failure.message })\n }\n\n private clearTimer(): void {\n if (this.timer !== undefined) {\n clearTimeout(this.timer)\n this.timer = undefined\n }\n }\n\n /** Close the server and watchdog without touching the published status. */\n private teardown(): void {\n this.clearTimer()\n this.server?.close()\n this.server = undefined\n this.settle = undefined\n }\n}\n\n/** A tagged settle failure carrying the stable copy reason. */\nclass LoginSettleError extends Error {\n constructor(public readonly reason: CommandCodeLoginFailureReason, message: string) {\n super(message)\n this.name = 'LoginSettleError'\n }\n}\n\n/** Echo the Origin header only when the Studio allowlist contains it. */\nfunction corsOrigin(origin: string | undefined): string {\n return origin !== undefined && LOGIN_ALLOWED_ORIGINS.includes(origin) ? origin : ''\n}\n","/**\n * dsh-commandcode-provider — Command Code web search provider over `ctx.web`.\n *\n * The official Command Code CLI ships a built-in `web_search` tool that POSTs\n * `{ query, numResults, allowedDomains?, blockedDomains? }` to\n * `{apiBase}/alpha/web-search` and reads `{ results: [{ title, url, snippet }] }`\n * back. It authenticates with the SAME `Authorization: Bearer <key>` header and\n * `x-command-code-version` the model adapter uses, so this provider reuses the\n * plugin's existing credential chain (`COMMANDCODE_API_KEY` → credentials seam →\n * `~/.commandcode/auth.json`) — no separate DeepSeek key, no extra endpoint.\n *\n * This mirrors the host-side `@deepseek-ai/dsh-web-search-deepseek` provider in\n * shape: a cordis-free class registered into the web seam, resolving its key per\n * search, mapping each server-side result to the harness's normalized\n * `WebSearchSource`. The web seam owns `maxResults` truncation.\n *\n * @module dsh-commandcode-provider/web-search\n */\n\nimport { WebError, type WebSearchProvider, type WebSearchRequest, type WebSearchResult, type WebSearchSource } from '@deepseek-ai/dsh-web'\nimport type { WebRuntime } from '@deepseek-ai/dsh-web'\nimport { attributionHeaders, type HarnessError } from '@deepseek-ai/dsh-llm'\nimport { COMMAND_CODE_CLI_VERSION } from './adapter.ts'\n\n/** Stable id this provider registers under in `ctx.web`. */\nexport const COMMANDCODE_SEARCH_PROVIDER_ID = 'commandcode'\n\n/**\n * The factory-declared search provider id dsh ships by default (from\n * `dsh-base`'s cordis patch `web.config.searchProvider`). A plugin that wants\n * its own backend to win rewrites `WebRuntime.searchProviderId` to its own id;\n * disabling that plugin restores this value.\n */\nexport const DEFAULT_WEB_SEARCH_PROVIDER_ID = 'deepseek-official'\n\n/**\n * A structurally-typed view of `WebRuntime`'s private selection field.\n *\n * `searchProviderId` is declared `private readonly` on the class, but the\n * compiled runtime property is a plain writable field read per search call\n * (`web.search()` reads `this.searchProviderId` on every invocation). dsh\n * offers no public API to change the selected search provider at runtime, so\n * this seam mutates the instance field directly. That is a deliberate, bounded\n * dependency on the runtime shape: if dsh ever makes the field `#private` or\n * caches it in a closure, this write silently stops applying and the plugin\n * falls back to its provider remaining registered-but-unselected (the boot-time\n * `searchProvider: commandcode` cordis patch is the durable alternative).\n */\ninterface WebRuntimeSearchField {\n /** The selected search provider id; read per call by `search()`. */\n searchProviderId: string | undefined\n}\n\n/**\n * Point the web seam's search selection at this plugin's provider (`commandcode`).\n * Sets the runtime field; the next search call honours it because `search()`\n * re-reads `searchProviderId` each time. Returns the prior id (or undefined).\n */\nexport function selectCommandCodeSearchProvider(web: WebRuntime, enable: boolean): string | undefined {\n const field = web as unknown as WebRuntimeSearchField\n const prior = field.searchProviderId\n field.searchProviderId = enable ? COMMANDCODE_SEARCH_PROVIDER_ID : DEFAULT_WEB_SEARCH_PROVIDER_ID\n return prior\n}\n\n/** Command Code's lower/upper bound on `numResults` (from the CLI's `web_search` schema). */\nconst MIN_NUM_RESULTS = 1\nconst MAX_NUM_RESULTS = 10\n/** CLI default when the caller sets no result cap. */\nconst DEFAULT_NUM_RESULTS = 5\n\n/** The endpoint the search POST goes to; `{apiBase}` is prepended. */\nconst SEARCH_ROUTE = '/alpha/web-search'\n\n/** Per-request facts the provider needs, all injected so the class stays cordis-free and testable. */\nexport interface CommandCodeSearchProviderDeps {\n /** Resolve one usable Command Code key (credential seam → env → auth file), or undefined when none. */\n resolveKey(): Promise<string | undefined>\n /** The API base host (defaults to `https://api.commandcode.ai`). */\n apiBase(): string\n /** Injectable fetch for tests; defaults to the global fetch. */\n fetchImpl?: typeof fetch\n}\n\n/**\n * Clamp a DSH `maxResults` bound into Command Code's 1–10 range, applying the\n * CLI default of 5 when the caller supplied none.\n */\nfunction clampNumResults(maxResults: number | undefined): number {\n return maxResults === undefined\n ? DEFAULT_NUM_RESULTS\n : Math.max(MIN_NUM_RESULTS, Math.min(MAX_NUM_RESULTS, Math.round(maxResults)))\n}\n\n/** Build a `WebSearchSource` from one raw `{ title, url, snippet }` result, omitting empty optional fields. */\nfunction toSource(result: { url?: string; title?: string; snippet?: string }): WebSearchSource | undefined {\n const url = result.url?.trim()\n if (url === undefined || url.length === 0) return undefined\n const title = result.title?.trim()\n const snippet = result.snippet?.trim()\n return {\n url,\n ...title !== undefined && title.length > 0 ? { title } : {},\n ...snippet !== undefined && snippet.length > 0 ? { snippet } : {},\n }\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof DOMException && error.name === 'AbortError'\n}\n\n/** Build the provider's stable cancellation error while retaining the caller's reason. */\nfunction searchAborted(signal: AbortSignal | undefined, fallback: unknown): WebError {\n return new WebError('Command Code web search aborted', 'WEB_ABORTED', {\n cause: signal?.aborted === true ? signal.reason : fallback,\n })\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted === true) throw searchAborted(signal, undefined)\n}\n\n/**\n * A `ctx.web` search provider backed by the Command Code Provider API. Reuses\n * the plugin's credential chain and `apiBase`, so search \"just works\" with the\n * existing key — the model-facing `web_search` tool needs no separate\n * configuration. Selection between multiple search providers is the web seam's\n * job (pin `searchProvider: commandcode` if ambiguous).\n */\nexport class CommandCodeSearchProvider implements WebSearchProvider {\n readonly id = COMMANDCODE_SEARCH_PROVIDER_ID\n\n constructor(private readonly deps: CommandCodeSearchProviderDeps) {}\n\n /** Cheap local check; must not make network calls. Presence of a key path + a parseable base is enough. */\n available(): boolean {\n const base = this.deps.apiBase()\n return base.length > 0 && URL.canParse(base)\n }\n\n async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult> {\n throwIfAborted(signal)\n const apiBase = this.deps.apiBase()\n if (!URL.canParse(apiBase)) {\n throw new WebError(\n `Command Code web search is misconfigured: apiBase ${JSON.stringify(apiBase)} is not a valid URL`,\n 'WEB_PROVIDER_ERROR',\n )\n }\n const key = await this.resolveKey(signal)\n throwIfAborted(signal)\n const endpoint = `${apiBase.replace(/\\/$/, '')}${SEARCH_ROUTE}`\n\n const body = {\n query: request.query,\n numResults: clampNumResults(request.maxResults),\n }\n\n let response: Response\n try {\n response = await (this.deps.fetchImpl ?? fetch)(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${key}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n },\n body: JSON.stringify(body),\n ...signal !== undefined ? { signal } : {},\n })\n } catch (error: unknown) {\n if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error)\n throw new WebError(\n `Command Code web search request failed: ${error instanceof Error ? error.message : String(error)}`,\n 'WEB_PROVIDER_ERROR',\n { cause: error },\n )\n }\n\n if (!response.ok) {\n let message = `Command Code web search failed (HTTP ${response.status})`\n try {\n const parsed: unknown = await response.json()\n const detail = typeof parsed === 'object' && parsed !== null\n ? (parsed as { error?: unknown })?.error\n : undefined\n if (typeof detail === 'string' && detail.length > 0) message += `: ${detail}`\n else if (typeof detail === 'object' && detail !== null) {\n const code = (detail as { code?: unknown })?.code\n const inner = (detail as { message?: unknown })?.message\n if (typeof code === 'string' || typeof inner === 'string') {\n message += `: ${typeof code === 'string' ? code : ''}${typeof code === 'string' && typeof inner === 'string' ? ' — ' : ''}${typeof inner === 'string' ? inner : ''}`\n }\n }\n } catch (error) {\n if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error)\n }\n throw new WebError(message, 'WEB_PROVIDER_ERROR')\n }\n\n let payload: unknown\n try {\n payload = await response.json()\n } catch (error) {\n if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error)\n throw new WebError('Command Code web search returned an unparseable response body', 'WEB_PROVIDER_ERROR')\n }\n\n const results = (payload as { results?: unknown })?.results\n if (!Array.isArray(results)) {\n throw new WebError(\n 'Command Code web search returned no results array (the server may have rejected the query)',\n 'WEB_PROVIDER_ERROR',\n )\n }\n\n const sources: WebSearchSource[] = []\n const seen = new Set<string>()\n for (const item of results) {\n if (typeof item !== 'object' || item === null) continue\n const source = toSource(item as { url?: string; title?: string; snippet?: string })\n if (source === undefined || seen.has(source.url)) continue\n seen.add(source.url)\n sources.push(source)\n }\n\n return { sources, truncated: false }\n }\n\n private async resolveKey(signal: AbortSignal | undefined): Promise<string> {\n let key: string | undefined\n try {\n key = await this.deps.resolveKey()\n } catch (error) {\n if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error)\n // Preserve the plugin's structured credential/usage taxonomy so the web\n // tool surfaces the real cause (e.g. every account exhausted, key\n // invalid) instead of a generic provider failure. The actionable\n // \"no key configured\" case maps to WEB_PROVIDER_CREDENTIAL_MISSING;\n // real rejection causes (INVALID_CREDENTIAL / RATE_LIMIT) keep their\n // message but ride the provider-error code the tool understands.\n if (error instanceof Error && typeof (error as HarnessError).code === 'string') {\n const code = (error as HarnessError).code\n if (code === 'MISSING_CREDENTIAL') throw new WebError(error.message, 'WEB_PROVIDER_CREDENTIAL_MISSING', { cause: error })\n if (code === 'INVALID_CREDENTIAL' || code === 'RATE_LIMIT') {\n throw new WebError(error.message, 'WEB_PROVIDER_ERROR', { cause: error })\n }\n }\n throw new WebError(\n `Command Code web search credential resolution failed: ${error instanceof Error ? error.message : String(error)}`,\n 'WEB_PROVIDER_ERROR',\n { cause: error },\n )\n }\n if (key === undefined || key.length === 0) {\n throw new WebError(\n 'Command Code web search has no API key; store COMMANDCODE_API_KEY through the credentials service (the web Models page writes it), export it in the launching environment, set config.apiKey, or run `command-code login` to write ~/.commandcode/auth.json',\n 'WEB_PROVIDER_CREDENTIAL_MISSING',\n )\n }\n return key\n }\n}\n","/**\n * dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command\n * Code (unofficial; ported from pi-commandcode-provider@0.5.1).\n *\n * Registers the `commandcode` provider route on `ctx.llm` and declares it in\n * the configurable-provider directory, so the web Models page shows a\n * \"Command Code\" card with an API-key field and the model picker lists the\n * live Command Code model catalog. Connection facts resolve per request over\n * the optional `llm-commandcode` user-settings section and the credential\n * seam, so a changed key, endpoint, or cache path reaches the next request\n * without a restart.\n *\n * ```yaml\n * - id: llm-commandcode\n * name: \"@mars-sea/dsh-commandcode-provider\"\n * config:\n * apiKeyEnv: COMMANDCODE_API_KEY\n * ```\n *\n * The `name` is the full package specifier as installed in the profile's\n * node_modules: the loader imports it as a module, and pnpm links packages by\n * their true (scoped) name — a bare `dsh-commandcode-provider` fails to\n * resolve (ERR_MODULE_NOT_FOUND) and crashes the app on boot. The value must\n * be quoted in YAML: an unquoted scalar starting with `@` fails to parse.\n *\n * @module dsh-commandcode-provider\n */\n\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { WebRuntime } from '@deepseek-ai/dsh-web'\nimport z from '@deepseek-ai/schemastery'\nimport { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'\nimport { assertUsableApiKey, LlmError } from '@deepseek-ai/dsh-llm'\nimport { credentialRef, type CredentialRef } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\nimport type {} from '@deepseek-ai/dsh-settings'\nimport { CommandCodeAdapter, DEFAULT_API_BASE, resolveAuthFileApiKey } from './adapter.ts'\nimport { DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS } from './adapter.ts'\nimport type { CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\nimport { CommandCodeAccountPool, accountUsable, selectActiveAccount } from './accounts.ts'\nimport type { CommandCodeAccountConfig, CommandCodeAccountSlot, CommandCodeModelAccountRule } from './accounts.ts'\nimport { applyCommands } from './commands.ts'\nimport { applyUsageRemote } from './usage-remote.ts'\nimport type { CommandCodeAccountsReport, CommandCodeCatalog } from './usage-wire.ts'\nimport { CommandCodeLoginFlow } from './login.ts'\nimport type { CommandCodeLoginCredentials } from './login.ts'\nimport { pickCommandLocale, type LocaleId } from './command-locales.ts'\nimport { CommandCodeSearchProvider, selectCommandCodeSearchProvider } from './web-search.ts'\n\nexport {\n COMMAND_CODE_CLI_VERSION,\n DEFAULT_API_BASE,\n DEFAULT_GENERATE_MAX_TOKENS,\n DEFAULT_MAX_OUTPUT_TOKENS,\n DEFAULT_REQUEST_TIMEOUT_MS,\n DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n CommandCodeAdapter,\n KNOWN_EFFORTS,\n KNOWN_IMAGE_MODELS,\n KNOWN_THINKING_MODELS,\n KNOWN_PLANS,\n KNOWN_SUBSCRIPTION_PLANS,\n KNOWN_DEALS,\n KNOWN_PEAK_PRICING,\n PLAN_LABELS,\n PLAN_ORDER,\n BILLING_ACCESS_TTL_MS,\n capabilityDescription,\n compareByPlan,\n dealLabel,\n formatContext,\n modelVisibleInPlan,\n peakPricingLabel,\n peakPricingState,\n planLabel,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n subscriptionPlanInfo,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeBillingAccess, CommandCodeConnectionOptions, CommandCodeUsageReport, ResolveAttachments } from './adapter.ts'\nexport { applyCommands, commandDefinition } from './commands.ts'\nexport type { CommandCodeCommandDeps } from './commands.ts'\nexport { applyUsageRemote, CommandCodeUsageService } from './usage-remote.ts'\nexport type { CommandCodeUsageDeps, LoginFlowFacade } from './usage-remote.ts'\nexport { USAGE_REPORT_ENDPOINT, usageReportSchema } from './usage-wire.ts'\nexport type { CommandCodeAccountUsage, CommandCodeAccountsReport } from './usage-wire.ts'\nexport {\n LOGIN_BEGIN_ENDPOINT,\n LOGIN_STATUS_ENDPOINT,\n LOGIN_CANCEL_ENDPOINT,\n parseLoginStatus,\n loginStatusSchema,\n} from './login-wire.ts'\nexport type {\n CommandCodeLoginStatus,\n CommandCodeLoginFailureReason,\n} from './login-wire.ts'\nexport {\n LOGIN_TIMEOUT_MS,\n LOGIN_START_PORT,\n LOGIN_MAX_PORT_ATTEMPTS,\n LOGIN_BODY_LIMIT_BYTES,\n LOGIN_ALLOWED_ORIGINS,\n buildCommandAuthUrl,\n studioBaseForApiBase,\n validateCommandApiKey,\n CommandCodeLoginFlow,\n} from './login.ts'\nexport type {\n CommandCodeLoginCredentials,\n CommandCodeLoginFlowDeps,\n ApiKeyValidation,\n} from './login.ts'\nexport { CommandCodeAccountPool, accountUsable, selectActiveAccount, matchModelRule, selectAccountForModel } from './accounts.ts'\nexport type { CommandCodeAccountConfig, CommandCodeAccountSlot, CommandCodeAccountState, CommandCodeModelAccountRule } from './accounts.ts'\nexport { CommandCodeSearchProvider, COMMANDCODE_SEARCH_PROVIDER_ID, DEFAULT_WEB_SEARCH_PROVIDER_ID, selectCommandCodeSearchProvider } from './web-search.ts'\nexport type { CommandCodeSearchProviderDeps } from './web-search.ts'\n\nexport const name = 'llm-commandcode'\nexport const inject = ['llm']\n\nconst NS = 'llm-commandcode'\nconst DEFAULT_API_KEY_ENV = 'COMMANDCODE_API_KEY'\n\n/** The single provider route this plugin owns. */\nexport const PROVIDER = 'commandcode'\n/** Default models cache path (mirrors the pi plugin's on-disk cache). */\nexport const DEFAULT_MODELS_CACHE_PATH = join(homedir(), '.commandcode', 'models-cache.json')\n\n/**\n * Plugin config, validated by the same-named schemastery schema and doubling\n * as the `llm-commandcode` settings-section shape. Every field is optional:\n * a missing API key resolves through {@link Config.apiKeyEnv} at each request\n * (the web Models page writes it), with the official Command Code CLI auth\n * file (`~/.commandcode/auth.json`) as the last fallback.\n */\nexport interface Config {\n /** Credential reference (environment-variable name) resolved per request; defaults to `COMMANDCODE_API_KEY`. */\n apiKeyEnv?: string\n /** Literal API key override (composition config only); takes precedence over `apiKeyEnv`. */\n apiKey?: string\n /** API base; defaults to the public Command Code Provider API. */\n apiBase?: string\n /** Working directory reported to the API; defaults to the process cwd. */\n workingDir?: string\n /** Model catalog cache path; defaults to `~/.commandcode/models-cache.json`. */\n modelsCachePath?: string\n /** Milliseconds to wait for the generate response's first byte; defaults to 60s. */\n requestTimeoutMs?: number\n /** Milliseconds a stream may stall before being treated as a dead connection; defaults to 300s. */\n streamIdleTimeoutMs?: number\n /**\n * Whether the model picker hides models above the account's subscription\n * tier; defaults to true. The filter fails open (unknown plan, billing\n * endpoint failure, or a positive on-demand credit balance all keep the\n * full catalog visible). Set false to always list every model.\n */\n filterModelsByPlan?: boolean\n /**\n * Extra accounts for multi-account rotation. The top-level\n * `apiKey`/`apiKeyEnv` (plus the CLI auth file) always form the first\n * (`default`) account; each entry here adds one more. When a request is\n * rejected pre-stream with 429 (usage window exhausted) or 401, the next\n * account's key retried transparently; when every account is exhausted the\n * request fails with a `RATE_LIMIT` error naming the earliest window\n * reset. Entries without `apiKey` or `apiKeyEnv` are ignored.\n */\n accounts?: CommandCodeAccountConfig[]\n /**\n * Manually selected active account: a slot id — `default`, or an extra\n * account's credential reference (e.g. `COMMANDCODE_API_KEY_2`). The\n * selected account serves whenever it is usable; an unknown id or an\n * exhausted selected account falls back to the first usable slot (automatic\n * rotation still applies). Unset means \"first usable account\".\n */\n activeAccount?: string\n /**\n * Model → account routing rules. Each rule lists catalog model ids to an\n * account slot id (`default`, or an extra account's credential reference).\n * When a request's model is in a rule's list and the routed account is\n * usable, that account serves — before the manual {@link activeAccount} and\n * the passive rotation order. A routed account that is exhausted or invalid\n * falls back to the normal selection, so the router is a hint, never a hard\n * gate. The first matching rule wins.\n */\n modelAccountRules?: CommandCodeModelAccountRule[]\n /**\n * Whether to use Command Code as the backend for dsh's model-facing\n * `web_search` tool. When enabled, the plugin registers a `commandcode`\n * search provider on `ctx.web` AND rewrites the web seam's selected\n * `searchProviderId` to `commandcode` (so it wins over the shipped\n * `deepseek-official`), using the SAME Command Code API key/base as chat.\n * The rewrite rides dsh's internal `searchProviderId`, which is read per\n * search call, so a setting change lands on the next search without a\n * restart. Defaults to true.\n */\n webSearch?: boolean\n /**\n * Language override for the `/commandcode` Host-side command's user-facing\n * copy. Host commands cannot read the client's `ctx.locale`, so this is\n * the explicit knob: `'zh'` or `'en'`. Unset means the command reads\n * `LC_ALL`/`LANG` from the launching shell, falling back to `'zh'`. The\n * web settings page is unaffected — it follows the browser's language\n * preference on its own. Two surfaces, two independent locales. The\n * declared type is `string` (the schemastery `pattern` cannot narrow\n * literal types); an unknown value is treated as \"unset\" by\n * `pickCommandLocale`.\n */\n lang?: string\n}\n\nexport const Config: z<Config> = z.object({\n apiKeyEnv: z.string().role('credential-ref').default(DEFAULT_API_KEY_ENV),\n apiKey: z.string(),\n apiBase: z.string(),\n workingDir: z.string(),\n modelsCachePath: z.string(),\n requestTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n streamIdleTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n filterModelsByPlan: z.boolean(),\n webSearch: z.boolean().default(true),\n accounts: z.array(z.object({\n label: z.string(),\n apiKeyEnv: z.string().role('credential-ref'),\n apiKey: z.string(),\n })),\n activeAccount: z.string(),\n modelAccountRules: z.array(z.object({\n models: z.array(z.string()),\n account: z.string(),\n })),\n lang: z.string().pattern(/^(zh|en)$/).default('zh' as const),\n})\n\n/** One resolution's complete request facts: connection plus credential reference. */\nexport interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {\n apiKeyEnv: CredentialRef\n}\n\n/**\n * The one explicit resolve step from raw config to validated connection\n * facts. Programmatic construction may bypass Schemastery normalization, so\n * every default is re-judged here — for the composition entry at load and for\n * each settings snapshot at its first use.\n */\nexport function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions {\n return {\n apiKeyEnv: credentialRef(config.apiKeyEnv ?? DEFAULT_API_KEY_ENV),\n apiBase: config.apiBase ?? DEFAULT_API_BASE,\n workingDir: config.workingDir ?? process.cwd(),\n modelsCachePath: config.modelsCachePath ?? DEFAULT_MODELS_CACHE_PATH,\n requestTimeoutMs: config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n streamIdleTimeoutMs: config.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n filterModelsByPlan: config.filterModelsByPlan ?? true,\n }\n}\n\nexport function apply(ctx: Context, config: Config): void {\n let current: () => Config = () => config\n let lastRaw: Config | undefined\n let lastGood: ResolvedCommandCodeOptions | undefined\n const options = (): ResolvedCommandCodeOptions => {\n const raw = current()\n if (raw === lastRaw && lastGood !== undefined) return lastGood\n const next = resolveAdapterOptions(raw)\n lastRaw = raw\n lastGood = next\n return next\n }\n options()\n\n // The account slots, rebuilt from the live config on every resolution so\n // a settings-page accounts change reaches the very next request. The\n // top-level apiKey/apiKeyEnv (+ the CLI auth file) form the default\n // account; each config.accounts entry adds one more.\n const slots = (): CommandCodeAccountSlot[] => {\n const raw = current()\n const list: CommandCodeAccountSlot[] = [{\n id: 'default',\n label: 'Default',\n ref: credentialRef(raw.apiKeyEnv ?? DEFAULT_API_KEY_ENV),\n literal: raw.apiKey,\n allowAuthFile: true,\n }]\n for (const [index, account] of (raw.accounts ?? []).entries()) {\n const refName = typeof account.apiKeyEnv === 'string' && account.apiKeyEnv.trim() !== ''\n ? account.apiKeyEnv.trim()\n : undefined\n const literal = typeof account.apiKey === 'string' && account.apiKey !== '' ? account.apiKey : undefined\n if (refName === undefined && literal === undefined) continue\n list.push({\n // Slot ids must survive account-list edits: an extra's id is its\n // credential reference (stable across reorders/removals), falling\n // back to the positional id only for literal-only composition\n // entries, which no settings document can name anyway.\n id: refName ?? `account-${index + 2}`,\n label: typeof account.label === 'string' && account.label.trim() !== ''\n ? account.label.trim()\n : `Account ${index + 2}`,\n ref: refName === undefined ? undefined : credentialRef(refName),\n literal,\n allowAuthFile: false,\n })\n }\n return list\n }\n\n // The manually selected account (settings page / config), re-read per\n // resolution like every other settings-backed fact.\n const preferredId = (): string | undefined => {\n const raw = current().activeAccount\n return typeof raw === 'string' && raw.trim() !== '' ? raw.trim() : undefined\n }\n\n const resolveRef = async (ref: ReturnType<typeof credentialRef>): Promise<string | undefined> => {\n const credentials = ctx.get('credentials')\n if (credentials !== undefined) {\n const hit = await credentials.resolve(ref)\n return hit?.value\n }\n const ambient = launchEnvironmentOf(ctx).get(ref)\n return ambient !== undefined && ambient.value.length > 0 ? ambient.value : undefined\n }\n\n // The multi-account pool: passive rotation only — a key is marked when a\n // request using it is actually rejected (429/401), and the marks are\n // re-checked against the live window limits only once every account is\n // marked, so the steady state costs zero extra API calls.\n // Explicit annotations break the pool↔adapter inference cycle (the pool's\n // probe calls the adapter; the adapter's rotation hook calls the pool).\n const pool: CommandCodeAccountPool = new CommandCodeAccountPool({\n slots,\n resolveRef,\n authFileKey: resolveAuthFileApiKey,\n // The adapter reference is assigned right below; the probe runs only at\n // request time, never during plugin startup.\n probeWindow: (apiKey: string) => adapter.probeFiveHourWindow(apiKey),\n preferredId,\n // Model → account routing rules, re-read per resolution like every\n // settings-backed fact.\n modelAccountRules: (): readonly CommandCodeModelAccountRule[] => current().modelAccountRules ?? [],\n })\n\n const resolveApiKey = async (connection: ResolvedCommandCodeOptions, model?: string): Promise<string> => {\n const resolved = await pool.resolveKey(model === undefined ? {} : { model })\n if (resolved !== undefined) {\n return assertUsableApiKey(resolved.key, 'llm-commandcode', resolved.slot.ref ?? `${resolved.slot.label} (config.apiKey)`)\n }\n const ref = connection.apiKeyEnv\n throw new LlmError(\n `llm-commandcode: no API key for provider route \"${PROVIDER}\"; store ${ref} through the`\n + ' credentials service (the web Models page writes it), export it in the launching'\n + ' environment, set config.apiKey, or run `command-code login` to write'\n + ' ~/.commandcode/auth.json',\n 'MISSING_CREDENTIAL',\n )\n }\n\n const adapter: CommandCodeAdapter<ResolvedCommandCodeOptions> = new CommandCodeAdapter({\n options,\n resolveApiKey,\n // Pre-stream 429/401: mark the rejected key and hand the adapter the next\n // account's key. When every account is exhausted the pool throws the\n // RATE_LIMIT/INVALID_CREDENTIAL error that names the earliest reset —\n // that error, not the raw 429, is what the caller sees.\n rotateApiKey: async (rejectedKey: string, rejection: 'rate-limit' | 'invalid-credential', _connection: ResolvedCommandCodeOptions, model?: string): Promise<string | undefined> => {\n pool.markRejected(rejectedKey, rejection)\n // Exclude the just-rejected key from probe-revival: a probe clearing its\n // window must not re-offer the same key within this request (the\n // adapter refuses already-tried keys); the next request picks it up.\n // The model rides along so model-routing rules pick the next account\n // for the same model.\n const resolved = await pool.resolveKey(\n model === undefined ? { exclude: rejectedKey } : { exclude: rejectedKey, model },\n )\n // Normalize like the initial resolution does: the pool keys its state\n // by the resolved key, so the adapter must send (and report back) the\n // same normalized form or the marks would miss.\n return resolved === undefined\n ? undefined\n : assertUsableApiKey(resolved.key, 'llm-commandcode', resolved.slot.ref ?? `${resolved.slot.label} (config.apiKey)`)\n },\n // The durable attachment service carries image bytes referenced by\n // ImageBlock; resolved lazily only when a request actually has images.\n resolveAttachments: () => {\n const attachments = ctx.get('attachments')\n return attachments === undefined ? undefined : attachments\n },\n })\n // The Models page card: a configurable provider with a settings address.\n // settingsPath [] means the whole `llm-commandcode` section configures it.\n ctx.llm.registerConfigurableProviders([\n { provider: PROVIDER, displayName: 'Command Code', settingsNs: NS, settingsPath: [] },\n ])\n // The live route: this is what makes models requestable under `commandcode`.\n ctx.llm.registerAdapter([PROVIDER], adapter)\n\n // Per-account usage for the /commandcode dashboard and the settings\n // page's account card: every pool account (configured or not) gets one\n // entry, each fetched with its own key so plan/credit facts never mix.\n const usageReports = async (): Promise<CommandCodeAccountsReport> => {\n // describeAccounts (not deduped) so two slots sharing one credential are\n // both reported as configured; the active badge follows the deduped\n // serving selection.\n const described = await pool.describeAccounts()\n const byId = new Map(described.map((account) => [account.slot.id, account]))\n const active = selectActiveAccount(await pool.resolvedAccounts(), preferredId())\n const entries = await Promise.all(slots().map(async (slot) => {\n const account = byId.get(slot.id)\n let report: CommandCodeUsageReport\n if (account === undefined) {\n report = { failures: [] }\n } else {\n try {\n report = await adapter.getUsage(account.key)\n } catch (error: unknown) {\n report = { failures: [error instanceof Error ? error.message : String(error)] }\n }\n }\n const state = account?.state\n // The mark mirrors servability: a usable account (never marked, or a\n // cooldown whose reset passed) shows no mark; a cooldown without a\n // known reset still shows \"rate-limit\" (it is not serving).\n const usable = accountUsable(state)\n return {\n id: slot.id,\n label: slot.label,\n configured: account !== undefined,\n active: account !== undefined && active?.slot.id === slot.id,\n mark: usable ? '' : state?.kind === 'disabled' ? 'invalid-credential' : 'rate-limit',\n cooldownUntil: !usable && state?.kind === 'cooldown' ? state.until : 0,\n report,\n }\n }))\n return { accounts: entries }\n }\n\n // The /commandcode usage command rides the optional `commands` service: a\n // child fiber injects it, so it registers whenever the profile mounts\n // dsh-commands and the fiber simply never activates when it does not.\n // The command runs Host-side and has no access to the client's locale\n // service, so its language is resolved here from `Config.lang` (explicit\n // override) and the launching shell's `LC_ALL`/`LANG` (inferred default);\n // resolved per invocation so a settings change reaches the next command\n // run without a restart.\n const commandLocale = (): LocaleId => pickCommandLocale(current().lang)\n ctx.inject(['commands'], (commandCtx) => {\n applyCommands(commandCtx, { adapter, reports: usageReports, getLocale: commandLocale })\n })\n\n // The settings page's account card: getUsage exposed to the browser through\n // the Typert Gateway (`commandcode/report`). Rides the optional `typert`\n // registry service, so profiles without the web stack never activate it.\n // The same service also exposes the browser-login flow: the Host binds a\n // loopback callback server (the official `command-code login` dance) and\n // stores the delivered key through the credentials seam under the same\n // reference the default slot resolves — no restart, no settings document.\n const loginFlow = new CommandCodeLoginFlow({\n apiBase: () => options().apiBase,\n storeKey: async ({ apiKey }: CommandCodeLoginCredentials): Promise<void> => {\n const ref = credentialRef(current().apiKeyEnv ?? DEFAULT_API_KEY_ENV)\n const credentials = ctx.get('credentials')\n if (credentials === undefined) {\n throw new Error('the credentials service is unavailable in this profile; paste the key manually')\n }\n await credentials.set(ref, apiKey)\n },\n })\n ctx.effect(() => () => loginFlow.dispose(), 'dsh-commandcode-provider: login flow')\n // The catalog for the settings page's routing-rule editor: served Host-side\n // from the adapter's cached/fetched catalog (sorted for picking), so the\n // browser never calls the Command Code API directly.\n const catalogForRules = async (): Promise<CommandCodeCatalog> => {\n const models = await adapter.listModels(PROVIDER)\n return {\n models: models.map((model) => ({ id: model.id, name: model.name.replace(/\\s*\\(CC\\)$/, '') })),\n }\n }\n applyUsageRemote(ctx, { adapter, reports: usageReports, login: loginFlow, listModels: catalogForRules })\n\n // Web search over the Command Code Provider API, exposed through the web\n // capability seam (`ctx.web`). Rides the optional `web` service: a child\n // fiber injects it, so the provider registers whenever the profile mounts\n // the web stack and the fiber never activates when it does not (profiles\n // without web remain an LLM-provider-only plugin). It reuses the SAME\n // credential chain as the model adapter (pool.resolveKey → env → auth file)\n // and the same apiBase, so DSH's model-facing web_search tool needs no\n // separate key or endpoint config — a Command Code key works as-is.\n //\n // Whether the `commandcode` provider WINS over the shipped `deepseek-official`\n // is controlled by `Config.webSearch` (default on). The web seam has no\n // public runtime selector, so the plugin writes its private `searchProviderId`\n // field (read per call) via `selectCommandCodeSearchProvider`. A settings\n // change lands on the next search without a restart. See src/web-search.ts\n // for why this runtime write is safe and what it depends on.\n let webRuntime: WebRuntime | undefined\n ctx.inject(['web'], (webCtx) => {\n webRuntime = webCtx.web\n webCtx.web.registerSearchProvider(new CommandCodeSearchProvider({\n resolveKey: async () => {\n const resolved = await pool.resolveKey()\n return resolved === undefined ? undefined : resolved.key\n },\n apiBase: () => options().apiBase,\n }))\n // Apply the selection at boot too, so a profile WITHOUT the manual\n // `searchProvider: commandcode` cordis patch still routes web search to\n // Command Code once this plugin loads (default `webSearch` on).\n selectCommandCodeSearchProvider(webCtx.web, current().webSearch ?? true)\n })\n\n // Settings became an optional service in dsh 0.1.2. Register the section\n // through its provider when present; profiles without settings continue to\n // use the composition entry captured by `current` above.\n ctx.inject(['settings'], (settingsCtx) => {\n settingsCtx.settings.installSection(ctx, NS, Config, config, {\n setSource: (source) => {\n current = source\n },\n // Re-apply the web search selection on every settings change so the\n // `webSearch` toggle reaches the web seam's next search without a\n // restart. The adapter's own facts are resolved per request, so nothing\n // else needs registration-level action here.\n onChange: () => {\n if (webRuntime !== undefined) {\n selectCommandCodeSearchProvider(webRuntime, current().webSearch ?? true)\n }\n },\n })\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAa,qBAAqB;;AAoGlC,SAAS,WAAW,IAAoB;CACtC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,eAAe;AACrC;;;;;;;AAQA,SAAgB,cAAc,OAAqD;CACjF,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,MAAM,SAAS,YAAY,OAAO,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,MAAM;CAC7E,OAAO;AACT;;;;;;;AAQA,SAAgB,oBACd,UACA,aAC6B;CAC7B,MAAM,SAAS,SAAS,QAAQ,YAAY,cAAc,QAAQ,KAAK,CAAC;CACxE,IAAI,gBAAgB,KAAA,GAAW;EAC7B,MAAM,YAAY,OAAO,MAAM,YAAY,QAAQ,KAAK,OAAO,WAAW;EAC1E,IAAI,cAAc,KAAA,GAAW,OAAO;CACtC;CACA,OAAO,OAAO;AAChB;;;;;AAMA,SAAgB,eACd,OACA,OACyC;CACzC,IAAI,UAAU,MAAM,UAAU,KAAA,KAAa,MAAM,WAAW,GAAG,OAAO,KAAA;CACtE,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,OAAO,SAAS,KAAK,GAAG,OAAO;AAG5C;;;;;;;AAQA,SAAgB,sBACd,UACA,OACA,OAC6B;CAC7B,MAAM,OAAO,eAAe,OAAO,KAAK;CACxC,IAAI,SAAS,KAAA,GAAW,OAAO,KAAA;CAC/B,OAAO,SAAS,MAAM,YAAY,QAAQ,KAAK,OAAO,KAAK,WAAW,cAAc,QAAQ,KAAK,CAAC;AACpG;;;;;;AAOA,IAAa,yBAAb,MAAoC;CAGL;;CAD7B,yBAA0B,IAAI,IAAqC;CACnE,YAAY,MAAmD;EAAlC,KAAA,OAAA;CAAmC;;;;;;CAOhE,MAAM,mBAA+C;EACnD,MAAM,MAAyB,CAAC;EAChC,MAAM,uBAAO,IAAI,IAAY;EAC7B,KAAK,MAAM,QAAQ,KAAK,KAAK,MAAM,GAAG;GACpC,MAAM,MAAM,MAAM,KAAK,eAAe,IAAI;GAC1C,IAAI,QAAQ,KAAA,KAAa,KAAK,IAAI,GAAG,GAAG;GACxC,KAAK,IAAI,GAAG;GACZ,IAAI,KAAK;IAAE;IAAM;IAAK,OAAO,KAAK,OAAO,IAAI,GAAG;GAAE,CAAC;EACrD;EACA,OAAO;CACT;;;;;;;CAQA,MAAM,mBAA+C;EACnD,MAAM,MAAyB,CAAC;EAChC,KAAK,MAAM,QAAQ,KAAK,KAAK,MAAM,GAAG;GACpC,MAAM,MAAM,MAAM,KAAK,eAAe,IAAI;GAC1C,IAAI,QAAQ,KAAA,GAAW;GACvB,IAAI,KAAK;IAAE;IAAM;IAAK,OAAO,KAAK,OAAO,IAAI,GAAG;GAAE,CAAC;EACrD;EACA,OAAO;CACT;;;;;;;;;;;;;;;;;;CAmBA,MAAM,WAAW,SAAoH;EACnI,MAAM,WAAW,MAAM,KAAK,iBAAiB;EAC7C,IAAI,SAAS,WAAW,GACtB;EAEF,MAAM,SAAS,sBAAsB,UAAU,SAAS,SAAS,IAAI,KAAK,KAAK,oBAAoB,CAAC;EACpG,IAAI,WAAW,KAAA,GAAW,OAAO,KAAK,KAAK,MAAM;EACjD,MAAM,SAAS,oBAAoB,UAAU,KAAK,KAAK,cAAc,CAAC;EACtE,IAAI,WAAW,KAAA,GAAW,OAAO,KAAK,KAAK,MAAM;EAIjD,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,YAAY;GAChD,IAAI,QAAQ,OAAO,SAAS,YAAY;GACxC,IAAI,SAAS,YAAY,KAAA,KAAa,QAAQ,QAAQ,QAAQ,SAAS;GACvE,MAAM,QAAQ,MAAM,KAAK,KAAK,YAAY,QAAQ,GAAG;GACrD,IAAI,UAAU,KAAA,GAAW;GACzB,IAAI,CAAC,MAAM,UACT,KAAK,OAAO,OAAO,QAAQ,GAAG;QAE9B,KAAK,OAAO,IAAI,QAAQ,KAAK;IAC3B,MAAM;IACN,QAAQ,QAAQ,OAAO,UAAU;IACjC,OAAO,MAAM;GACf,CAAC;EAEL,CAAC,CAAC;EAEF,MAAM,UAAU,oBAAoB,MAAM,KAAK,iBAAiB,GAAG,KAAK,KAAK,cAAc,CAAC;EAC5F,IAAI,YAAY,KAAA,GAAW,OAAO,KAAK,KAAK,OAAO;EAEnD,MAAM,SAAS,MAAM,KAAK,iBAAiB;EAE3C,IADiB,OAAO,QAAQ,YAAY,QAAQ,OAAO,SAAS,UACzD,CAAC,CAAC,WAAW,OAAO,QAI7B,MAAM,IAAI,SACR,2DAA2D,OAAO,OAAO,qGAE5D,OAAO,OAAO,4EAE3B,oBACF;EAEF,MAAM,SAAS,OACZ,KAAK,YAAY,QAAQ,KAAK,CAAC,CAC/B,QAAQ,UAA4C,UAAU,KAAA,KAAa,MAAM,SAAS,cAAc,MAAM,QAAQ,CAAC,CAAC,CACxH,KAAK,UAAU,MAAM,KAAK;EAC7B,MAAM,WAAW,OAAO,SAAS,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI;EAQ3D,MAAM,OAAO,WAAW,IAAI,KAAK,IAAI,KAAM,WAAW,KAAK,IAAI,CAAC,IAAI;EACpE,MAAM,IAAI,SACR,wBAAwB,OAAO,OAAO,+DACjC,WAAW,IAAI,mCAAmC,WAAW,QAAQ,MAAM,MAC5E,iFACU,OAAO,OAAO,4BACvB,WAAW,IAAI,aAAa,WAAW,QAAQ,MAAM,MACtD,6BACJ,cACA,OAAO,KAAK,QAAA,MAA6B,EAAE,sBAAsB,KAAK,IAAI,KAAA,CAC5E;CACF;;;;;;;CAQA,aAAa,QAAgB,WAAmC;EAC9D,IAAI,cAAc,sBAChB,KAAK,OAAO,IAAI,QAAQ;GAAE,MAAM;GAAY,QAAQ;GAAyB,OAAO;EAAE,CAAC;OAEvF,KAAK,OAAO,IAAI,QAAQ;GAAE,MAAM;GAAW,QAAQ;GAAsB,OAAO;EAAE,CAAC;CAEvF;;CAGA,MAAc,eAAe,MAA2D;EACtF,IAAI,KAAK,YAAY,KAAA,KAAa,KAAK,YAAY,IAAI,OAAO,KAAK;EACnE,IAAI,KAAK,QAAQ,KAAA,GAAW;GAC1B,MAAM,MAAM,MAAM,KAAK,KAAK,WAAW,KAAK,GAAG;GAC/C,IAAI,QAAQ,KAAA,KAAa,QAAQ,IAAI,OAAO;EAC9C;EACA,IAAI,KAAK,eAAe;GACtB,MAAM,WAAW,KAAK,KAAK,YAAY;GACvC,IAAI,aAAa,KAAA,KAAa,aAAa,IAAI,OAAO;EACxD;CAEF;;CAGA,KAAa,SAAyE;EACpF,OAAO;GAAE,KAAK,QAAQ;GAAK,MAAM,QAAQ;EAAK;CAChD;AACF;;;;;;;;;;;;;;;;;;;;;;;;ACvTA,MAAa,gBAA6D;CAexE,oBAAoB;EAAC;EAAO;EAAU;CAAO;CAC7C,oBAAoB;EAAC;EAAO;EAAU;CAAO;CAC7C,sBAAsB;EAAC;EAAO;EAAU;CAAO;CAC/C,kBAAkB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CAC1D,mBAAmB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CAC3D,mBAAmB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CAC3D,iBAAiB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CACzD,qBAAqB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CAC7D,mBAAmB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CAI3D,mCAAmC;EAAC;EAAO;EAAQ;CAAK;CACxD,8BAA8B,CAAC,QAAQ,KAAK;CAC5C,yCAAyC,CAAC,QAAQ,KAAK;CACvD,4BAA4B,CAAC,QAAQ,KAAK;CAC1C,gCAAgC;EAAC;EAAO;EAAU;CAAM;CACxD,2BAA2B;EAAC;EAAO;EAAU;CAAM;CACnD,gCAAgC;EAAC;EAAO;EAAU;CAAM;CACxD,2BAA2B;EAAC;EAAO;EAAU;CAAM;CACnD,2BAA2B;EAAC;EAAO;EAAU;CAAM;CACnD,iBAAiB;EAAC;EAAO;EAAU;EAAQ;CAAO;CAClD,WAAW;EAAC;EAAO;EAAU;EAAQ;CAAO;CAC5C,gBAAgB;EAAC;EAAO;EAAU;CAAM;CACxC,WAAW;EAAC;EAAO;EAAU;EAAQ;CAAO;CAC5C,gBAAgB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CACxD,eAAe;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CACvD,iBAAiB;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK;CACzD,qBAAqB,CAAC,QAAQ,OAAO;CACrC,uBAAuB;EAAC;EAAO;EAAU;CAAM;CAC/C,gBAAgB;EAAC;EAAO;EAAU;CAAM;CACxC,gBAAgB;EAAC;EAAO;EAAU;EAAQ;CAAO;CACjD,sBAAsB;EAAC;EAAO;EAAQ;CAAK;CAC3C,mBAAmB,CAAC,QAAQ,KAAK;CACjC,mBAAmB;EAAC;EAAO;EAAQ;CAAK;AAC1C;;;;;;;;;;;;;;;;AAiBA,MAAa,qCAA0C,IAAI,IAAI;CAC7D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;;;;;;;;;;;AAsBD,MAAa,wCAA6C,IAAI,IAAI;CAChE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;;;;;;AAiBD,MAAa,cAAgD;CAE3D,0BAA0B;CAC1B,0BAA0B;CAC1B,wBAAwB;CACxB,4BAA4B;CAC5B,qBAAqB;CACrB,sBAAsB;CACtB,oBAAoB;CACpB,qBAAqB;CACrB,oBAAoB;CACpB,sBAAsB;CACtB,oBAAoB;CAGpB,mCAAmC;CACnC,8BAA8B;CAC9B,yCAAyC;CACzC,4BAA4B;CAC5B,gBAAgB;CAChB,mCAAmC;CACnC,mCAAmC;CACnC,6BAA6B;CAC7B,2BAA2B;CAC3B,wBAAwB;CACxB,wBAAwB;CACxB,6BAA6B;CAC7B,uCAAuC;CACvC,sBAAsB;CACtB,qCAAqC;CACrC,8BAA8B;CAC9B,0BAA0B;CAC1B,0BAA0B;CAC1B,eAAe;CACf,oBAAoB;CACpB,uBAAuB;CACvB,4BAA4B;CAC5B,kCAAkC;CAClC,gBAAgB;CAChB,oBAAoB;CACpB,wBAAwB;CACxB,sBAAsB;CACtB,iBAAiB;CACjB,mBAAmB;CACnB,mBAAmB;CACnB,wBAAwB;CACxB,mBAAmB;CAEnB,2BAA2B;CAC3B,eAAe;CACf,uBAAuB;CACvB,gBAAgB;CAEhB,6BAA6B;CAC7B,qBAAqB;CACrB,mBAAmB;CACnB,gCAAgC;CAChC,2BAA2B;CAC3B,gCAAgC;CAChC,2BAA2B;CAC3B,iBAAiB;CACjB,WAAW;CACX,gBAAgB;CAChB,WAAW;CACX,iBAAiB;CACjB,uBAAuB;CAEvB,kBAAkB;CAClB,mBAAmB;CACnB,mBAAmB;CACnB,iBAAiB;CACjB,qBAAqB;AACvB;;AAGA,MAAa,cAAgD;CAC3D,IAAI;CACJ,MAAM;CACN,KAAK;CACL,UAAU;CACV,KAAK;AACP;;;;;AAMA,MAAa,aAA+C;CAC1D,IAAI;CACJ,MAAM;CACN,KAAK;CACL,UAAU;CACV,KAAK;AACP;;;;;;;AAQA,SAAgB,YAAY,SAA0B;CACpD,OAAO,YAAY,QAAQ,EAAE,SAAS;AACxC;;;;;;AAOA,SAAgB,cACd,GACA,GACQ;CACR,MAAM,YAAY,OAAO,YAAY,EAAE,EAAE,CAAC,IAAI,OAAO,YAAY,EAAE,EAAE,CAAC;CACtE,IAAI,cAAc,GAAG,OAAO;CAC5B,MAAM,KAAK,WAAW,YAAY,EAAE,OAAO,OAAO,OAAO;CACzD,MAAM,KAAK,WAAW,YAAY,EAAE,OAAO,OAAO,OAAO;CACzD,IAAI,OAAO,IAAI,OAAO,KAAK;CAC3B,MAAM,WAAW,EAAE,KAAK,cAAc,EAAE,IAAI;CAC5C,IAAI,aAAa,GAAG,OAAO;CAC3B,OAAO,EAAE,GAAG,cAAc,EAAE,EAAE;AAChC;;;;;;;;;;;;;AAcA,MAAa,2BAAmH;CAC9H,iBAAiB;EAAE,MAAM;EAAM,gBAAgB;EAAI,YAAY;CAAE;CACjE,mBAAmB;EAAE,MAAM;EAAQ,gBAAgB;EAAI,YAAY;CAAE;CACrE,kBAAkB;EAAE,MAAM;EAAO,gBAAgB;EAAI,YAAY;CAAE;CACnE,qBAAqB;EAAE,MAAM;EAAO,gBAAgB;EAAI,YAAY;CAAE;CACtE,uBAAuB;EAAE,MAAM;EAAY,gBAAgB;EAAI,YAAY;CAAE;CAC7E,kBAAkB;EAAE,MAAM;EAAO,gBAAgB;EAAK,YAAY;CAAE;CACpE,oBAAoB;EAAE,MAAM;EAAS,gBAAgB;EAAK,YAAY;CAAE;CACxE,aAAa;EAAE,MAAM;EAAa,gBAAgB;EAAI,YAAY;CAAE;AACtE;;AAGA,MAAM,6BAA6B,OAAO,KAAK,wBAAwB,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;;;;;;;;AAS3G,SAAgB,qBAAqB,QAA0F;CAC7H,MAAM,aAAa,OAAO,YAAY,CAAC,CAAC,QAAQ,MAAM,GAAG;CACzD,MAAM,SAAS,2BAA2B,MAAM,cAAc,WAAW,WAAW,SAAS,CAAC;CAC9F,OAAO,WAAW,KAAA,IAAY,KAAA,IAAY,yBAAyB;AACrE;;;;;;;AAwBA,SAAgB,mBAAmB,SAAiB,QAAuD;CACzG,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,IAAI,OAAO,kBAAkB,GAAG,OAAO;CACvC,IAAI,OAAO,eAAe,KAAA,GAAW,OAAO;CAC5C,MAAM,OAAO,YAAY;CACzB,IAAI,SAAS,KAAA,GAAW,OAAO;CAC/B,MAAM,SAAS,WAAW;CAC1B,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,OAAO,UAAU,OAAO;AAC1B;AA2BA,MAAa,cAAmD;CAI9D,wBAAwB,EAAE,OAAO,UAAU;CAC3C,wBAAwB,EAAE,OAAO,UAAU;CAC3C,oBAAoB,EAAE,OAAO,UAAU;CAOvC,8BAA8B;EAAE,OAAO;EAAQ,MAAM;CAAK;AAC5D;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,qCAA0C,IAAI,IAAI;CAC7D;CACA;CACA;CAIA;AACF,CAAC;;AAGD,MAAM,mBAA6D,CACjE,CAAC,GAAG,CAAC,GACL,CAAC,GAAG,EAAE,CACR;;;;;AAMA,SAAgB,iBACd,SACA,MAAc,KAAK,IAAI,GACU;CACjC,IAAI,CAAC,mBAAmB,IAAI,OAAO,GAAG,OAAO,KAAA;CAC7C,MAAM,OAAO,IAAI,KAAK,GAAG,CAAC,CAAC,YAAY;CAEvC,OADe,iBAAiB,MAAM,CAAC,OAAO,SAAS,QAAQ,SAAS,OAAO,GACnE,IAAI,SAAS;AAC3B;;;;;;;;AASA,SAAgB,iBACd,SACA,MAAc,KAAK,IAAI,GACH;CACpB,MAAM,QAAQ,iBAAiB,SAAS,GAAG;CAC3C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,OAAO,UAAU,SAAS,SAAS;AACrC;AAEA,MAAa,2BAA2B;AACxC,MAAa,mBAAmB;AAChC,MAAa,8BAA8B;AAC3C,MAAa,4BAA4B;AACzC,MAAa,oBAAoB;;AAEjC,MAAa,wBAAwB;;;;;AAMrC,MAAM,+CAAoD,IAAI,IAAI;CAAC;CAAU;CAAY;AAAU,CAAC;;AAEpG,MAAa,6BAA6B;;AAE1C,MAAa,iCAAiC;AAC9C,MAAM,sBAAsB;AAM5B,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;;;AAMA,SAAgB,UAAU,SAAqC;CAC7D,MAAM,OAAO,YAAY;CACzB,OAAO,SAAS,KAAA,IAAY,KAAA,IAAY,YAAY;AACtD;;;;;;;;AASA,SAAgB,UAAU,SAAiB,MAAc,KAAK,IAAI,GAAuB;CACvF,MAAM,OAAO,YAAY;CACzB,IAAI,SAAS,KAAA,GAAW,OAAO,KAAA;CAC/B,IAAI,KAAK,cAAc,KAAA,KAAa,OAAO,KAAK,MAAM,KAAK,SAAS,GAAG,OAAO,KAAA;CAC9E,OAAO,KAAK;AACd;;;;;;AAOA,SAAgB,cAAc,eAAuD;CACnF,IAAI,kBAAkB,KAAA,KAAa,CAAC,OAAO,SAAS,aAAa,KAAK,iBAAiB,GACrF;CAEF,IAAI,iBAAiB,KAAW;EAC9B,MAAM,IAAI,gBAAgB;EAG1B,MAAM,UAAU,KAAK,MAAM,IAAI,EAAE,IAAI;EACrC,OAAO,GAAG,OAAO,UAAU,OAAO,IAAI,UAAU,QAAQ,QAAQ,CAAC,EAAE;CACrE;CACA,OAAO,GAAG,KAAK,MAAM,gBAAgB,GAAK,EAAE;AAC9C;;;;;;;;AASA,SAAgB,sBACd,SACA,eACA,MAAc,KAAK,IAAI,GACf;CACR,MAAM,QAAkB,CAAC;CACzB,MAAM,OAAO,UAAU,OAAO;CAC9B,IAAI,SAAS,KAAA,GAAW,MAAM,KAAK,IAAI;CACvC,MAAM,OAAO,UAAU,SAAS,GAAG;CACnC,IAAI,SAAS,KAAA,GAAW,MAAM,KAAK,IAAI;CACvC,MAAM,OAAO,iBAAiB,SAAS,GAAG;CAC1C,IAAI,SAAS,KAAA,GAAW,MAAM,KAAK,IAAI;CACvC,IAAI,mBAAmB,IAAI,OAAO,GAAG,MAAM,KAAK,OAAO;CACvD,MAAM,MAAM,cAAc,aAAa;CACvC,IAAI,QAAQ,KAAA,GAAW,MAAM,KAAK,GAAG;CACrC,OAAO,MAAM,KAAK,KAAK;AACzB;AAEA,SAAS,YAAY,OAAoC;CACvD,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;AAC7C;AAEA,SAAS,YAAY,OAAoC;CACvD,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ,KAAA;AACvE;AAEA,SAAS,aAAa,OAAqC;CACzD,OAAO,OAAO,UAAU,YAAY,QAAQ,KAAA;AAC9C;;AAGA,SAAS,eAAe,OAAwB;CAC9C,MAAM,WAAW,YAAY,KAAK;CAClC,IAAI,aAAa,KAAA,GAAW,OAAO;CACnC,MAAM,WAAW,YAAY,KAAK;CAClC,IAAI,aAAa,KAAA,GAAW,OAAO;CACnC,MAAM,SAAS,KAAK,MAAM,QAAQ;CAClC,OAAO,OAAO,MAAM,MAAM,IAAI,IAAI;AACpC;;;;;;AAOA,MAAM,gCAAgC;CACpC;CACA;CACA;AACF;AAEA,SAAS,wBAAwB,SAA0B;CACzD,MAAM,QAAQ,QAAQ,YAAY;CAClC,OAAO,8BAA8B,MAAM,WAAW,MAAM,SAAS,MAAM,CAAC;AAC9E;AAEA,SAAS,cAAc,OAAyC;CAC9D,IAAI,SAAS,KAAK,GAAG,OAAO;CAC5B,IAAI,OAAO,UAAU,UACnB,IAAI;EACF,MAAM,SAAkB,KAAK,MAAM,KAAK;EACxC,IAAI,SAAS,MAAM,GAAG,OAAO;CAC/B,QAAQ,CAER;CAEF,OAAO,CAAC;AACV;AAEA,SAAgB,oBAAoB,UAA0B;CAY5D,OAXa,SACV,YAAY,CAAC,CACb,QAAQ,YAAY,EAAE,CAAC,CACvB,QAAQ,eAAe,GAAG,CAAC,CAO3B,QAAQ,kBAAkB,EACnB,KAAK;AACjB;AAEA,SAAS,qBAAqB,MAAmC;CAC/D,IAAI,UAAU,KAAK,KAAK;CACxB,IAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,QAAQ,GAAG,OAAO,KAAA;CAChF,IAAI,QAAQ,WAAW,OAAO,GAAG,UAAU,QAAQ,MAAM,CAAC,CAAC,CAAC,KAAK;CACjE,IAAI,CAAC,WAAW,YAAY,UAAU,OAAO,KAAA;CAC7C,IAAI;EACF,OAAO,KAAK,MAAM,OAAO;CAC3B,QAAQ;EACN;CACF;AACF;;AAWA,SAAS,2BAA2B,OAAoC;CACtE,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO,KAAA;CAC7B,MAAM,OAAO,YAAY,MAAM,IAAI;CACnC,IAAI,SAAS,OAAO,OAAO,YAAY,MAAM,GAAG;CAChD,IAAI,SAAS,SAAS,OAAO,YAAY,MAAM,MAAM;CACrD,OAAO,YAAY,MAAM,GAAG,KAAK,YAAY,MAAM,MAAM;AAC3D;;AAGA,SAAgB,wBAA4C;CAC1D,MAAM,WAAW,KAAK,QAAQ,GAAG,gBAAgB,WAAW;CAC5D,IAAI;EACF,IAAI,CAAC,WAAW,QAAQ,GAAG,OAAO,KAAA;EAClC,MAAM,SAAkB,KAAK,MAAM,aAAa,UAAU,OAAO,CAAC;EAClE,IAAI,CAAC,SAAS,MAAM,GAAG,OAAO,KAAA;EAC9B,MAAM,SAAS,YAAY,OAAO,MAAM,KAAK,YAAY,OAAO,WAAW;EAC3E,IAAI,QAAQ,OAAO;EAInB,OAFE,2BAA2B,OAAO,WAAW,KAC7C,2BAA2B,OAAO,eAAe;CAErD,QAAQ,CAER;AAEF;AAaA,SAAS,qBAAqB,OAAoC;CAChE,IAAI,CAAC,SAAS,KAAK,KAAK,MAAM,WAAW,UAAU,CAAC,MAAM,QAAQ,MAAM,IAAI,GAC1E,MAAM,IAAI,SAAS,iDAAiD,yBAAyB;CAE/F,MAAM,SAA6B,CAAC;CACpC,KAAK,MAAM,SAAS,MAAM,MAAM;EAC9B,IAAI,CAAC,SAAS,KAAK,GAAG;EACtB,MAAM,KAAK,YAAY,MAAM,EAAE;EAC/B,MAAM,OAAO,YAAY,MAAM,IAAI;EACnC,MAAM,gBAAgB,YAAY,MAAM,cAAc;EACtD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,iBAAiB,GAAG;EAC1D,OAAO,KAAK;GACV;GACA;GACA,eAAe;GACf,WAAW,KAAK,IAAI,eAAe,yBAAyB;EAC9D,CAAC;CACH;CACA,IAAI,OAAO,WAAW,GACpB,MAAM,IAAI,SAAS,gDAAgD,yBAAyB;CAE9F,OAAO;AACT;AAEA,eAAe,gBAAgB,WAAgD;CAC7E,MAAM,SAAkB,KAAK,MAAM,MAAM,SAAS,WAAW,OAAO,CAAC;CACrE,IAAI,CAAC,SAAS,MAAM,KAAK,OAAO,YAAY,uBAAuB,CAAC,MAAM,QAAQ,OAAO,MAAM,GAC7F,MAAM,IAAI,MAAM,0BAA0B,WAAW;CAEvD,OAAO,OAAO;AAChB;AAEA,eAAe,iBAAiB,WAAmB,QAA2C;CAC5F,MAAM,MAAM,QAAQ,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;CACnD,MAAM,MAAM,GAAG,UAAU,GAAG,QAAQ,IAAI;CACxC,IAAI;EACF,MAAM,UAAU,KAAK,GAAG,KAAK,UAAU;GAAE,SAAS;GAAqB;EAAO,GAAG,MAAM,CAAC,EAAE,KAAK;GAC7F,UAAU;GACV,MAAM;EACR,CAAC;EACD,MAAM,OAAO,KAAK,SAAS;CAC7B,UAAU;EACR,MAAM,GAAG,KAAK,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;CACtD;AACF;;;;;;;;AAgBA,SAAS,gBAAgB,UAGvB;CACA,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,wBAAQ,IAAI,IAAoB;CACtC,MAAM,4BAAY,IAAI,IAAY;CAClC,KAAK,MAAM,WAAW,UACpB,KAAK,MAAM,SAAS,QAAQ,SAAS;EACnC,IAAI,QAAQ,SAAS,eAAe,MAAM,SAAS,aAAa;GAC9D,QAAQ,IAAI,MAAM,EAAE;GACpB,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI;EAChC;EACA,IAAI,MAAM,SAAS,eAAe,UAAU,IAAI,MAAM,UAAU;CAClE;CAEF,OAAO;EAAE,KAAK,IAAI,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,QAAQ,OAAO,UAAU,IAAI,EAAE,CAAC,CAAC;EAAG;CAAM;AAC/E;AAEA,SAAS,UAAU,OAA6B;CAC9C,OAAO,MAAM,SAAS,UAAU,MAAM,SAAS,cAAc,MAAM,OAAO;AAC5E;AAEA,SAAS,eAAe,OAA+D;CACrF,OAAO,MAAM,QAAQ,IAAI,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI;AAC/D;AAEA,SAAS,gBAAgB,SAA2B;CAClD,MAAM,SAAS,WACb,OAAO,MACJ,MAAM,EAAE,SAAS,WAAY,EAAE,SAAS,iBAAiB,MAAM,EAAE,OAAO,CAC3E;CACF,OAAO,MAAM,QAAQ,OAAO;AAC9B;;;;;;;AAQA,eAAe,mBACb,KACA,WAC0F;CAC1F,MAAM,OAAO,MAAM,UAAU,GAAG;CAChC,OAAO;EACL,MAAM;EACN,QAAQ;GACN,MAAM;GACN,YAAY,IAAI;GAChB,MAAM,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS,QAAQ;EAC3C;CACF;AACF;AAEA,eAAe,aACb,UACA,WACoB;CACpB,MAAM,MAAiB,CAAC;CACxB,MAAM,EAAE,KAAK,QAAQ,OAAO,cAAc,gBAAgB,QAAQ;CAElE,KAAK,MAAM,WAAW,UAAU;EAC9B,IAAI,QAAQ,SAAS,UAAU;EAE/B,IAAI,QAAQ,SAAS,UAAU,QAAQ,OAAO,SAAS,QAAQ;GAC7D,MAAM,QAAmB,CAAC;GAC1B,KAAK,MAAM,SAAS,QAAQ,SAAS;IACnC,IAAI,MAAM,SAAS,QAAQ,MAAM,KAAK;KAAE,MAAM;KAAQ,MAAM,MAAM;IAAK,CAAC;IACxE,IAAI,MAAM,SAAS,SAAS;KAI1B,IAAI,CAAC,WACH,MAAM,IAAI,SACR,uDACA,qBACF;KAEF,MAAM,KAAK,MAAM,mBAAmB,MAAM,YAAY,SAAS,CAAC;IAClE;GACF;GACA,IAAI,KAAK;IAAE,MAAM;IAAQ,SAAS;GAAM,CAAC;GACzC;EACF;EAEA,IAAI,QAAQ,SAAS,aAAa;GAChC,MAAM,QAAmB,CAAC;GAC1B,KAAK,MAAM,SAAS,QAAQ,SAC1B,IAAI,MAAM,SAAS,QACjB,MAAM,KAAK;IAAE,MAAM;IAAQ,MAAM,MAAM;GAAK,CAAC;QACxC,IAAI,MAAM,SAAS,eAAe,OAAO,IAAI,MAAM,EAAE,GAC1D,MAAM,KAAK;IACT,MAAM;IACN,YAAY,MAAM;IAClB,UAAU,MAAM;IAChB,OAAO,cAAc,MAAM,SAAS;GACtC,CAAC;GAIL,IAAI,MAAM,SAAS,GAAG,IAAI,KAAK;IAAE,MAAM;IAAa,SAAS;GAAM,CAAC;GACpE;EACF;EAGA,IAAI,QAAQ,SAAS,UAAU,QAAQ,OAAO,SAAS,QAAQ;GAC7D,MAAM,QAAQ,QAAQ,QAAQ;GAC9B,IAAI,CAAC,SAAS,MAAM,SAAS,iBAAiB,CAAC,OAAO,IAAI,MAAM,UAAU,GAAG;GAC7E,IAAI,KAAK;IACP,MAAM;IACN,SAAS,CACP;KACE,MAAM;KACN,YAAY,MAAM;KAIlB,UAAU,UAAU,IAAI,MAAM,UAAU,KAAK;KAC7C,QAAQ,MAAM,UACV;MAAE,MAAM;MAAc,OAAO,eAAe,KAAK;KAAE,IACnD;MAAE,MAAM;MAAQ,OAAO,eAAe,KAAK;KAAE;IACnD,CACF;GACF,CAAC;EACH;CACF;CACA,OAAO;AACT;;AAmHA,MAAM,uBAAuB;AAmB7B,IAAa,qBAAb,cAA+G,WAAW;CAU3F;CAT7B,UAAsC,CAAC;CACvC;CACA;CAIA,gCAAiC,IAAI,IAAyE;CAC9G,wCAAyC,IAAI,IAA2D;CAExG,YAAY,MAAkD;EAC5D,MAAM;EADqB,KAAA,OAAA;EAE3B,KAAK,YAAY,KAAK,aAAa;EACnC,KAAK,qBAAqB,KAAK;CACjC;;;;;;;;CASA,aAAsB,UAAmC;EACvD,OAAO;GAAE,IAAI;GAAU,MAAM;EAAe;CAC9C;;;;;;;;;;;;;;;;;;CAmBA,oBAA6B,WAAwC;EACnE,OAAO,mBACL;GACE,MAAM;GACN,YAAY;GACZ,gBAAgB;IAAC;IAAkB;IAAc;IAAU;IAAW;GAAW;GACjF,SAAS;IAAE,gBAAgB;IAAK,YAAY;IAAoB,aAAa;GAAI;EACnF,GACA,8BACF;CACF;;CAGA,MAAc,YAAY,QAAmD;EAC3E,MAAM,EAAE,SAAS,oBAAoB,KAAK,KAAK,QAAQ;EACvD,IAAI;GACF,MAAM,WAAW,MAAM,KAAK,UAAU,GAAG,QAAQ,sBAAsB;IACrE,SAAS;KAAE,QAAQ;KAAoB,GAAG,mBAAmB;IAAE;IAC/D,QAAQ,UAAU,YAAY,QAAA,GAAyB;GACzD,CAAC;GACD,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,4BAA4B,SAAS,QAAQ;GAE/D,KAAK,UAAU,qBAAqB,MAAM,SAAS,KAAK,CAAC;GACzD,MAAM,iBAAiB,iBAAiB,KAAK,OAAO,CAAC,CAAC,YAAY,KAAA,CAAS;EAC7E,SAAS,OAAO;GACd,IAAI,QAAQ,SAAS,MAAM;GAK3B,KAAK,UAAU,MAAM,gBAAgB,eAAe,CAAC,CAAC,YAAY,KAAK,OAAO;EAChF;EACA,OAAO,KAAK;CACd;CAEA,MAAe,WAAW,UAAoD;EAC5E,MAAM,UAAU,MAAM,KAAK,YAAY;EAMvC,MAAM,SAAS,KAAK,KAAK,QAAQ,CAAC,CAAC,uBAAuB,QACtD,KAAA,IACA,MAAM,KAAK,kBAAkB;EACjC,OAAO,QACJ,QAAQ,UAAU,mBAAmB,MAAM,IAAI,MAAM,CAAC,CAAC,CACvD,KAAK,UAAU;GACd,MAAM,SAAS,mBAAmB,IAAI,MAAM,EAAE;GAC9C,OAAO;IACL;IACA,IAAI,MAAM;IACV,MAAM,GAAG,MAAM,KAAK;IAGpB,aAAa,sBAAsB,MAAM,IAAI,MAAM,aAAa;IAChE,iBAAiB,SAAU,CAAC,QAAQ,OAAO,IAAe,CAAC,MAAM;GACnE;EACF,CAAC,CAAC,CAID,KAAK,aAAa;CACvB;CAEA,MAAe,aACb,UACA,OACA,QAC+B;EAC/B,MAAM,QACJ,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,KAAK,MACtC,MAAM,KAAK,YAAY,MAAM,EAAA,CAAG,MAAM,MAAM,EAAE,OAAO,KAAK;EAE7D,MAAM,UAAU,cAAc;EAC9B,MAAM,SAAS,mBAAmB,IAAI,KAAK;EAC3C,OAAO;GACL;GACA,IAAI;GACJ,MAAM,QAAQ,GAAG,MAAM,KAAK,SAAS;GACrC,aAAa,sBAAsB,OAAO,OAAO,aAAa;GAC9D,iBAAiB,SAAU,CAAC,QAAQ,OAAO,IAAe,CAAC,MAAM;GACjE,GAAI,QACA;IACE,SAAS,EAAE,eAAe,MAAM,cAAc;IAC9C,kBAAkB,KAAK,IAAI,MAAM,WAAW,2BAA2B;GACzE,IACA,CAAC;GAGL,GAAI,UACA,EACE,WAAW,EACT,SAAS,QAAQ,KAAK,YAAY;IAChC,IAAI,kBAAkB,MAAM;IAC5B,MAAM;GACR,EAAE,EACJ,EACF,IACA,CAAC;EACP;CACF;;CAGA,MAAc,eAAe,QAAkD;EAC7E,MAAM,aAAa,KAAK,KAAK,QAAQ;EAErC,OAAO;GACL,eAAe,UAFL,UAAW,MAAM,KAAK,KAAK,cAAc,UAAU;GAG7D,0BAA0B;GAC1B,qBAAqB;GACrB,GAAG,mBAAmB;EACxB;CACF;;;;;;CAOA,MAAc,oBAAmE;EAC/E,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,KAAK,KAAK,cAAc,KAAK,KAAK,QAAQ,CAAC;EAC5D,QAAQ;GACN;EACF;EACA,MAAM,SAAS,KAAK,cAAc,IAAI,MAAM;EAC5C,IAAI,WAAW,KAAA,KAAa,KAAK,IAAI,IAAI,OAAO,KAAA,KAA4B,OAAO,OAAO;EAC1F,MAAM,WAAW,KAAK,sBAAsB,IAAI,MAAM;EACtD,IAAI,aAAa,KAAA,GAAW,OAAO;EACnC,MAAM,WAAW,KAAK,mBAAmB,MAAM,CAAC,CAC7C,MAAM,UAAU;GACf,KAAK,cAAc,IAAI,QAAQ;IAAE;IAAO,IAAI,KAAK,IAAI;GAAE,CAAC;GACxD,OAAO;EACT,CAAC,CAAC,CACD,cAAc;GACb,KAAK,sBAAsB,OAAO,MAAM;EAC1C,CAAC;EACH,KAAK,sBAAsB,IAAI,QAAQ,QAAQ;EAC/C,OAAO;CACT;;;;;;;;;;CAWA,MAAc,mBAAmB,QAA+D;EAC9F,IAAI;GACF,MAAM,aAAa,KAAK,KAAK,QAAQ;GACrC,MAAM,UAAU,MAAM,KAAK,eAAe,MAAM;GAChD,MAAM,OAAO,WAAW;GACxB,MAAM,UAAU,OAAO,SAA+D;IACpF,MAAM,WAAW,MAAM,KAAK,UAAU,GAAG,OAAO,QAAQ;KACtD;KAEA,QAAQ,YAAY,QAAQ,iBAAiB;IAC/C,CAAC;IACD,IAAI,CAAC,SAAS,IAAI,OAAO,KAAA;IACzB,MAAM,SAAkB,MAAM,SAAS,KAAK;IAC5C,OAAO,SAAS,MAAM,IAAI,SAAS,KAAA;GACrC;GACA,MAAM,SAAS,MAAM,QAAQ,eAAe;GAC5C,MAAM,UAAU,UAAU,SAAS,OAAO,GAAG,IAAI,OAAO,MAAM,KAAA;GAC9D,MAAM,QAAQ,YAAY,KAAA,IAAY,KAAA,IAAY,YAAY,QAAQ,EAAE;GACxE,MAAM,CAAC,cAAc,WAAW,MAAM,QAAQ,IAAI,CAChD,QAAQ,UAAU,KAAA,IACd,iCACA,sCAAsC,mBAAmB,KAAK,GAAG,GACrE,QAAQ,wBAAwB,CAClC,CAAC;GACD,MAAM,UAAU,gBAAgB,SAAS,aAAa,IAAI,IAAI,aAAa,OAAO,KAAA;GAClF,MAAM,cAAc,WAAW,SAAS,QAAQ,OAAO,IAAI,QAAQ,UAAU,KAAA;GAC7E,IAAI,YAAY,KAAA,KAAa,gBAAgB,KAAA,GAAW,OAAO,KAAA;GAC/D,IAAI;GACJ,IAAI,YAAY,KAAA,GAAW;IACzB,MAAM,SAAS,YAAY,QAAQ,MAAM;IACzC,IAAI,WAAW,KAAA,KAAa,6BAA6B,IAAI,MAAM,GAAG,SAAS,YAAY,QAAQ,MAAM;GAC3G,OACE,SAAS,YAAY,aAAa,MAAM;GAE1C,OAAO;IACL,YAAY,WAAW,KAAA,IAAY,KAAA,IAAY,qBAAqB,MAAM,CAAC,EAAE;IAC7E,kBAAkB,YAAY,aAAa,gBAAgB,KAAK,MAAM,YAAY,aAAa,WAAW,KAAK;GACjH;EACF,QAAQ;GACN;EACF;CACF;;;;;;;;;;;CAYA,MAAM,SAAS,QAAkD;EAE/D,MAAM,OADa,KAAK,KAAK,QACP,CAAC,CAAC;EACxB,MAAM,UAAU,MAAM,KAAK,eAAe,MAAM;EAChD,MAAM,WAAqB,CAAC;EAG5B,MAAM,iBAA4C,CAAC;EAEnD,MAAM,UAAU,OAAO,SAA+D;GACpF,IAAI;IACF,MAAM,WAAW,MAAM,KAAK,UAAU,GAAG,OAAO,QAAQ;KACtD;KAGA,QAAQ,YAAY,QAAQ,iBAAiB;IAC/C,CAAC;IACD,IAAI,CAAC,SAAS,IAAI;KAChB,SAAS,KAAK,GAAG,KAAK,SAAS,SAAS,QAAQ;KAChD,eAAe,KAAK,SAAS,MAAM;KACnC;IACF;IACA,MAAM,SAAkB,MAAM,SAAS,KAAK;IAC5C,OAAO,SAAS,MAAM,IAAI,SAAS,KAAA;GACrC,SAAS,OAAgB;IACvB,SAAS,KAAK,GAAG,KAAK,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;IAClF,eAAe,KAAK,KAAA,CAAS;IAC7B;GACF;EACF;EAEA,MAAM,SAAiC,EAAE,SAAS;EAGlD,MAAM,SAAS,MAAM,QAAQ,eAAe;EAC5C,MAAM,aAAa,UAAU,SAAS,OAAO,IAAI,IAAI,OAAO,OAAO,KAAA;EACnE,IAAI,YACF,OAAO,UAAU;GACf,IAAI,YAAY,WAAW,EAAE,KAAK;GAClC,MAAM,YAAY,WAAW,IAAI,KAAK;GACtC,UAAU,YAAY,WAAW,QAAQ,KAAK;EAChD;EAEF,MAAM,UAAU,UAAU,SAAS,OAAO,GAAG,IAAI,OAAO,MAAM,KAAA;EAC9D,MAAM,QAAQ,YAAY,KAAA,IAAY,KAAA,IAAY,YAAY,QAAQ,EAAE;EAGxE,MAAM,QAAQ,MAAM,QAAQ,sBAAsB;EAClD,IAAI,OACF,OAAO,QAAQ;GACb,YAAY,YAAY,MAAM,UAAU,KAAK;GAC7C,WAAW,YAAY,MAAM,SAAS,KAAK;GAC3C,aAAa,YAAY,MAAM,WAAW,KAAK;GAC/C,gBAAgB,YAAY,MAAM,cAAc,KAAK;GACrD,aAAa,YAAY,MAAM,WAAW,KAAK;GAC/C,eAAe,YAAY,MAAM,aAAa,KAAK;GACnD,gBAAgB,YAAY,MAAM,cAAc,KAAK;GACrD,cAAc,YAAY,MAAM,YAAY,KAAK;GACjD,aAAa,YAAY,MAAM,WAAW,KAAK;EACjD;EAIF,MAAM,UAAU,MAAM,QAAQ,wBAAwB;EACtD,MAAM,cAAc,WAAW,SAAS,QAAQ,OAAO,IAAI,QAAQ,UAAU,KAAA;EAC7E,MAAM,eAAe,WAAW,SAAS,QAAQ,YAAY,IAAI,QAAQ,eAAe,KAAA;EACxF,MAAM,WAAW,gBAAgB,SAAS,aAAa,QAAQ,IAAI,aAAa,WAAW,KAAA;EAC3F,MAAM,SAAS,gBAAgB,SAAS,aAAa,MAAM,IAAI,aAAa,SAAS,KAAA;EACrF,IAAI,eAAe,YAAY,QAC7B,OAAO,UAAU;GACf,gBAAgB,YAAY,aAAa,cAAc,KAAK;GAC5D,kBAAkB,YAAY,aAAa,gBAAgB,KAAK;GAChE,aAAa,YAAY,aAAa,WAAW,KAAK;GACtD,UAAU;IACR,MAAM,YAAY,UAAU,IAAI,KAAK;IACrC,KAAK,YAAY,UAAU,GAAG,KAAK;IACnC,UAAU,UAAU,aAAa;IACjC,SAAS,YAAY,UAAU,OAAO,KAAK;GAC7C;GACA,QAAQ;IACN,MAAM,YAAY,QAAQ,IAAI,KAAK;IACnC,KAAK,YAAY,QAAQ,GAAG,KAAK;IACjC,UAAU,QAAQ,aAAa;IAC/B,SAAS,YAAY,QAAQ,OAAO,KAAK;GAC3C;EACF;EAOF,MAAM,eAAe,MAAM,QAAQ,UAAU,KAAA,IACzC,iCACA,sCAAsC,mBAAmB,KAAK,GAAG;EACrE,MAAM,UAAU,gBAAgB,SAAS,aAAa,IAAI,IAAI,aAAa,OAAO,KAAA;EAClF,MAAM,SAAS,YAAY,SAAS,MAAM,KAAK,YAAY,aAAa,MAAM;EAC9E,IAAI,YAAY,KAAA,KAAa,WAAW,KAAA,GAAW;GACjD,MAAM,OAAO,WAAW,KAAA,IAAY,KAAA,IAAY,qBAAqB,MAAM;GAC3E,OAAO,OAAO;IACZ,QAAQ,UAAU;IAClB,MAAM,MAAM,QAAQ,UAAU;IAC9B,QAAQ,YAAY,SAAS,MAAM,KAAK;IACxC,gBAAgB,MAAM,kBAAkB;IACxC,kBAAkB,eAAe,SAAS,gBAAgB;GAC5D;EACF;EAOA,IAAI,SAAS,WAAW,sBAAsB;GAC5C,MAAM,QAAQ,eAAe,QAAQ,WAA6B,WAAW,KAAA,CAAS;GACtF,IAAI,MAAM,WAAW,wBAAwB,MAAM,OAAO,SAAS,SAAS,GAAG,GAC7E,OAAO,UAAU;QACZ,IAAI,MAAM,WAAW,wBAAwB,MAAM,OAAO,SAAS,QAAQ,GAAG,GACnF,OAAO,UAAU;QACZ,IAAI,MAAM,WAAW,GAC1B,OAAO,UAAU;EAErB;EAEA,OAAO;CACT;;;;;;;;;CAUA,MAAM,oBAAoB,QAA6E;EACrG,IAAI;GACF,MAAM,aAAa,KAAK,KAAK,QAAQ;GACrC,MAAM,WAAW,MAAM,KAAK,UAAU,GAAG,WAAW,QAAQ,yBAAyB;IACnF,SAAS,MAAM,KAAK,eAAe,MAAM;IACzC,QAAQ,YAAY,QAAQ,iBAAiB;GAC/C,CAAC;GACD,IAAI,CAAC,SAAS,IAAI,OAAO,KAAA;GACzB,MAAM,SAAkB,MAAM,SAAS,KAAK;GAC5C,IAAI,CAAC,SAAS,MAAM,GAAG,OAAO,KAAA;GAC9B,MAAM,eAAe,SAAS,OAAO,YAAY,IAAI,OAAO,eAAe,KAAA;GAC3E,MAAM,WAAW,gBAAgB,SAAS,aAAa,QAAQ,IAAI,aAAa,WAAW,KAAA;GAC3F,IAAI,aAAa,KAAA,GAAW,OAAO,KAAA;GACnC,OAAO;IAAE,UAAU,SAAS,aAAa;IAAM,SAAS,YAAY,SAAS,OAAO,KAAK;GAAE;EAC7F,QAAQ;GACN;EACF;CACF;CAEA,OAAO,OAAO,SAAsD;EAClE,IAAI,QAAQ,MAAM,QAGhB,MAAM,IAAI,SAAS,wDAAwD,oBAAoB;EAEjG,MAAM,YAAY,QAAQ,SAAS,KAAK,eAAe;EAIvD,IAAI;EACJ,IAAI,WAAW;GAMb,IAAI,CAAC,mBAAmB,IAAI,QAAQ,KAAK,GACvC,MAAM,IAAI,SACR,uBAAuB,QAAQ,MAAM,4FAErC,qBACF;GAIF,MAAM,cAAc,KAAK,qBAAqB;GAC9C,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,SACR,oEACA,qBACF;GAEF,aAAa,QAAQ,YAAY,UAAU,GAAG,CAAC,CAAC,MAAM,WAAW,OAAO,IAAI;EAC9E;EAEA,MAAM,aAAa,KAAK,KAAK,QAAQ;EAGrC,IAAI,SAAS,MAAM,KAAK,KAAK,cAAc,YAAY,QAAQ,KAAK;EAEpE,MAAM,WADQ,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ,KACnC,CAAC,EAAE,aAAA;EACxB,MAAM,YAAY,KAAK,IACrB,QAAQ,aAAa,UACrB,UACA,2BACF;EAEA,MAAM,SAAS,QAAQ;EACvB,MAAM,YAAY,cAAc,QAAQ;EACxC,MAAM,kBACJ,UAAU,WAAW,SAAS,WAAW,SAAS,MAAM,IAAI,SAAS,KAAA;EAEvE,MAAM,aAAa,CACjB,QAAQ,UAAU,IAClB,GAAG,QAAQ,SACR,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,CAClC,KAAK,MAAM,EAAE,QAAQ,IAAI,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC,CACnE,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,MAAM;EAEd,MAAM,OAAO;GACX,QAAQ;IACN,YAAY,WAAW;IACvB,uBAAM,IAAI,KAAK,EAAA,CAAE,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,aAAa,GAAG,QAAQ,SAAS,GAAG,QAAQ,KAAK,YAAY,QAAQ;IACrE,WAAW,CAAC;IACZ,WAAW;IACX,eAAe;IACf,YAAY;IACZ,WAAW;IACX,eAAe,CAAC;GAClB;GACA,QAAQ;GACR,OAAO;GACP,QAAQ;GACR,QAAQ;IACN,OAAO,QAAQ;IACf,UAAU,MAAM,aAAa,QAAQ,UAAU,SAAS;IACxD,QAAQ,QAAQ,SAAS,CAAC,EAAA,CAAG,KAAK,UAAU;KAC1C,MAAM;KACN,MAAM,KAAK;KACX,aAAa,KAAK;KAClB,cAAc,KAAK;IACrB,EAAE;IACF,QAAQ;IACR,YAAY;IACZ,aAAa,QAAQ,eAAe;IACpC,QAAQ;IACR,GAAI,kBAAkB,EAAE,kBAAkB,gBAAgB,IAAI,CAAC;GACjE;GACA,UAAU,WAAW;EACvB;EAYA,MAAM,UAAU,OACd,QACsH;GACtH,MAAM,eAAe,IAAI,gBAAgB;GACzC,IAAI,kBAAkB;GACtB,MAAM,eAAe,iBAAiB;IACpC,kBAAkB;IAClB,aAAa,MACX,IAAI,aACF,+BAA+B,WAAW,QAAQ,yCAAyC,WAAW,iBAAiB,KACvH,cACF,CACF;GACF,GAAG,WAAW,gBAAgB;GAC9B,MAAM,sBAAsB;IAC1B,aAAa,MAAM,QAAQ,QAAQ,MAAM;GAC3C;GACA,IAAI,QAAQ,QAAQ;IAClB,IAAI,QAAQ,OAAO,SACjB,cAAc;SAEd,QAAQ,OAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,KAAK,CAAC;GAE1E;GAIA,MAAM,gBAAgB;IACpB,aAAa,YAAY;IACzB,IAAI,QAAQ,QACV,QAAQ,OAAO,oBAAoB,SAAS,aAAa;GAE7D;GAEA,IAAI;GACJ,IAAI;IACF,WAAW,MAAM,KAAK,UAAU,GAAG,WAAW,QAAQ,kBAAkB;KACtE,QAAQ;KACR,SAAS;MACP,gBAAgB;MAChB,eAAe,UAAU;MACzB,0BAA0B;MAC1B,qBAAqB;MACrB,kBAAkB,oBAAoB,WAAW,UAAU;MAC3D,oBAAoB;MACpB,aAAa;MACb,GAAG,mBAAmB;KACxB;KACA,MAAM,KAAK,UAAU,IAAI;KACzB,QAAQ,aAAa;IACvB,CAAC;IACD,aAAa,YAAY;GAC3B,SAAS,OAAgB;IACvB,QAAQ;IACR,IAAI,QAAQ,QAAQ,SAClB,MAAM;IAER,IAAI,mBAAoB,iBAAiB,gBAAgB,MAAM,SAAS,gBACtE,MAAM,IAAI,SACR,+BAA+B,WAAW,QAAQ,yCAAyC,WAAW,iBAAiB,MAChH,WAAW,KAAK,EAAA,wBACI,WAAW,iBAAiB,+BACvD,WACA,EAAE,OAAO,MAAM,CACjB;IAOF,MAAM,IAAI,SACR,+BAA+B,WAAW,QAAQ,0BAA0B,WAAW,KAAK,EAAA,qDAE5F,aACA,EAAE,OAAO,MAAM,CACjB;GACF;GAEA,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,UAAU,MAAM,SAAS,KAAK,CAAC,CAAC,YAAY,EAAE;IACpD,QAAQ;IACR,MAAM,eAAe,kBAAkB,SAAS,QAAQ,IAAI,aAAa,CAAC;IAE1E,OAAO,iBAAiB,KAAA,IACpB;KAAE,QAAQ,SAAS;KAAQ;IAAQ,IACnC;KAAE,QAAQ,SAAS;KAAQ;KAAS;IAAa;GACvD;GACA,OAAO;IAAE;IAAU;GAAQ;EAC7B;EAKA,MAAM,wBAAQ,IAAI,IAAY;EAC9B,IAAI;EACJ,SAAS;GACP,MAAM,IAAI,MAAM;GAChB,MAAM,UAAU,MAAM,QAAQ,MAAM;GACpC,IAAI,cAAc,SAAS;IACzB,YAAY;IACZ;GACF;GACA,MAAM,SAAS,KAAK,KAAK;GACzB,KACG,QAAQ,WAAW,OAAO,QAAQ,WAAW,QAC3C,WAAW,KAAA,KACX,QAAQ,QAAQ,YAAY,QAC5B,MAAM,OAAO,uBAChB;IACA,MAAM,OAAO,MAAM,OAAO,QAAQ,QAAQ,WAAW,MAAM,eAAe,sBAAsB,YAAY,QAAQ,KAAK;IACzH,IAAI,SAAS,KAAA,KAAa,CAAC,MAAM,IAAI,IAAI,GAAG;KAC1C,SAAS;KACT;IACF;GACF;GACA,MAAM,kBAAkB,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,YAAY;EAC/E;EACA,MAAM,EAAE,UAAU,YAAY;EAC9B,IAAI,CAAC,SAAS,MAAM;GAClB,QAAQ;GACR,MAAM,IAAI,SAAS,8CAA8C,yBAAyB;EAC5F;EAGA,MAAM,SAAS,SAAS,KAAK,UAAU;EACvC,MAAM,UAAU,IAAI,YAAY;EAChC,IAAI,SAAS;EAUb,IAAI;EACJ,IAAI,YAAY;EAChB,MAAM,gBAAgB;GACpB,IAAI,cAAc,KAAA,GAAW,aAAa,SAAS;GACnD,YAAY,iBAAiB;IAC3B,YAAY;IACZ,OAAY,OAAO,CAAC,CAAC,YAAY,KAAA,CAAS;GAC5C,GAAG,WAAW,mBAAmB;EACnC;EACA,MAAM,kBAAkB;GACtB,IAAI,cAAc,KAAA,GAAW;IAC3B,aAAa,SAAS;IACtB,YAAY,KAAA;GACd;EACF;EAIA,IAAI,YAAY;EAChB,IAAI,YAAY;EAChB,IAAI,cAAc;EAClB,IAAI,iBAAiB;EACrB,IAAI,mBAAmB;EACvB,IAAI,aAAa;EAEjB,MAAM,YAAY,aAAqC;GACrD,IAAI,YAAY,GAAG;GACnB,MAAM;IACJ,MAAM;IACN,OAAO;IACP,OAAO;KAAE,MAAM;KAAQ,MAAM;IAAY;GAC3C;GACA,YAAY;GACZ,cAAc;EAChB;EACA,MAAM,iBAAiB,aAAqC;GAC1D,IAAI,iBAAiB,GAAG;GACxB,MAAM;IACJ,MAAM;IACN,OAAO;IACP,OAAO;KAAE,MAAM;KAAa,MAAM;IAAiB;GACrD;GACA,iBAAiB;GACjB,mBAAmB;EACrB;EAEA,MAAM,eAAe,UAAkC;GACrD,MAAM,SAAwB,CAAC;GAC/B,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;GAE7B,QAAQ,MAAM,MAAd;IACE,KAAK,cAAc;KACjB,OAAO,KAAK,GAAG,eAAe,CAAC;KAC/B,IAAI,YAAY,GAAG;MACjB,YAAY;MACZ,OAAO,KAAK;OAAE,MAAM;OAAe,OAAO;OAAW,WAAW;MAAO,CAAC;KAC1E;KACA,MAAM,QAAQ,YAAY,MAAM,IAAI,KAAK;KACzC,eAAe;KACf,aAAa;KACb,OAAO,KAAK;MAAE,MAAM;MAAc,OAAO;MAAW,MAAM;KAAM,CAAC;KACjE;IACF;IACA,KAAK,mBAAmB;KACtB,OAAO,KAAK,GAAG,UAAU,CAAC;KAC1B,IAAI,iBAAiB,GAAG;MACtB,iBAAiB;MACjB,OAAO,KAAK;OAAE,MAAM;OAAe,OAAO;OAAgB,WAAW;MAAY,CAAC;KACpF;KACA,MAAM,QAAQ,YAAY,MAAM,IAAI,KAAK;KACzC,oBAAoB;KACpB,OAAO,KAAK;MAAE,MAAM;MAAmB,OAAO;MAAgB,MAAM;KAAM,CAAC;KAC3E;IACF;IACA,KAAK;KACH,OAAO,KAAK,GAAG,UAAU,CAAC;KAC1B;IACF,KAAK;KACH,OAAO,KAAK,GAAG,eAAe,CAAC;KAC/B;IACF,KAAK,aAAa;KAChB,OAAO,KAAK,GAAG,UAAU,GAAG,GAAG,eAAe,CAAC;KAC/C,MAAM,KAAK,YAAY,MAAM,UAAU,KAAK,WAAW;KACvD,MAAM,OAAO,YAAY,MAAM,QAAQ,KAAK;KAC5C,MAAM,OAAO,KAAK,UAAU,cAAc,MAAM,SAAS,MAAM,QAAQ,MAAM,SAAS,CAAC;KACvF,MAAM,QAAQ;KACd,aAAa;KACb,OAAO,KACL;MAAE,MAAM;MAAe;MAAO,WAAW;KAAY,GACrD;MAAE,MAAM;MAAmB;MAAO,IAAI,WAAW,EAAE;MAAG;MAAM,gBAAgB;KAAK,GACjF;MACE,MAAM;MACN;MACA,OAAO;OAAE,MAAM;OAAa,IAAI,WAAW,EAAE;OAAG;OAAM,WAAW;MAAK;KACxE,CACF;KACA;IACF;IACA,KAAK,UAAU;KACb,OAAO,KAAK,GAAG,UAAU,GAAG,GAAG,eAAe,CAAC;KAC/C,MAAM,QAAQ,SAAS,MAAM,UAAU,IAAI,MAAM,aAAa,KAAA;KAC9D,IAAI,OAAO;MACT,MAAM,UAAU,SAAS,MAAM,iBAAiB,IAAI,MAAM,oBAAoB,KAAA;MAC9E,MAAM,aAAa,YAAY,MAAM,WAAW,KAAK;MACrD,MAAM,YAAY,YAAY,SAAS,eAAe,KAAK;MAC3D,MAAM,aAAa,YAAY,SAAS,gBAAgB,KAAK;MAE7D,MAAM,aAAyB;OAC7B,aACE,YAAY,SAAS,aAAa,KAAK,KAAK,IAAI,GAAG,aAAa,YAAY,UAAU;OACxF,cAAc,YAAY,MAAM,YAAY,KAAK;OACjD,iBAAiB;OACjB,kBAAkB;MACpB;MACA,OAAO,KAAK;OAAE,MAAM;OAAS,OAAO;MAAW,CAAC;KAClD;KACA,OAAO,KAAK;MAAE,MAAM;MAAU,QAAQ,gBAAgB,MAAM,YAAY;KAAE,CAAC;KAC3E;IACF;IACA,KAAK,SAAS;KAUZ,MAAM,MAAM,SAAS,MAAM,KAAK,IAAI,MAAM,QAAQ,KAAA;KAClD,MAAM,SAAS,SAAS,MAAM,KAAK,IAC9B,YAAY,MAAM,MAAM,OAAO,KAAK,KAAK,UAAU,MAAM,KAAK,IAC9D,YAAY,MAAM,KAAK,KAAK,YAAY,MAAM,OAAO,KAAK;KAC/D,MAAM,aAAa,MAAM,YAAY,IAAI,UAAU,IAAI,KAAA;KACvD,MAAM,cAAc,MAAM,aAAa,IAAI,WAAW,IAAI,KAAA;KAC1D,MAAM,kBAAkB,eAAe,KAAA,MAAc,eAAe,OAAO,cAAc;KACzF,MAAM,WAAW,wBAAwB,MAAM;KAG/C,IAAI,EAFc,gBAAgB,SAC5B,eAAe,KAAA,IAAY,kBAAmB,gBAAgB,SAAS,CAAC,YAE5E,MAAM,IAAI,SACR,8BAA8B,UAC9B,yBACA,eAAe,KAAA,IAAY,EAAE,QAAQ,WAAW,IAAI,KAAA,CACtD;KAEF,MAAM,IAAI,SACR,8BAA8B,UAC9B,UACA,eAAe,KAAA,IAAY,EAAE,QAAQ,WAAW,IAAI,KAAA,CACtD;IACF;GACF;GACA,OAAO;EACT;EAEA,IAAI;GACF,IAAI,WAAW;GACf,SAAS;IACP,IAAI;IACJ,QAAQ;IACR,IAAI;KACF,OAAO,MAAM,OAAO,KAAK;IAC3B,SAAS,OAAgB;KAGvB,IAAI,QAAQ,QAAQ,SAAS,MAAM;KACnC,MAAM,IAAI,SACR,gCAAgC,WAAW,QAAQ,yBAAyB,WAAW,KAAK,EAAA,6CAE5F,aACA,EAAE,OAAO,MAAM,CACjB;IACF,UAAU;KACR,UAAU;IACZ;IACA,MAAM,EAAE,MAAM,UAAU;IACxB,IAAI,MAAM;KAIR,IAAI,WACF,MAAM,IAAI,SACR,gCAAgC,WAAW,QAAQ,gBAAgB,WAAW,oBAAoB,6EAErE,WAAW,oBAAoB,sCAC5D,SACF;KAEF,IAAI,OAAO,KAAK,GAAG,KAAK,MAAM,SAAS,YAAY,qBAAqB,MAAM,CAAC,GAAG,MAAM;KACxF;IACF;IACA,UAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;IAChD,MAAM,QAAQ,OAAO,MAAM,IAAI;IAC/B,SAAS,MAAM,IAAI,KAAK;IACxB,KAAK,MAAM,QAAQ,OAAO;KACxB,MAAM,SAAS,YAAY,qBAAqB,IAAI,CAAC;KACrD,KAAK,MAAM,SAAS,QAAQ;MAC1B,MAAM;MACN,IAAI,MAAM,SAAS,UAAU,WAAW;KAC1C;IACF;IACA,IAAI,UAAU;GAChB;GACA,IAAI,CAAC,UAAU;IAGb,OAAO,UAAU;IACjB,OAAO,eAAe;IACtB,IAAI,CAAC,YACH,MAAM,IAAI,SAAS,uEAAuE,gBAAgB;IAE5G,MAAM;KAAE,MAAM;KAAU,QAAQ,EAAE,MAAM,OAAO;IAAE;GACnD;EACF,UAAU;GACR,UAAU;GACV,QAAQ;GACR,MAAM,OAAO,OAAO,CAAC,CAAC,YAAY,KAAA,CAAS;GAC3C,OAAO,YAAY;EACrB;CACF;AACF;;AAGA,MAAM,wBAAwB;;;;;;;;;;;AAY9B,SAAS,kBAAkB,QAAgB,SAAiB,cAAiC;CAC3F,IAAI;CACJ,IAAI;EACF,MAAM,SAAkB,KAAK,MAAM,OAAO;EAC1C,IAAI,SAAS,MAAM,KAAK,SAAS,OAAO,KAAK,GAC3C,eAAe,YAAY,OAAO,MAAM,IAAI;CAEhD,QAAQ,CAER;CACA,MAAM,SAAS,gBAAgB,QAAQ;CACvC,IAAI,WAAW,KAIb,OAAO,IAAI,SACT,+BAA+B,OAAO,wMAGtC,sBACA,EAAE,QAAQ,IAAI,CAChB;CAEF,OAAO,IAAI,SACT,0BAA0B,SAAS,WAAW,QAAQ,WAAW,KAAK,KAAK,OAAO,GAAG,IAAI,QAAQ,MAAM,GAAG,GAAG,KAC7G,WAAW,MAAM,eAAe,uBAChC;EACE;EACA,GAAI,iBAAiB,KAAA,KAAa,eAAe,KAAK,gBAAA,MAClD,EAAE,sBAAsB,aAAa,IACrC,CAAC;CACP,CACF;AACF;;;;;;;;;AAUA,SAAS,kBAAkB,OAAkC,MAAM,KAAK,IAAI,GAAuB;CACjG,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,OAAO,KAAA;CAClD,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,YAAY,IAAI,OAAO,KAAA;CAC3B,MAAM,UAAU,OAAO,OAAO;CAC9B,IAAI,OAAO,SAAS,OAAO,KAAK,WAAW,GAAG;EAC5C,MAAM,KAAK,UAAU;EACrB,OAAO,OAAO,SAAS,EAAE,IAAI,KAAK,MAAM,EAAE,IAAI,KAAA;CAChD;CACA,MAAM,OAAO,KAAK,MAAM,OAAO;CAC/B,IAAI,CAAC,OAAO,MAAM,IAAI,GAAG,OAAO,KAAK,IAAI,GAAG,OAAO,GAAG;AAExD;AAEA,SAAS,gBAAgB,QAA+B;CACtD,IAAI,WAAW,cAAc,OAAO,EAAE,MAAM,aAAa;CACzD,IACE,WAAW,YACX,WAAW,gBACX,WAAW,gBACX,WAAW,qBAEX,OAAO,EAAE,MAAM,aAAa;CAE9B,OAAO,EAAE,MAAM,OAAO;AACxB;;;ACx7DA,MAAa,qBAA8E;CACzF,IAAI;EACF,OAAO;EACP,cAAc;EACd,kBAAkB;EAClB,aAAa;EACb,wBAAwB;EACxB,eAAe;EACf,gBAAgB;EAChB,cAAc;EACd,mBACE;EACF,2BACE;EACF,gBACE;EACF,UAAU;EACV,kBAAkB;EAClB,aAAa;EACb,cAAc;EACd,UAAU;EACV,YAAY;EACZ,eAAe;EACf,aAAa;EACb,SAAS;EACT,eAAe;EACf,cAAc;EACd,YAAY;EACZ,eAAe;EACf,iBAAiB;EACjB,aAAa;EACb,iBAAiB;EACjB,QAAQ;EACR,WAAW;EACX,WACE;CAEJ;CACA,IAAI;EACF,OAAO;EACP,cAAc;EACd,kBAAkB;EAClB,aAAa;EACb,wBAAwB;EACxB,eAAe;EACf,gBAAgB;EAChB,cAAc;EACd,mBACE;EACF,2BACE;EACF,gBACE;EACF,UAAU;EACV,kBAAkB;EAClB,aAAa;EACb,cAAc;EACd,UAAU;EACV,YAAY;EACZ,eAAe;EACf,aAAa;EACb,SAAS;EACT,eAAe;EACf,cAAc;EACd,YAAY;EACZ,eAAe;EACf,iBAAiB;EACjB,aAAa;EACb,iBAAiB;EACjB,QAAQ;EACR,WAAW;EACX,WACE;CAGJ;AACF;;;;;;;;;;;;;;;AAgBA,SAAgB,kBACd,UACA,MAAoD,QAAQ,KAClD;CACV,IAAI,aAAa,QAAQ,aAAa,MAAM,OAAO;CAGnD,MAFY,IAAI,UAAU,IAAI,QAAQ,GAAA,CACtB,YAAY,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,QACvC,MAAM,OAAO;CACzB,OAAO;AACT;;AAGA,SAAgB,YAAY,QAAkB,KAAoC;CAChF,OAAO,mBAAmB,OAAO,CAAC,QAAQ,mBAAmB,GAAG,QAAQ;AAC1E;;;;ACtGA,SAAS,MAAM,OAAuB;CACpC,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC5B;;AAGA,SAAS,WAAW,OAAuB;CACzC,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC5B;;AAGA,SAAS,cAAc,OAAuB;CAC5C,IAAI,SAAS,KAAK,OAAO,IAAI,QAAQ,IAAA,CAAK,QAAQ,CAAC,EAAE;CACrD,IAAI,SAAS,KAAK,OAAO,IAAI,QAAQ,IAAA,CAAK,QAAQ,CAAC,EAAE;CACrD,IAAI,SAAS,KAAK,OAAO,IAAI,QAAQ,IAAA,CAAK,QAAQ,CAAC,EAAE;CACrD,OAAO,OAAO,KAAK;AACrB;;AAGA,SAAS,WAAW,IAAoB;CACtC,IAAI,MAAM,GAAG,OAAO;CACpB,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,eAAe;AACrC;;;;;AAMA,SAAS,IAAI,MAAc,KAAqB;CAC9C,IAAI,OAAO,GAAG,OAAO;CACrB,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,GAAG,CAAC;CACjD,MAAM,SAAS,KAAK,MAAM,QAAQ,EAAE;CACpC,OAAO,IAAI,OAAO,MAAM,IAAI,IAAI,OAAO,KAAK,MAAM;AACpD;;AAOA,SAAS,UAAU,OAAgC,QAA0B;CAC3E,IAAI,MAAM,SAAS,sBAAsB,OAAO,YAAY,QAAQ,wBAAwB;CAC5F,IAAI,MAAM,gBAAgB,GACxB,OAAO,YAAY,QAAQ,eAAe,CAAC,CAAC,QAAQ,UAAU,WAAW,MAAM,aAAa,CAAC;CAE/F,IAAI,MAAM,SAAS,cAAc,OAAO,YAAY,QAAQ,gBAAgB;CAC5E,OAAO;AACT;;AAGA,SAAS,aAAa,QAAgC,QAAkB,OAAwB;CAC9F,MAAM,QAAkB,CAAC;CACzB,MAAM,UAAU,OAAO,UAAU,KAAK,OAAO,QAAQ,YAAY,OAAO,QAAQ,KAAK,KAAK;CAE1F,MAAM,KACJ,SAAS,YAAY,QAAQ,OAAO,CAAC,CAAC,QAAQ,aAAa,OAAO,GAClE,EACF;CAIA,IAAI,OAAO,YAAY,eACrB,MAAM,KAAK,YAAY,QAAQ,mBAAmB,GAAG,EAAE;MAClD,IAAI,OAAO,YAAY,uBAC5B,MAAM,KAAK,YAAY,QAAQ,2BAA2B,GAAG,EAAE;MAC1D,IAAI,OAAO,YAAY,WAC5B,MAAM,KAAK,YAAY,QAAQ,gBAAgB,GAAG,EAAE;CAGtD,IAAI,OAAO,QAAQ,OAAO,KAAK,SAAS,IAAI;EAC1C,MAAM,IAAI,OAAO;EACjB,MAAM,SAAS,EAAE,WAAW,MAAM,EAAE,WAAW,WAAW,KAAK,EAAE,OAAO,KAAK;EAC7E,MAAM,SAAS,EAAE,mBAAmB,IAChC,YAAY,QAAQ,kBAAkB,CAAC,CAAC,QAAQ,UAAU,IAAI,KAAK,EAAE,gBAAgB,CAAC,CAAC,mBAAmB,CAAC,IAC3G;EACJ,MAAM,KAAK,YAAY,QAAQ,UAAU,CAAC,CACvC,QAAQ,UAAU,EAAE,IAAI,CAAC,CACzB,QAAQ,YAAY,MAAM,CAAC,CAC3B,QAAQ,YAAY,MAAM,GAAG,EAAE;CACpC;CAEA,IAAI,OAAO,OAAO;EAChB,MAAM,IAAI,OAAO;EACjB,MAAM,KACJ,YAAY,QAAQ,aAAa,GACjC,YAAY,QAAQ,cAAc,CAAC,CAChC,QAAQ,OAAO,OAAO,EAAE,cAAc,CAAC,CAAC,CACxC,QAAQ,OAAO,OAAO,EAAE,WAAW,CAAC,CAAC,CACrC,QAAQ,OAAO,OAAO,EAAE,WAAW,CAAC,GACvC,YAAY,QAAQ,UAAU,CAAC,CAC5B,QAAQ,WAAW,MAAM,EAAE,SAAS,CAAC,CAAC,CACtC,QAAQ,aAAa,WAAW,EAAE,YAAY,CAAC,GAClD,YAAY,QAAQ,YAAY,CAAC,CAC9B,QAAQ,QAAQ,cAAc,EAAE,aAAa,CAAC,CAAC,CAC/C,QAAQ,SAAS,cAAc,EAAE,cAAc,CAAC,GACnD,EACF;CACF;CAEA,IAAI,OAAO,SAAS;EAClB,MAAM,IAAI,OAAO;EACjB,MAAM,aAAa,EAAE,iBAAiB,IAClC,IAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,oBAAqB,IAAA,CAAK,QAAQ,CAAC,EAAE,KACnF;EACJ,MAAM,KACJ,YAAY,QAAQ,eAAe,GACnC,YAAY,QAAQ,aAAa,CAAC,CAC/B,QAAQ,aAAa,WAAW,EAAE,cAAc,CAAC,CAAC,CAClD,QAAQ,eAAe,WAAW,EAAE,gBAAgB,CAAC,CAAC,CACtD,QAAQ,UAAU,WAAW,EAAE,WAAW,CAAC,GAC9C,YAAY,QAAQ,SAAS,CAAC,CAC3B,QAAQ,SAAS,IAAI,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,CAAC,CAC9E,QAAQ,SAAS,UAAU,GAC9B,IACA,YAAY,QAAQ,eAAe,GACnC,YAAY,QAAQ,cAAc,CAAC,CAChC,QAAQ,UAAU,WAAW,EAAE,SAAS,IAAI,CAAC,CAAC,CAC9C,QAAQ,SAAS,WAAW,EAAE,SAAS,GAAG,CAAC,CAAC,CAC5C,QAAQ,UAAU,EAAE,SAAS,WAAW,YAAY,QAAQ,iBAAiB,IAAI,EAAE,GACtF,YAAY,QAAQ,eAAe,CAAC,CACjC,QAAQ,SAAS,IAAI,EAAE,SAAS,MAAM,EAAE,SAAS,GAAG,CAAC,CAAC,CACtD,QAAQ,UAAU,WAAW,EAAE,SAAS,OAAO,CAAC,GACnD,YAAY,QAAQ,YAAY,CAAC,CAC9B,QAAQ,UAAU,WAAW,EAAE,OAAO,IAAI,CAAC,CAAC,CAC5C,QAAQ,SAAS,WAAW,EAAE,OAAO,GAAG,CAAC,CAAC,CAC1C,QAAQ,UAAU,EAAE,OAAO,WAAW,YAAY,QAAQ,iBAAiB,IAAI,EAAE,GACpF,YAAY,QAAQ,eAAe,CAAC,CACjC,QAAQ,SAAS,IAAI,EAAE,OAAO,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,CAClD,QAAQ,UAAU,WAAW,EAAE,OAAO,OAAO,CAAC,GACjD,EACF;CACF;CAEA,IAAI,OAAO,SAAS,SAAS,GAC3B,MAAM,KAAK,YAAY,QAAQ,iBAAiB,CAAC,CAAC,QAAQ,UAAU,OAAO,SAAS,KAAK,IAAI,CAAC,GAAG,EAAE;CAErG,IAAI,CAAC,OAAO,WAAW,CAAC,OAAO,SAAS,CAAC,OAAO,SAC9C,MAAM,KAAK,YAAY,QAAQ,QAAQ,GAAG,EAAE;CAG9C,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,QAAQ;AAClC;;AAGA,SAAgB,kBACd,MACmB;CACnB,MAAM,EAAE,YAAY;CACpB,OAAO;EACL,MAAM;EACN,aAAa;EACb,OAAO,EAAE,MAAM,WAAW;EAC1B,SAAS,YAAY;GACnB,MAAM,SAAmB,KAAK,YAAY,KAAK;GAC/C,IAAI;IACF,IAAI,KAAK,YAAY,KAAA,GAAW;KAC9B,MAAM,EAAE,aAAa,MAAM,KAAK,QAAQ;KASxC,OAAO;MAAE,MAAM;MAAW,MART,SAAS,KAAK,UAAU;OACvC,MAAM,SAAS,GAAG,MAAM,SAAS,YAAY,QAAQ,aAAa,IAAI,KAAK,UAAU,OAAO,MAAM;OAClG,MAAM,QAAQ,YAAY,QAAQ,cAAc,CAAC,CAC9C,QAAQ,WAAW,MAAM,KAAK,CAAC,CAC/B,QAAQ,YAAY,MAAM;OAC7B,IAAI,CAAC,MAAM,YAAY,OAAO,GAAG,MAAM,MAAM,YAAY,QAAQ,cAAc;OAC/E,OAAO,aAAa,MAAM,QAAQ,QAAQ,KAAK;MACjD,CACuC,CAAC,CAAC,KAAK,OAAO,YAAY,QAAQ,kBAAkB,EAAE,KAAK;KAAE;IACtG;IAEA,OAAO;KAAE,MAAM;KAAW,MAAM,aAAa,MADxB,QAAQ,SAAS,GACe,MAAM;IAAE;GAC/D,SAAS,OAAgB;IACvB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;IACrE,OAAO;KACL,MAAM;KACN,MAAM,YAAY,QAAQ,WAAW,CAAC,CAAC,QAAQ,aAAa,OAAO;IACrE;GACF;EACF;CACF;AACF;;AAGA,SAAgB,cACd,KACA,MACM;CACN,IAAI,SAAS,SAAS,kBAAkB,IAAI,CAAC;AAC/C;;;;AC7LA,MAAa,uBAAuB;;AAGpC,MAAa,wBAAwB;;AAGrC,SAASA,SAAO,OAAsB;CACpC,MAAM,IAAI,UAAU,sCAAsC,OAAO;AACnE;;AAGA,SAAS,YAAY,QAAiC,KAAa,OAAuB;CACxF,MAAM,QAAQ,OAAO;CACrB,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GAAG,SAAO,KAAK;CACtE,OAAO;AACT;;AAGA,SAAS,YAAY,QAAiC,KAAa,OAAuB;CACxF,MAAM,QAAQ,OAAO;CACrB,IAAI,OAAO,UAAU,UAAU,SAAO,KAAK;CAC3C,OAAO;AACT;;AAGA,SAAS,aAAa,QAAiC,KAAa,OAAwB;CAC1F,MAAM,QAAQ,OAAO;CACrB,IAAI,OAAO,UAAU,WAAW,SAAO,KAAK;CAC5C,OAAO;AACT;;AAGA,SAAS,OAAO,OAAgB,OAAwC;CACtE,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG,SAAO,KAAK;CACrF,OAAO;AACT;;AAGA,SAAS,YAAY,OAAgB,OAAkF;CACrH,MAAM,SAAS,OAAO,OAAO,KAAK;CAClC,OAAO;EACL,MAAM,YAAY,QAAQ,QAAQ,GAAG,MAAM,MAAM;EACjD,KAAK,YAAY,QAAQ,OAAO,GAAG,MAAM,KAAK;EAC9C,UAAU,aAAa,QAAQ,YAAY,GAAG,MAAM,UAAU;EAC9D,SAAS,YAAY,QAAQ,WAAW,GAAG,MAAM,SAAS;CAC5D;AACF;;;;;;AAOA,SAAS,iBAAiB,OAAwC;CAChE,MAAM,SAAS,OAAO,OAAO,QAAQ;CACrC,MAAM,WAAW,OAAO;CACxB,IAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,MAAM,UAAU,OAAO,UAAU,QAAQ,GAAG,SAAO,UAAU;CACtG,MAAM,SAAiC,EAAY,SAAqB;CAExE,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,MAAM,UAAU,OAAO;EACvB,IAAI,YAAY,iBAAiB,YAAY,yBAAyB,YAAY,WAAW,SAAO,SAAS;EAC7G,OAAO,UAAU;CACnB;CAEA,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,MAAM,UAAU,OAAO,OAAO,SAAS,SAAS;EAChD,OAAO,UAAU;GACf,IAAI,YAAY,SAAS,MAAM,YAAY;GAC3C,MAAM,YAAY,SAAS,QAAQ,cAAc;GACjD,UAAU,YAAY,SAAS,YAAY,kBAAkB;EAC/D;CACF;CAEA,IAAI,OAAO,UAAU,KAAA,GAAW;EAC9B,MAAM,QAAQ,OAAO,OAAO,OAAO,OAAO;EAC1C,OAAO,QAAQ;GACb,YAAY,YAAY,OAAO,cAAc,kBAAkB;GAC/D,WAAW,YAAY,OAAO,aAAa,iBAAiB;GAC5D,aAAa,YAAY,OAAO,eAAe,mBAAmB;GAClE,gBAAgB,YAAY,OAAO,kBAAkB,sBAAsB;GAC3E,aAAa,YAAY,OAAO,eAAe,mBAAmB;GAClE,eAAe,YAAY,OAAO,iBAAiB,qBAAqB;GACxE,gBAAgB,YAAY,OAAO,kBAAkB,sBAAsB;GAC3E,cAAc,YAAY,OAAO,gBAAgB,oBAAoB;GACrE,aAAa,YAAY,OAAO,eAAe,mBAAmB;EACpE;CACF;CAEA,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,MAAM,UAAU,OAAO,OAAO,SAAS,SAAS;EAChD,OAAO,UAAU;GACf,gBAAgB,YAAY,SAAS,kBAAkB,wBAAwB;GAC/E,kBAAkB,YAAY,SAAS,oBAAoB,0BAA0B;GACrF,aAAa,YAAY,SAAS,eAAe,qBAAqB;GACtE,UAAU,YAAY,QAAQ,UAAU,kBAAkB;GAC1D,QAAQ,YAAY,QAAQ,QAAQ,gBAAgB;EACtD;CACF;CAEA,IAAI,OAAO,SAAS,KAAA,GAAW;EAC7B,MAAM,OAAO,OAAO,OAAO,MAAM,MAAM;EACvC,MAAM,UAAU,KAAK;EACrB,IAAI,YAAY,SAAS,OAAO,YAAY,YAAY,CAAC,OAAO,SAAS,OAAO,IAAI,SAAO,qBAAqB;EAChH,OAAO,OAAO;GACZ,QAAQ,YAAY,MAAM,UAAU,aAAa;GACjD,MAAM,YAAY,MAAM,QAAQ,WAAW;GAC3C,QAAQ,YAAY,MAAM,UAAU,aAAa;GACjD,gBAAgB;GAChB,kBAAkB,YAAY,MAAM,oBAAoB,uBAAuB;EACjF;CACF;CAEA,OAAO;AACT;;AAGA,SAAS,kBAAkB,OAAyC;CAClE,MAAM,SAAS,OAAO,OAAO,SAAS;CACtC,OAAO;EACL,IAAI,YAAY,QAAQ,MAAM,YAAY;EAC1C,OAAO,YAAY,QAAQ,SAAS,eAAe;EACnD,YAAY,aAAa,QAAQ,cAAc,oBAAoB;EACnE,QAAQ,aAAa,QAAQ,UAAU,gBAAgB;EACvD,MAAM,YAAY,QAAQ,QAAQ,cAAc;EAChD,eAAe,YAAY,QAAQ,iBAAiB,uBAAuB;EAC3E,QAAQ,iBAAiB,OAAO,MAAM;CACxC;AACF;;AAGA,SAAS,oBAAoB,OAA2C;CAEtE,MAAM,WADS,OAAO,OAAO,QACP,CAAC,CAAC;CACxB,IAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG,SAAO,UAAU;CAC/C,OAAO,EAAE,UAAU,SAAS,IAAI,iBAAiB,EAAE;AACrD;;;;;;AAOA,MAAa,oBAA6D,EACxE,OAAO,oBACT;;AAsBA,MAAa,0BAA0B;CACrC,SAAS;CACT,MAAM;CACN,SAAS,CAAC;CAKV,OAAO;EAAE,UAAU,CAAC;EAAG,QAAQ,CAAC;EAAG,SAAS,CAAC;CAAE;CAC/C,aAAa,CAAC;EAvBd,IAAI,GAAG,qBAAqB,GAAG;EAC/B,SAAS;EACT,WAAW;EACX,QAAQ;EACR,YAAY,EAAE,MAAM,SAAS;EAC7B,YAAY,CAAC;EACb,QAAQ;GACN,MAAM;GACN,YAAY,GAAG,qBAAqB;GACpC,QAAQ;EACV;CAac,CAAuB;AACvC;;AA0BA,MAAa,kBAAkB;;AAG/B,SAAS,kBAAkB,OAAyC;CAClE,MAAM,SAAS,OAAO,OAAO,OAAO;CACpC,OAAO;EACL,IAAI,YAAY,QAAQ,MAAM,UAAU;EACxC,MAAM,YAAY,QAAQ,QAAQ,YAAY;CAChD;AACF;;AAGA,SAAS,aAAa,OAAoC;CAExD,MAAM,SADS,OAAO,OAAO,QACT,CAAC,CAAC;CACtB,IAAI,CAAC,MAAM,QAAQ,MAAM,GAAG,SAAO,QAAQ;CAC3C,OAAO,EAAE,QAAQ,OAAO,IAAI,iBAAiB,EAAE;AACjD;;;;;AAWA,MAAa,oBAA0C;CACrD,IAAI,GAAG,qBAAqB,GAAG;CAC/B,SAAS;CACT,WAAW;CACX,QAAQ;CACR,YAAY,EAAE,MAAM,SAAS;CAC7B,YAAY,CAAC;CACb,QAAQ;EACN,MAAM;EACN,YAAY,GAAG,qBAAqB;EACpC,QAAQ,EAjBV,OAAO,aAiBG;CACV;AACF;;;;ACxOA,MAAa,uBAAuB;AACpC,MAAa,wBAAwB;AACrC,MAAa,wBAAwB;AAErC,MAAM,UAAoD;CACxD;CAAU;CAAW;CAAe;CAAW;CAAe;CAAa;AAC7E;;AAGA,SAAS,OAAO,OAAsB;CACpC,MAAM,IAAI,UAAU,qCAAqC,OAAO;AAClE;;;;;;AAOA,SAAgB,iBAAiB,OAAwC;CACvE,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG,OAAO,QAAQ;CACxF,MAAM,SAAS;CACf,MAAM,QAAQ,OAAO;CACrB,IAAI,UAAU,UAAU,UAAU,aAAa,UAAU,aAAa,UAAU,UAC9E,OAAO,OAAO;CAEhB,MAAM,SAAiC,EAAE,MAAM;CAC/C,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,IAAI,OAAO,OAAO,YAAY,UAAU,OAAO,SAAS;EACxD,OAAO,UAAU,OAAO;CAC1B;CACA,IAAI,OAAO,aAAa,KAAA,GAAW;EACjC,IAAI,OAAO,OAAO,aAAa,UAAU,OAAO,UAAU;EAC1D,OAAO,WAAW,OAAO;CAC3B;CACA,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,IAAI,OAAO,OAAO,YAAY,UAAU,OAAO,SAAS;EACxD,OAAO,UAAU,OAAO;CAC1B;CACA,IAAI,OAAO,WAAW,KAAA,GAAW;EAC/B,IAAI,CAAC,QAAQ,SAAS,OAAO,MAAuC,GAAG,OAAO,QAAQ;EACtF,OAAO,SAAS,OAAO;CACzB;CACA,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,IAAI,OAAO,OAAO,YAAY,UAAU,OAAO,SAAS;EACxD,OAAO,UAAU,OAAO;CAC1B;CACA,OAAO;AACT;;AAGA,MAAa,oBAA0D,EACrE,OAAO,iBACT;;AAGA,SAAS,gBAAgB,UAAkB,QAAsC;CAC/E,OAAO;EACL,IAAI,GAAG,qBAAqB,GAAG;EAC/B,SAAS;EACT,WAAW;EACX;EACA,YAAY,EAAE,MAAM,SAAS;EAC7B,YAAY,CAAC;EACb,QAAQ;GACN,MAAM;GACN,YAAY,GAAG,qBAAqB;GACpC,QAAQ;EACV;CACF;AACF;;AAGA,MAAa,oBAAqD;CAChE,gBAAgB,sBAAsB,YAAY;CAClD,gBAAgB,uBAAuB,aAAa;CACpD,gBAAgB,uBAAuB,aAAa;AACtD;;;;;;;;;;ACxDA,IAAa,0BAAb,cACU,oBAAoB;CAC5B;CAEA,YAAY,KAAc,MAA+B;EACvD,MAAM,KAAK,oBAAoB,EAAE,WAAW,cAAc,CAAC;EAC3D,KAAK,OAAO;CACd;;;;;;;;;CAUA,MAAM,SAA6C;EACjD,IAAI,KAAK,KAAK,YAAY,KAAA,GAAW,OAAO,KAAK,KAAK,QAAQ;EAE9D,OAAO,EACL,UAAU,CAAC;GACT,IAAI;GACJ,OAAO;GACP,YAAY;GACZ,QAAQ;GACR,MAAM;GACN,eAAe;GACf,QAAA,MATiB,KAAK,KAAK,QAAQ,SAAS;EAU9C,CAAC,EACH;CACF;;;;;;;CAQA,MAAM,SAAsC;EAC1C,OAAO,KAAK,KAAK,aAAa,KAAK,EAAE,QAAQ,CAAC,EAAE;CAClD;;;;;;;CAQA,MAAM,aAA8C;EAElD,OADc,KAAK,aACR,CAAC,CAAC,MAAM;CACrB;;CAGA,MAAM,cAA+C;EACnD,OAAO,KAAK,KAAK,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO;CACtD;;CAGA,MAAM,cAA+C;EACnD,KAAK,KAAK,OAAO,OAAO;EACxB,OAAO,KAAK,KAAK,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO;CACtD;CAEA,eAAwC;EACtC,MAAM,QAAQ,KAAK,KAAK;EACxB,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,kEAAkE;EAEpF,OAAO;CACT;AACF;;;;;;AAOA,SAAgB,iBACd,KACA,MACM;CACN,IAAI,OAAO,CAAC,QAAQ,IAAI,cAAc;EACpC,IAAI,wBAAwB,WAAW,IAAI;EAM3C,MAAM,aALW,UAAU,OAKC,SAAS;GACnC,GAAG;GACH,aAAa;IAAC,GAAG,wBAAwB;IAAa;IAAmB,GAAG;GAAiB;EAC/F,CAAC;EAGD,UAAU,mBAAmB,KAAK,WAAW,GAAG,wCAAwC;CAC1F,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3IA,MAAa,mBAAmB;;AAGhC,MAAa,mBAAmB;;AAGhC,MAAa,0BAA0B;;AAGvC,MAAa,yBAAyB;;AAGtC,MAAa,wBAA2C;CACtD;CACA;CACA;AACF;;AAGA,MAAM,mBAAmB;;AAyCzB,SAAgB,oBAAoB,SAAsE;CACxG,MAAM,WAAW,oBAAoB,QAAQ,KAAK;CAClD,OAAO,GAAG,QAAQ,aAAa,iBAAiB,YAAY,mBAAmB,QAAQ,EAAE,SAAS,mBAAmB,QAAQ,KAAK;AACpI;;AAGA,SAAgB,qBAAqB,SAAyB;CAC5D,IAAI,2CAA2C,KAAK,OAAO,GAAG,OAAO;CACrE,IAAI,+BAA+B,KAAK,OAAO,GAAG,OAAO;CACzD,OAAO;AACT;;;;;;AAOA,eAAsB,sBACpB,WACA,SACA,QAC2B;CAC3B,IAAI;EACF,MAAM,WAAW,MAAM,UAAU,GAAG,QAAQ,gBAAgB;GAC1D,QAAQ;GACR,SAAS;IAAE,gBAAgB;IAAoB,eAAe,UAAU;GAAS;EACnF,CAAC;EACD,IAAI,SAAS,WAAW,KAAK,OAAO;GAAE,OAAO;GAAO,OAAO;EAAc;EACzE,IAAI,SAAS,IAAI,OAAO,EAAE,OAAO,KAAK;EACtC,OAAO;GAAE,OAAO;GAAO,OAAO;EAAe;CAC/C,QAAQ;EACN,OAAO;GAAE,OAAO;GAAO,OAAO;EAAgB;CAChD;AACF;;AAGA,SAAS,mBAAmB,MAAgC;CAC1D,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,QAAQC,eAAgB;EAC9B,MAAM,KAAK,eAAe,QAAQ,KAAK,CAAC;EACxC,MAAM,KAAK,mBAAmB,MAAM,YAAY,QAAQ,IAAI,CAAC,CAAC;EAC9D,MAAM,OAAO,MAAM,WAAW;CAChC,CAAC;AACH;;AAGA,SAAS,sBAAsB,OAAgF;CAC7G,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,SAAS;CACf,OAAO,OAAO,OAAO,WAAW,YAAY,OAAO,WAAW,MACzD,OAAO,OAAO,UAAU,YACxB,OAAO,OAAO,WAAW,YACzB,OAAO,OAAO,aAAa,YAC3B,OAAO,OAAO,YAAY;AACjC;;;;;;AAOA,IAAa,uBAAb,MAAkC;CAChC;CACA,4BAA6B,IAAI,IAAgB;CAEjD,cAA8C,EAAE,OAAO,OAAO;CAC9D;CACA;;CAEA;CAIA,WAAmB;CAEnB,YAAY,MAAgC;EAC1C,KAAK,OAAO;CACd;;CAGA,SAAS,UAAkC;EACzC,KAAK,UAAU,IAAI,QAAQ;EAC3B,aAAa,KAAK,UAAU,OAAO,QAAQ;CAC7C;;CAGA,SAAiC;EAC/B,OAAO,KAAK;CACd;;;;;;CAOA,MAAM,QAAyC;EAC7C,IAAI,KAAK,UAAU,MAAM,IAAI,MAAM,8BAA8B;EACjE,IAAI,KAAK,YAAY,UAAU,WAAW,OAAO,KAAK;EACtD,KAAK,SAAS;EAEd,MAAM,OAAO,MAAM,KAAK,SAAS;EACjC,MAAM,gBAAgB,KAAK,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,CAAC,CAAC,SAAS,WAAW;EAIzF,MAAM,UAAU,IAAI,SAAsC,SAAS,WAAW;GAC5E,KAAK,SAAS;IAAE;IAAS;GAAO;EAClC,CAAC;EAED,MAAM,KAAK,WAAW,MAAM,aAAa;EAEzC,MAAM,UAAU,KAAK,YAAY;EACjC,KAAK,UAAU;GACb,OAAO;GACP,SAAS,oBAAoB;IAAE,YAAY,qBAAqB,OAAO;IAAG;IAAM,OAAO;GAAc,CAAC;EACxG,CAAC;EAGD,KAAK,QAAQ,iBAAiB;GAC5B,KAAK,SAAS;GACd,KAAK,UAAU;IACb,OAAO;IACP,QAAQ;IACR,SAAS;GACX,CAAC;EACH,GAAG,KAAK,KAAK,aAAA,IAA6B;EAC1C,KAAK,MAAM,QAAQ;EAEnB,QAAa,MACV,gBAAgB,KAAK,SAAS,WAAW,IACzC,YAAY,KAAK,SAAS,OAAO,CACpC;EACA,OAAO,KAAK;CACd;;CAGA,SAAe;EACb,IAAI,KAAK,YAAY,KAAK,YAAY,UAAU,WAAW;EAC3D,KAAK,SAAS;EACd,KAAK,UAAU;GAAE,OAAO;GAAU,QAAQ;EAAY,CAAC;CACzD;;CAGA,UAAgB;EACd,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW;EAChB,MAAM,aAAa,KAAK,YAAY,UAAU;EAC9C,KAAK,SAAS;EACd,IAAI,YAAY,KAAK,UAAU;GAAE,OAAO;GAAU,QAAQ;EAAY,CAAC;CACzE;CAMA,cAA8B;EAE5B,QADY,OAAO,KAAK,KAAK,YAAY,aAAa,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,YAAA;CAExF;CAEA,UAAkB,MAAoC;EACpD,KAAK,cAAc;EACnB,KAAK,MAAM,YAAY,CAAC,GAAG,KAAK,SAAS,GAAG,SAAS;CACvD;;CAGA,MAAc,WAA4B;EACxC,MAAM,YAAY,KAAK,KAAK,aAAA;EAC5B,MAAM,WAAW,KAAK,KAAK,mBAAA;EAC3B,KAAK,IAAI,QAAQ,GAAG,QAAQ,UAAU,SAAS,GAAG;GAChD,MAAM,YAAY,YAAY;GAC9B,IAAI,MAAM,mBAAmB,SAAS,GAAG,OAAO;EAClD;EACA,MAAM,IAAI,MAAM,iCAAiC,SAAS,+BAA+B,WAAW;CACtG;;;;;;CAOA,WAAmB,MAAc,eAAsC;EACrE,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,IAAI,UAAU;GACd,MAAM,SAASC,cAAkB,SAAS,aAAa,KAAK,eAAe,SAAS,UAAU,aAAa,CAAC;GAC5G,KAAK,SAAS;GACd,OAAO,KAAK,UAAU,UAAiC;IACrD,IAAI,KAAK,WAAW,QAAQ;IAC5B,KAAK,SAAS,KAAA;IACd,MAAM,SAAS,IAAI,iBACjB,SACA,oDAAoD,KAAK,IAAI,MAAM,QAAQ,MAAM,SACnF;IACA,IAAI,SAAS;KACX,UAAU;KACV,OAAO,MAAM;IACf,OACE,KAAK,QAAQ,OAAO,MAAM;GAE9B,CAAC;GACD,OAAO,OAAO,MAAM,mBAAmB;IACrC,IAAI,CAAC,SAAS;IACd,UAAU;IACV,QAAQ;GACV,CAAC;EACH,CAAC;CACH;;CAGA,eAAuB,SAA0B,UAA0B,eAA6B;EAItG,SAAS,UAAU,cAAc,OAAO;EACxC,SAAS,UAAU,+BAA+B,WAAW,QAAQ,QAAQ,MAAM,CAAC;EACpF,SAAS,UAAU,gCAAgC,eAAe;EAClE,SAAS,UAAU,gCAAgC,cAAc;EACjE,SAAS,UAAU,gBAAgB,kBAAkB;EACrD,MAAM,QAAQ,MAAc,SAAkC;GAC5D,SAAS,UAAU,IAAI;GACvB,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;EACnC;EACA,IAAI,QAAQ,WAAW,WAAW;GAChC,SAAS,UAAU,GAAG;GACtB,SAAS,IAAI;GACb;EACF;EAEA,KADa,QAAQ,KAAK,MAAM,GAAG,CAAC,CAAC,MAAM,SAC9B,aAAa;GACxB,KAAK,KAAK;IAAE,SAAS;IAAO,OAAO;GAAY,CAAC;GAChD;EACF;EACA,IAAI,QAAQ,WAAW,QAAQ;GAC7B,KAAK,KAAK;IAAE,SAAS;IAAO,OAAO;GAAgC,CAAC;GACpE;EACF;EACA,IAAI,OAAO;EACX,QAAQ,GAAG,SAAS,UAAkB;GACpC,QAAQ,MAAM,SAAS;GACvB,IAAI,KAAK,SAAA,KAAiC,QAAQ,QAAQ;EAC5D,CAAC;EACD,QAAQ,GAAG,aAAa;GACtB,IAAI;GACJ,IAAI;IACF,UAAU,KAAK,MAAM,IAAI;GAC3B,QAAQ;IACN,KAAK,KAAK;KAAE,SAAS;KAAO,OAAO;IAAe,CAAC;IACnD;GACF;GAEA,IAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,WAAW,SAAS;IACzE,MAAM,SAAS;IACf,MAAM,cAAc,OAAO,qBAAqB,OAAO;IACvD,KAAK,cAAc,MAAM,KAAK,EAAE,SAAS,KAAK,GAAG,IAAI,iBACnD,OAAO,UAAU,kBAAkB,WAAW,SAC9C,OAAO,gBAAgB,YAAY,gBAAgB,KAAK,cAAc,sBACxE,CAAC;IACD;GACF;GACA,IAAI,CAAC,sBAAsB,OAAO,GAAG;IACnC,KAAK,KAAK;KAAE,SAAS;KAAO,OAAO;IAA0B,CAAC;IAC9D;GACF;GACA,IAAI,QAAQ,UAAU,eAAe;IAGnC,KAAK,KAAK;KAAE,SAAS;KAAO,OAAO;IAAsB,CAAC;IAC1D;GACF;GACA,KAAK,cAAc,MAAM,KAAK,EAAE,SAAS,KAAK,GAAG,KAAA,GAAW,EAAE,GAAG,QAAQ,CAAC;EAC5E,CAAC;EACD,QAAQ,GAAG,eAAe,CAAC,CAAC;CAC9B;;CAGA,cACE,MACA,MACA,MACA,SACA,aACM;EACN,KAAK,MAAM,IAAI;EAEf,MAAM,SAAS,KAAK;EACpB,KAAK,SAAS;EACd,IAAI,WAAW,KAAA,GAAW;EAC1B,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO,OAAO;OAC3C,IAAI,gBAAgB,KAAA,GAAW,OAAO,QAAQ,WAAW;CAChE;;CAGA,MAAc,SAAS,aAAyD;EAC9E,IAAI,KAAK,YAAY,KAAK,YAAY,UAAU,WAAW;EAC3D,MAAM,aAAa,MAAM,sBACvB,KAAK,KAAK,aAAa,OACvB,KAAK,YAAY,GACjB,YAAY,MACd;EACA,IAAI,CAAC,WAAW,OAAO;GACrB,MAAM,SAAwC,WAAW,UAAU,gBAC/D,gBACA,WAAW,UAAU,kBAAkB,YAAY;GACvD,KAAK,UAAU;IACb,OAAO;IACP;IACA,SAAS,6CAA6C,WAAW,MAAM;GACzE,CAAC;GACD;EACF;EACA,IAAI;GACF,MAAM,KAAK,KAAK,SAAS,WAAW;EACtC,SAAS,OAAgB;GACvB,KAAK,UAAU;IACb,OAAO;IACP,QAAQ;IACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAChE,CAAC;GACD;EACF;EACA,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW;EAChB,KAAK,UAAU;GAAE,OAAO;GAAW,UAAU,YAAY;GAAU,SAAS,YAAY;EAAQ,CAAC;CACnG;;CAGA,SAAiB,SAAwB;EACvC,IAAI,EAAE,mBAAmB,mBAAmB;EAC5C,IAAI,KAAK,YAAY,KAAK,YAAY,UAAU,WAAW;EAC3D,KAAK,UAAU;GAAE,OAAO;GAAU,QAAQ,QAAQ;GAAQ,SAAS,QAAQ;EAAQ,CAAC;CACtF;CAEA,aAA2B;EACzB,IAAI,KAAK,UAAU,KAAA,GAAW;GAC5B,aAAa,KAAK,KAAK;GACvB,KAAK,QAAQ,KAAA;EACf;CACF;;CAGA,WAAyB;EACvB,KAAK,WAAW;EAChB,KAAK,QAAQ,MAAM;EACnB,KAAK,SAAS,KAAA;EACd,KAAK,SAAS,KAAA;CAChB;AACF;;AAGA,IAAM,mBAAN,cAA+B,MAAM;CACP;CAA5B,YAAY,QAAuD,SAAiB;EAClF,MAAM,OAAO;EADa,KAAA,SAAA;EAE1B,KAAK,OAAO;CACd;AACF;;AAGA,SAAS,WAAW,QAAoC;CACtD,OAAO,WAAW,KAAA,KAAa,sBAAsB,SAAS,MAAM,IAAI,SAAS;AACnF;;;;;;;;;;;;;;;;;;;;;;AClbA,MAAa,iCAAiC;;;;;;;AAQ9C,MAAa,iCAAiC;;;;;;AAyB9C,SAAgB,gCAAgC,KAAiB,QAAqC;CACpG,MAAM,QAAQ;CACd,MAAM,QAAQ,MAAM;CACpB,MAAM,mBAAmB,SAAS,iCAAiC;CACnE,OAAO;AACT;;AAGA,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;;AAExB,MAAM,sBAAsB;;AAG5B,MAAM,eAAe;;;;;AAgBrB,SAAS,gBAAgB,YAAwC;CAC/D,OAAO,eAAe,KAAA,IAClB,sBACA,KAAK,IAAI,iBAAiB,KAAK,IAAI,iBAAiB,KAAK,MAAM,UAAU,CAAC,CAAC;AACjF;;AAGA,SAAS,SAAS,QAAyF;CACzG,MAAM,MAAM,OAAO,KAAK,KAAK;CAC7B,IAAI,QAAQ,KAAA,KAAa,IAAI,WAAW,GAAG,OAAO,KAAA;CAClD,MAAM,QAAQ,OAAO,OAAO,KAAK;CACjC,MAAM,UAAU,OAAO,SAAS,KAAK;CACrC,OAAO;EACL;EACA,GAAG,UAAU,KAAA,KAAa,MAAM,SAAS,IAAI,EAAE,MAAM,IAAI,CAAC;EAC1D,GAAG,YAAY,KAAA,KAAa,QAAQ,SAAS,IAAI,EAAE,QAAQ,IAAI,CAAC;CAClE;AACF;AAEA,SAAS,aAAa,OAAyB;CAC7C,OAAO,iBAAiB,gBAAgB,MAAM,SAAS;AACzD;;AAGA,SAAS,cAAc,QAAiC,UAA6B;CACnF,OAAO,IAAI,SAAS,mCAAmC,eAAe,EACpE,OAAO,QAAQ,YAAY,OAAO,OAAO,SAAS,SACpD,CAAC;AACH;AAEA,SAAS,eAAe,QAAuC;CAC7D,IAAI,QAAQ,YAAY,MAAM,MAAM,cAAc,QAAQ,KAAA,CAAS;AACrE;;;;;;;;AASA,IAAa,4BAAb,MAAoE;CAGrC;CAF7B,KAAc;CAEd,YAAY,MAAsD;EAArC,KAAA,OAAA;CAAsC;;CAGnE,YAAqB;EACnB,MAAM,OAAO,KAAK,KAAK,QAAQ;EAC/B,OAAO,KAAK,SAAS,KAAK,IAAI,SAAS,IAAI;CAC7C;CAEA,MAAM,OAAO,SAA2B,QAAgD;EACtF,eAAe,MAAM;EACrB,MAAM,UAAU,KAAK,KAAK,QAAQ;EAClC,IAAI,CAAC,IAAI,SAAS,OAAO,GACvB,MAAM,IAAI,SACR,qDAAqD,KAAK,UAAU,OAAO,EAAE,sBAC7E,oBACF;EAEF,MAAM,MAAM,MAAM,KAAK,WAAW,MAAM;EACxC,eAAe,MAAM;EACrB,MAAM,WAAW,GAAG,QAAQ,QAAQ,OAAO,EAAE,IAAI;EAEjD,MAAM,OAAO;GACX,OAAO,QAAQ;GACf,YAAY,gBAAgB,QAAQ,UAAU;EAChD;EAEA,IAAI;EACJ,IAAI;GACF,WAAW,OAAO,KAAK,KAAK,aAAa,MAAA,CAAO,UAAU;IACxD,QAAQ;IACR,SAAS;KACP,gBAAgB;KAChB,eAAe,UAAU;KACzB,0BAA0B;KAC1B,qBAAqB;KACrB,GAAG,mBAAmB;IACxB;IACA,MAAM,KAAK,UAAU,IAAI;IACzB,GAAG,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;GAC1C,CAAC;EACH,SAAS,OAAgB;GACvB,IAAI,QAAQ,YAAY,QAAQ,aAAa,KAAK,GAAG,MAAM,cAAc,QAAQ,KAAK;GACtF,MAAM,IAAI,SACR,2CAA2C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KAChG,sBACA,EAAE,OAAO,MAAM,CACjB;EACF;EAEA,IAAI,CAAC,SAAS,IAAI;GAChB,IAAI,UAAU,wCAAwC,SAAS,OAAO;GACtE,IAAI;IACF,MAAM,SAAkB,MAAM,SAAS,KAAK;IAC5C,MAAM,SAAS,OAAO,WAAW,YAAY,WAAW,OACnD,QAAgC,QACjC,KAAA;IACJ,IAAI,OAAO,WAAW,YAAY,OAAO,SAAS,GAAG,WAAW,KAAK;SAChE,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM;KACtD,MAAM,OAAQ,QAA+B;KAC7C,MAAM,QAAS,QAAkC;KACjD,IAAI,OAAO,SAAS,YAAY,OAAO,UAAU,UAC/C,WAAW,KAAK,OAAO,SAAS,WAAW,OAAO,KAAK,OAAO,SAAS,YAAY,OAAO,UAAU,WAAW,QAAQ,KAAK,OAAO,UAAU,WAAW,QAAQ;IAEpK;GACF,SAAS,OAAO;IACd,IAAI,QAAQ,YAAY,QAAQ,aAAa,KAAK,GAAG,MAAM,cAAc,QAAQ,KAAK;GACxF;GACA,MAAM,IAAI,SAAS,SAAS,oBAAoB;EAClD;EAEA,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,SAAS,KAAK;EAChC,SAAS,OAAO;GACd,IAAI,QAAQ,YAAY,QAAQ,aAAa,KAAK,GAAG,MAAM,cAAc,QAAQ,KAAK;GACtF,MAAM,IAAI,SAAS,iEAAiE,oBAAoB;EAC1G;EAEA,MAAM,UAAW,SAAmC;EACpD,IAAI,CAAC,MAAM,QAAQ,OAAO,GACxB,MAAM,IAAI,SACR,8FACA,oBACF;EAGF,MAAM,UAA6B,CAAC;EACpC,MAAM,uBAAO,IAAI,IAAY;EAC7B,KAAK,MAAM,QAAQ,SAAS;GAC1B,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM;GAC/C,MAAM,SAAS,SAAS,IAA0D;GAClF,IAAI,WAAW,KAAA,KAAa,KAAK,IAAI,OAAO,GAAG,GAAG;GAClD,KAAK,IAAI,OAAO,GAAG;GACnB,QAAQ,KAAK,MAAM;EACrB;EAEA,OAAO;GAAE;GAAS,WAAW;EAAM;CACrC;CAEA,MAAc,WAAW,QAAkD;EACzE,IAAI;EACJ,IAAI;GACF,MAAM,MAAM,KAAK,KAAK,WAAW;EACnC,SAAS,OAAO;GACd,IAAI,QAAQ,YAAY,QAAQ,aAAa,KAAK,GAAG,MAAM,cAAc,QAAQ,KAAK;GAOtF,IAAI,iBAAiB,SAAS,OAAQ,MAAuB,SAAS,UAAU;IAC9E,MAAM,OAAQ,MAAuB;IACrC,IAAI,SAAS,sBAAsB,MAAM,IAAI,SAAS,MAAM,SAAS,mCAAmC,EAAE,OAAO,MAAM,CAAC;IACxH,IAAI,SAAS,wBAAwB,SAAS,cAC5C,MAAM,IAAI,SAAS,MAAM,SAAS,sBAAsB,EAAE,OAAO,MAAM,CAAC;GAE5E;GACA,MAAM,IAAI,SACR,yDAAyD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KAC9G,sBACA,EAAE,OAAO,MAAM,CACjB;EACF;EACA,IAAI,QAAQ,KAAA,KAAa,IAAI,WAAW,GACtC,MAAM,IAAI,SACR,+PACA,iCACF;EAEF,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/IA,MAAa,OAAO;AACpB,MAAa,SAAS,CAAC,KAAK;AAE5B,MAAM,KAAK;AACX,MAAM,sBAAsB;;AAG5B,MAAa,WAAW;;AAExB,MAAa,4BAA4B,KAAK,QAAQ,GAAG,gBAAgB,mBAAmB;AAoF5F,MAAa,SAAoB,EAAE,OAAO;CACxC,WAAW,EAAE,OAAO,CAAC,CAAC,KAAK,gBAAgB,CAAC,CAAC,QAAQ,mBAAmB;CACxE,QAAQ,EAAE,OAAO;CACjB,SAAS,EAAE,OAAO;CAClB,YAAY,EAAE,OAAO;CACrB,iBAAiB,EAAE,OAAO;CAC1B,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,kBAAkB;CAC1D,qBAAqB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,kBAAkB;CAC7D,oBAAoB,EAAE,QAAQ;CAC9B,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,IAAI;CACnC,UAAU,EAAE,MAAM,EAAE,OAAO;EACzB,OAAO,EAAE,OAAO;EAChB,WAAW,EAAE,OAAO,CAAC,CAAC,KAAK,gBAAgB;EAC3C,QAAQ,EAAE,OAAO;CACnB,CAAC,CAAC;CACF,eAAe,EAAE,OAAO;CACxB,mBAAmB,EAAE,MAAM,EAAE,OAAO;EAClC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;EAC1B,SAAS,EAAE,OAAO;CACpB,CAAC,CAAC;CACF,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,WAAW,CAAC,CAAC,QAAQ,IAAa;AAC7D,CAAC;;;;;;;AAaD,SAAgB,sBAAsB,QAA4C;CAChF,OAAO;EACL,WAAW,cAAc,OAAO,aAAa,mBAAmB;EAChE,SAAS,OAAO,WAAA;EAChB,YAAY,OAAO,cAAc,QAAQ,IAAI;EAC7C,iBAAiB,OAAO,mBAAmB;EAC3C,kBAAkB,OAAO,oBAAA;EACzB,qBAAqB,OAAO,uBAAA;EAC5B,oBAAoB,OAAO,sBAAsB;CACnD;AACF;AAEA,SAAgB,MAAM,KAAc,QAAsB;CACxD,IAAI,gBAA8B;CAClC,IAAI;CACJ,IAAI;CACJ,MAAM,gBAA4C;EAChD,MAAM,MAAM,QAAQ;EACpB,IAAI,QAAQ,WAAW,aAAa,KAAA,GAAW,OAAO;EACtD,MAAM,OAAO,sBAAsB,GAAG;EACtC,UAAU;EACV,WAAW;EACX,OAAO;CACT;CACA,QAAQ;CAMR,MAAM,cAAwC;EAC5C,MAAM,MAAM,QAAQ;EACpB,MAAM,OAAiC,CAAC;GACtC,IAAI;GACJ,OAAO;GACP,KAAK,cAAc,IAAI,aAAa,mBAAmB;GACvD,SAAS,IAAI;GACb,eAAe;EACjB,CAAC;EACD,KAAK,MAAM,CAAC,OAAO,aAAa,IAAI,YAAY,CAAC,EAAA,CAAG,QAAQ,GAAG;GAC7D,MAAM,UAAU,OAAO,QAAQ,cAAc,YAAY,QAAQ,UAAU,KAAK,MAAM,KAClF,QAAQ,UAAU,KAAK,IACvB,KAAA;GACJ,MAAM,UAAU,OAAO,QAAQ,WAAW,YAAY,QAAQ,WAAW,KAAK,QAAQ,SAAS,KAAA;GAC/F,IAAI,YAAY,KAAA,KAAa,YAAY,KAAA,GAAW;GACpD,KAAK,KAAK;IAKR,IAAI,WAAW,WAAW,QAAQ;IAClC,OAAO,OAAO,QAAQ,UAAU,YAAY,QAAQ,MAAM,KAAK,MAAM,KACjE,QAAQ,MAAM,KAAK,IACnB,WAAW,QAAQ;IACvB,KAAK,YAAY,KAAA,IAAY,KAAA,IAAY,cAAc,OAAO;IAC9D;IACA,eAAe;GACjB,CAAC;EACH;EACA,OAAO;CACT;CAIA,MAAM,oBAAwC;EAC5C,MAAM,MAAM,QAAQ,CAAC,CAAC;EACtB,OAAO,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAA;CACrE;CAEA,MAAM,aAAa,OAAO,QAAuE;EAC/F,MAAM,cAAc,IAAI,IAAI,aAAa;EACzC,IAAI,gBAAgB,KAAA,GAElB,QAAO,MADW,YAAY,QAAQ,GAAG,EAAA,EAC7B;EAEd,MAAM,UAAU,oBAAoB,GAAG,CAAC,CAAC,IAAI,GAAG;EAChD,OAAO,YAAY,KAAA,KAAa,QAAQ,MAAM,SAAS,IAAI,QAAQ,QAAQ,KAAA;CAC7E;CAQA,MAAM,OAA+B,IAAI,uBAAuB;EAC9D;EACA;EACA,aAAa;EAGb,cAAc,WAAmB,QAAQ,oBAAoB,MAAM;EACnE;EAGA,yBAAiE,QAAQ,CAAC,CAAC,qBAAqB,CAAC;CACnG,CAAC;CAED,MAAM,gBAAgB,OAAO,YAAwC,UAAoC;EACvG,MAAM,WAAW,MAAM,KAAK,WAAW,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,CAAC;EAC3E,IAAI,aAAa,KAAA,GACf,OAAO,mBAAmB,SAAS,KAAK,mBAAmB,SAAS,KAAK,OAAO,GAAG,SAAS,KAAK,MAAM,iBAAiB;EAE1H,MAAM,MAAM,WAAW;EACvB,MAAM,IAAI,SACR,mDAAmD,SAAS,WAAW,IAAI,+LAI3E,oBACF;CACF;CAEA,MAAM,UAA0D,IAAI,mBAAmB;EACrF;EACA;EAKA,cAAc,OAAO,aAAqB,WAAgD,aAAyC,UAAgD;GACjL,KAAK,aAAa,aAAa,SAAS;GAMxC,MAAM,WAAW,MAAM,KAAK,WAC1B,UAAU,KAAA,IAAY,EAAE,SAAS,YAAY,IAAI;IAAE,SAAS;IAAa;GAAM,CACjF;GAIA,OAAO,aAAa,KAAA,IAChB,KAAA,IACA,mBAAmB,SAAS,KAAK,mBAAmB,SAAS,KAAK,OAAO,GAAG,SAAS,KAAK,MAAM,iBAAiB;EACvH;EAGA,0BAA0B;GACxB,MAAM,cAAc,IAAI,IAAI,aAAa;GACzC,OAAO,gBAAgB,KAAA,IAAY,KAAA,IAAY;EACjD;CACF,CAAC;CAGD,IAAI,IAAI,8BAA8B,CACpC;EAAE,UAAU;EAAU,aAAa;EAAgB,YAAY;EAAI,cAAc,CAAC;CAAE,CACtF,CAAC;CAED,IAAI,IAAI,gBAAgB,CAAC,QAAQ,GAAG,OAAO;CAK3C,MAAM,eAAe,YAAgD;EAInE,MAAM,YAAY,MAAM,KAAK,iBAAiB;EAC9C,MAAM,OAAO,IAAI,IAAI,UAAU,KAAK,YAAY,CAAC,QAAQ,KAAK,IAAI,OAAO,CAAC,CAAC;EAC3E,MAAM,SAAS,oBAAoB,MAAM,KAAK,iBAAiB,GAAG,YAAY,CAAC;EA4B/E,OAAO,EAAE,UAAU,MA3BG,QAAQ,IAAI,MAAM,CAAC,CAAC,IAAI,OAAO,SAAS;GAC5D,MAAM,UAAU,KAAK,IAAI,KAAK,EAAE;GAChC,IAAI;GACJ,IAAI,YAAY,KAAA,GACd,SAAS,EAAE,UAAU,CAAC,EAAE;QAExB,IAAI;IACF,SAAS,MAAM,QAAQ,SAAS,QAAQ,GAAG;GAC7C,SAAS,OAAgB;IACvB,SAAS,EAAE,UAAU,CAAC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;GAChF;GAEF,MAAM,QAAQ,SAAS;GAIvB,MAAM,SAAS,cAAc,KAAK;GAClC,OAAO;IACL,IAAI,KAAK;IACT,OAAO,KAAK;IACZ,YAAY,YAAY,KAAA;IACxB,QAAQ,YAAY,KAAA,KAAa,QAAQ,KAAK,OAAO,KAAK;IAC1D,MAAM,SAAS,KAAK,OAAO,SAAS,aAAa,uBAAuB;IACxE,eAAe,CAAC,UAAU,OAAO,SAAS,aAAa,MAAM,QAAQ;IACrE;GACF;EACF,CAAC,CAAC,EACyB;CAC7B;CAUA,MAAM,sBAAgC,kBAAkB,QAAQ,CAAC,CAAC,IAAI;CACtE,IAAI,OAAO,CAAC,UAAU,IAAI,eAAe;EACvC,cAAc,YAAY;GAAE;GAAS,SAAS;GAAc,WAAW;EAAc,CAAC;CACxF,CAAC;CASD,MAAM,YAAY,IAAI,qBAAqB;EACzC,eAAe,QAAQ,CAAC,CAAC;EACzB,UAAU,OAAO,EAAE,aAAyD;GAC1E,MAAM,MAAM,cAAc,QAAQ,CAAC,CAAC,aAAa,mBAAmB;GACpE,MAAM,cAAc,IAAI,IAAI,aAAa;GACzC,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,gFAAgF;GAElG,MAAM,YAAY,IAAI,KAAK,MAAM;EACnC;CACF,CAAC;CACD,IAAI,mBAAmB,UAAU,QAAQ,GAAG,sCAAsC;CAIlF,MAAM,kBAAkB,YAAyC;EAE/D,OAAO,EACL,SAAQ,MAFW,QAAQ,WAAW,QAAQ,EAAA,CAE/B,KAAK,WAAW;GAAE,IAAI,MAAM;GAAI,MAAM,MAAM,KAAK,QAAQ,cAAc,EAAE;EAAE,EAAE,EAC9F;CACF;CACA,iBAAiB,KAAK;EAAE;EAAS,SAAS;EAAc,OAAO;EAAW,YAAY;CAAgB,CAAC;CAiBvG,IAAI;CACJ,IAAI,OAAO,CAAC,KAAK,IAAI,WAAW;EAC9B,aAAa,OAAO;EACpB,OAAO,IAAI,uBAAuB,IAAI,0BAA0B;GAC9D,YAAY,YAAY;IACtB,MAAM,WAAW,MAAM,KAAK,WAAW;IACvC,OAAO,aAAa,KAAA,IAAY,KAAA,IAAY,SAAS;GACvD;GACA,eAAe,QAAQ,CAAC,CAAC;EAC3B,CAAC,CAAC;EAIF,gCAAgC,OAAO,KAAK,QAAQ,CAAC,CAAC,aAAa,IAAI;CACzE,CAAC;CAKD,IAAI,OAAO,CAAC,UAAU,IAAI,gBAAgB;EACxC,YAAY,SAAS,eAAe,KAAK,IAAI,QAAQ,QAAQ;GAC3D,YAAY,WAAW;IACrB,UAAU;GACZ;GAKA,gBAAgB;IACd,IAAI,eAAe,KAAA,GACjB,gCAAgC,YAAY,QAAQ,CAAC,CAAC,aAAa,IAAI;GAE3E;EACF,CAAC;CACH,CAAC;AACH"}