@mars-sea/dsh-commandcode-provider 0.10.0-alpha.1 → 0.10.0-alpha.2
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/CHANGELOG.md +15 -1
- package/README.md +9 -0
- package/README.zh-CN.md +9 -0
- package/lib/client.js +578 -89
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +91 -12
- package/lib/index.js +120 -27
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["numberField","booleanField","reject","pkg.version","useState","loginFailureCopy","Button","useState"],"sources":["../src/client/snapshot-store.ts","../src/command-locales.ts","../src/client/sessions.ts","../src/client/settings.ts","../src/client/legacy-credentials.ts","../src/client/usage.ts","../src/client/login.ts","../src/usage-wire.ts","../src/login-wire.ts","../package.json","../src/client/version.ts","../src/client/update.ts","../src/client/section.tsx","../src/client/card.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * A tiny observable snapshot store — the `getSnapshot` / `subscribe` / `set`\n * triple React's `useSyncExternalStore` consumes through the harness slot kit\n * (the host builds each slot's `useFoo(selector)` hook from one of these).\n *\n * Vendored on purpose. DSH 0.1.2 seeds `@deepseek-ai/dsh-client-store` as a\n * platform module, but older Web shells do not and the package is not yet\n * published independently on npm. Inlining the small subset used here avoids\n * a version-specific module request while preserving the slot-hook contract.\n */\n\n/** Mutable observable snapshot consumed by slot hooks. */\nexport interface SnapshotStore<T> {\n getSnapshot(): T\n subscribe(listener: () => void): () => void\n set(value: T): void\n}\n\n/** Notify every subscriber without letting one faulty UI consumer suppress the rest. */\nfunction notifyListeners(listeners: ReadonlySet<() => void>): void {\n for (const listener of listeners) {\n try {\n listener()\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] snapshot subscriber failed:', error)\n }\n }\n}\n\n/** Create one observable snapshot store. */\nexport function createSnapshotStore<T>(initial: T): SnapshotStore<T> {\n let snapshot = initial\n const listeners = new Set<() => void>()\n return {\n getSnapshot: () => snapshot,\n subscribe(listener: () => void) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n set(value: T) {\n if (Object.is(value, snapshot)) return\n snapshot = value\n notifyListeners(listeners)\n },\n }\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 * Friendly-error wrapper for the harness's image-session gate.\n *\n * The host rejects switching to a text-only model while the session already\n * contains images with a `model-unavailable` error\n * (`dsh-host-apiproxy`'s `session.selectModel` handler). That rejection is\n * intentional and cannot be relaxed from the plugin side — the adapter's\n * `inputModalities` is exactly what makes the guard work. What we CAN do is\n * make the error message friendlier: wrap the shared\n * `connection.api.sessions.selectModel` face so a `model-unavailable`\n * rejection shows a clear, actionable hint (with the requested model name)\n * instead of the raw English harness message.\n *\n * The wrapper is deliberately narrow: only the `model-unavailable` code is\n * rewritten, only when the message matches the image-session gate, and only\n * the message text changes — the error code and details pass through\n * untouched so any caller that switches on `error.code` keeps working.\n *\n * The wire types are spelled structurally here (not imported from\n * `@deepseek-ai/dsh-host-apiproxy`) so this client bundle does not drag an\n * extra peer dependency into the package; the shapes are stable and the\n * client build inlines them anyway.\n *\n * The wrapper takes a `getLocale` thunk because it is reached from a\n * non-React path that has no `t` in scope; the supplied thunk reads the\n * active locale at call time (typically `() => ctx.locale.getLocale().active`\n * in the client entry), and the message template lives in the shared\n * `commandcodeCommand` dictionary used by the Host-side `/commandcode`\n * command — the same bilingual surface serves both.\n *\n * This module is deliberately free of React and other client-platform\n * imports so the node test runner can exercise it directly.\n */\n\nimport { commandcodeCommand, type LocaleId } from '../command-locales.ts'\n\n/** The `model-unavailable` error details: provider + model id. */\ninterface ModelUnavailableDetails {\n provider: string\n model: string\n}\n\n/** The narrow slice of the RPC error we need to inspect and rewrite. */\ninterface RpcErrorLike {\n code: string\n message: string\n details?: ModelUnavailableDetails\n}\n\n/**\n * The narrow slice of a unary RPC result we need to inspect and rewrite.\n * The wire shape from `sessions.selectModel` (via `AbstractApiClient.callUnary`)\n * is the full envelope `{ rpcId, result: { ok, error? } }` — the error lives\n * under `result.result`, not at the top level. `RpcResultLike` models that.\n */\ninterface RpcResultLike {\n rpcId: string\n result:\n | { ok: true; value?: unknown }\n | { ok: false; error: RpcErrorLike }\n}\n\n/** One selectModel call: payload in, envelope out. */\ntype SelectModelCall = (\n payload: { sessionId: string; provider: string; model: string; reasoningEffort?: string },\n signal?: AbortSignal,\n) => Promise<RpcResultLike>\n\n/** The shared sessions wire face we wrap. */\ninterface SessionsLike {\n selectModel: SelectModelCall\n}\n\n/** Whether a selectModel rejection is the harness's image-session gate. */\nexport function isImageSessionRejection(\n result: RpcResultLike,\n): result is RpcResultLike & { result: { ok: false; error: RpcErrorLike } } {\n return (\n !result.result.ok &&\n result.result.error.code === 'model-unavailable' &&\n result.result.error.message.includes('does not accept image input')\n )\n}\n\n/** Wrap the shared sessions API so selectModel failures read friendlier. */\nexport function withFriendlyImageError(\n sessions: SessionsLike,\n getLocale: () => LocaleId,\n): SessionsLike {\n const selectModel = sessions.selectModel.bind(sessions)\n return {\n ...sessions,\n selectModel: async (payload, signal) => {\n const result = await selectModel(payload, signal)\n if (!isImageSessionRejection(result)) return result\n const model = result.result.error.details?.model ?? payload.model\n const template = commandcodeCommand[getLocale()].imageGate\n ?? commandcodeCommand.en.imageGate\n return {\n ...result,\n result: {\n ...result.result,\n error: {\n ...result.result.error,\n message: template.replace('{model}', model),\n },\n },\n }\n },\n }\n}\n\n/**\n * The pre-0.1.2 connection handle that exposed the shared session API under\n * `connection.api.sessions`. In 0.1.2 the connection service became a\n * transport/generation handle and model selection moved to `remote.session`,\n * so this legacy field is deliberately optional.\n */\nexport interface ConnectionLike {\n api?: { sessions?: SessionsLike }\n}\n\n/**\n * Install the friendly-error wrapper when a legacy sessions face is present.\n *\n * @returns whether the wrapper was installed. The rewrite is only UX polish;\n * a 0.1.2 connection has no `api.sessions`, and its absence must never block\n * the plugin from mounting its settings, credential, or usage surfaces.\n */\nexport function installFriendlyImageError(\n connection: ConnectionLike,\n getLocale: () => LocaleId,\n): boolean {\n const api = connection.api\n const sessions = api?.sessions\n if (api === undefined || sessions === undefined || typeof sessions.selectModel !== 'function') return false\n api.sessions = withFriendlyImageError(sessions, getLocale)\n return true\n}\n","/**\n * Browser controller for the \"Command Code\" settings page.\n *\n * The page lives at the same settings-nav level as General / Models / Plugins\n * (a `settings.section` entry, id `commandcode`). It exists because the\n * Models page renders an unknown-adapter-family card for the `commandcode`\n * provider and deliberately disables its submit — the API key cannot be\n * configured there. This page owns the connection facts the plugin resolves\n * per request:\n *\n * - API key -> written through the credentials domain under the reference\n * the plugin resolves (`apiKeyEnv`, default\n * `COMMANDCODE_API_KEY`). The literal never rides a response,\n * so the control only reports whether one is configured.\n * - API base -> the `llm-commandcode` settings namespace (`apiBase`), same\n * namespace the Models page card addresses.\n * - Working dir, request/stream timeouts -> the same namespace.\n *\n * The controller mirrors the plugin-card pattern from the harness's own\n * settings UI: it binds the `llm-commandcode` namespace through the\n * `settingsScope` service, keeps a staged draft of edits, and writes them on\n * save through `scope.set` / the credentials domain. The Host stays the\n * single fact source; the snapshot is republished after each accepted write.\n *\n * This module is deliberately free of JSX — it only produces the state face\n * the React component renders.\n */\n\n/** The settings namespace the plugin registers (host half, src/index.ts). */\nexport const COMMANDCODE_NS = 'llm-commandcode'\n/** Default credential reference the plugin resolves when none is named. */\nexport const DEFAULT_API_KEY_REF = 'COMMANDCODE_API_KEY'\n\n/** The settings-scope snapshot fields consumed by this controller. */\nexport interface SettingsScopeSnapshot<T> {\n status: 'loading' | 'ready' | 'unavailable'\n value: T | undefined\n base: unknown\n user: unknown\n revision: number | undefined\n writable: boolean\n mode: 'host' | 'memory'\n}\n\n/** Current settings-scope service face used without importing a browser plugin value. */\nexport interface SettingsScope<T> {\n getSnapshot(): SettingsScopeSnapshot<T>\n subscribe(listener: () => void): () => void\n set(field: string, value: unknown): Promise<void>\n unset(field: string): Promise<void>\n}\n\n/** Result envelope returned by one current Typert Remote call. */\ninterface RemoteResult<T> {\n ok: boolean\n value?: T\n error?: { message: string }\n}\n\n/** Credential facts returned without exposing the credential value. */\ninterface CredentialInfo {\n configured: boolean\n writable: boolean\n}\n\n/** The narrow slice of the wire face this controller needs. */\nexport interface SettingsPageApi {\n /** Credential methods exposed by the current Typert Remote namespace. */\n credentials: {\n describe(refs: string[]): Promise<RemoteResult<Record<string, CredentialInfo>>>\n set(ref: string, value: string): Promise<RemoteResult<void>>\n unset(ref: string): Promise<RemoteResult<void>>\n }\n}\n\n/** The Host-description observable the page reads the process cwd from. */\nexport interface HostDescriptionSource {\n getSnapshot(): { cwd?: string } | undefined\n subscribe(fn: () => void): () => void\n}\n\n/** One editable text field's staged state (blank = keep stored value). */\nexport interface StagedField {\n /** Live draft text the input shows. */\n text: string\n /** Whether the user explicitly cleared the field (reset to inherited). */\n clear: boolean\n /** Whether the user layer carries this field (marks it overridden). */\n overridden: boolean\n /** Whether the staged draft fails to parse (blocks save). */\n invalid: boolean\n /**\n * Why the draft is invalid — a non-number (`format`) or an out-of-range\n * number (`tooSmall`/`tooLarge`); undefined when valid.\n */\n invalidReason: InvalidReason | undefined\n}\n\n/** Why a staged draft fails validation (drives the per-field error copy). */\nexport type InvalidReason = 'format' | 'tooSmall' | 'tooLarge'\n\n/** One extra account row's staged state (the default account uses `apiKey`). */\nexport interface AccountItemState {\n /** Stable id — the account's credential reference. */\n id: string\n /** Credential reference this account's key lives under. */\n ref: string\n /** Label draft text (the stored/generated label until edited). */\n label: string\n /** The API key draft (write-only; starts blank, never echoes the stored key). */\n keyText: string\n /** Whether a key is stored for this account (Host-reported). */\n configured: boolean\n /** Whether the credentials domain can store the key. */\n writable: boolean\n /** Staged for addition (not yet saved). */\n added: boolean\n /** Staged for key removal on the next save (the stored key is bad/unwanted). */\n clearStaged: boolean\n}\n\n/** The page's full state face, projected from the scope + drafts + credential. */\nexport interface SettingsPageState {\n /** Whether the namespace snapshot is ready. */\n available: boolean\n /** Whether the Host document accepts writes. */\n writable: boolean\n /** Whether the API key is currently configured (Host-reported). */\n apiKeyConfigured: boolean\n /** Whether ANY account (default or extra) has a stored key — gates the usage card. */\n anyAccountConfigured: boolean\n /** Whether the credentials domain can store the key. */\n apiKeyWritable: boolean\n /** The API key draft (write-only; starts blank, never echoes the stored key). */\n apiKey: StagedField\n /** Whether the default account's stored key is staged for removal on the next save. */\n apiKeyClearStaged: boolean\n /** apiBase draft. */\n apiBase: StagedField\n /** workingDir draft. */\n workingDir: StagedField\n /**\n * The working directory a blank `workingDir` resolves to: the Host\n * process cwd (`host.describe().cwd`). Shown as the field's placeholder so\n * the user sees what \"leave it empty\" means — no configuration needed.\n */\n defaultWorkingDir: string | undefined\n /** requestTimeoutMs draft. */\n requestTimeoutMs: StagedField\n /** streamIdleTimeoutMs draft. */\n streamIdleTimeoutMs: StagedField\n /**\n * filterModelsByPlan draft, staged as `'true'`/`'false'`/`''` (unset). The\n * component renders it as a toggle; `''` means \"inherit the default\" (on).\n */\n filterModelsByPlan: StagedField\n /**\n * The manually selected active account, staged as a slot id (`default`\n * or an extra account's credential reference); `''` means \"auto — first\n * usable account\". The component renders it as a select.\n */\n activeAccount: StagedField\n /** Extra accounts (multi-account rotation), in rotation order. */\n accounts: AccountItemState[]\n /** Refs of stored accounts staged for removal (the usage card hides them). */\n accountsRemoving: string[]\n /** Whether any staged edit differs from the stored section. */\n dirty: boolean\n /** Whether a staged numeric field fails to parse (save blocked). */\n invalid: boolean\n /** Whether a save is in flight. */\n saving: boolean\n /** Whether the last save failed (drafts retained for correction). */\n failed: boolean\n /**\n * Monotonic counter bumped once per accepted save. The component watches it\n * to flash the \"Saved ✓\" affordance (timing lives in the component; the\n * controller stays a plain state machine with no timers).\n */\n savedCount: number\n}\n\n/** Parsed outcome of one field's draft. */\ntype Parsed =\n | { kind: 'set'; value: string | number | boolean }\n | { kind: 'clear' }\n | { kind: 'invalid'; reason: InvalidReason }\n\n/** One field's staged draft (internal; the public face adds derived flags). */\ninterface Staged {\n text: string\n clear: boolean\n}\n\n/** A field conversion spec. */\ninterface FieldSpec {\n field: string\n format(value: unknown): string\n parse(text: string): Parsed\n}\n\n/** A free-text field; an empty draft clears it. */\nfunction textField(field: string): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'string' ? value : ''),\n parse: (text) => {\n const trimmed = text.trim()\n return trimmed === '' ? { kind: 'clear' } : { kind: 'set', value: trimmed }\n },\n }\n}\n\n/**\n * A numeric field; an empty draft clears it, anything non-numeric blocks\n * save, and an optional inclusive `bounds` range rejects out-of-range values\n * with a specific reason (the Host schema would reject them at save time with\n * only a generic failure — catching it here names the problem while typing).\n * Decimals pass: the Host schema is `z.number()` too, and a fractional\n * millisecond value is harmless even if pointless.\n */\nfunction numberField(field: string, bounds?: { min?: number; max?: number }): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'number' ? String(value) : ''),\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return { kind: 'clear' }\n const parsed = Number(trimmed)\n if (!Number.isFinite(parsed)) return { kind: 'invalid', reason: 'format' }\n if (bounds?.min !== undefined && parsed < bounds.min) return { kind: 'invalid', reason: 'tooSmall' }\n if (bounds?.max !== undefined && parsed > bounds.max) return { kind: 'invalid', reason: 'tooLarge' }\n return { kind: 'set', value: parsed }\n },\n }\n}\n\n/**\n * A boolean field, staged as the strings `'true'`/`'false'` (an empty draft\n * clears it). The component renders a toggle and only ever stages these two\n * strings; anything else blocks save.\n */\nfunction booleanField(field: string): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'boolean' ? String(value) : ''),\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return { kind: 'clear' }\n if (trimmed === 'true') return { kind: 'set', value: true }\n if (trimmed === 'false') return { kind: 'set', value: false }\n return { kind: 'invalid', reason: 'format' }\n },\n }\n}\n\n/**\n * Inclusive bounds for the millisecond timeout fields, mirroring the Host\n * Config schema (`z.number().min(1).max(MAX_TIMER_DELAY_MS)` in src/index.ts;\n * `MAX_TIMER_DELAY_MS` is dsh-timeout's 2^31-1 timer ceiling). The client\n * bundle cannot import the node-side package, so the bound is pinned here —\n * the host remains the final gate.\n */\nexport const MIN_TIMEOUT_MS = 1\nexport const MAX_TIMEOUT_MS = 2147483647\n\n/** The fields this page edits inside the `llm-commandcode` namespace. */\nconst SECTION_FIELDS: FieldSpec[] = [\n textField('apiBase'),\n textField('workingDir'),\n numberField('requestTimeoutMs', { min: MIN_TIMEOUT_MS, max: MAX_TIMEOUT_MS }),\n numberField('streamIdleTimeoutMs', { min: MIN_TIMEOUT_MS, max: MAX_TIMEOUT_MS }),\n booleanField('filterModelsByPlan'),\n textField('activeAccount'),\n]\n\n/**\n * Controller bridging the `llm-commandcode` scope and the credentials domain\n * onto the page. Public API mirrors the harness's CardForm actions, so the\n * component stays thin.\n */\nexport class CommandCodeSettingsController {\n private readonly scope: SettingsScope<Record<string, unknown>>\n private readonly api: SettingsPageApi\n private readonly specs = new Map(SECTION_FIELDS.map((spec) => [spec.field, spec]))\n private readonly staged = new Map<string, Staged>()\n private readonly listeners = new Set<() => void>()\n private readonly disposers: Array<() => void> = []\n private disposed = false\n private defaultWorkingDir: string | undefined\n /** The credential reference the default account resolves. */\n private credentialRef = DEFAULT_API_KEY_REF\n /** Host-reported configured/writable state per credential reference. */\n private readonly credentialStates = new Map<string, { configured: boolean; writable: boolean }>()\n /** Staged account additions (not yet saved). */\n private addedAccounts: Array<{ label: string; ref: string }> = []\n /** Staged removals of stored extra accounts, by credential reference. */\n private readonly removedRefs = new Set<string>()\n /** Staged label drafts, by credential reference. */\n private readonly labelDrafts = new Map<string, string>()\n /** Staged key drafts, by credential reference (blank = keep stored key). */\n private readonly keyDrafts = new Map<string, string>()\n /** Credential references staged for removal on the next save. */\n private readonly keyClears = new Set<string>()\n private saving = false\n private failed = false\n private savedCount = 0\n\n /**\n * @param scope - bound scope for the `llm-commandcode` namespace.\n * @param api - credentials wire face.\n * @param hostDescription - the Host-description observable whose `cwd` is\n * shown as the placeholder a blank `workingDir` field resolves to.\n */\n constructor(\n scope: SettingsScope<Record<string, unknown>>,\n api: SettingsPageApi,\n hostDescription?: HostDescriptionSource,\n ) {\n this.scope = scope\n this.api = api\n this.disposers.push(scope.subscribe(() => {\n this.recomputeCredentialRef()\n void this.describeAll()\n this.publish()\n }))\n if (hostDescription !== undefined) {\n this.defaultWorkingDir = hostDescription.getSnapshot()?.cwd\n this.disposers.push(hostDescription.subscribe(() => {\n if (this.disposed) return\n const cwd = hostDescription.getSnapshot()?.cwd\n if (cwd !== this.defaultWorkingDir) {\n this.defaultWorkingDir = cwd\n this.publish()\n }\n }))\n }\n this.recomputeCredentialRef()\n void this.describeAll()\n }\n\n /** Release every subscription held on external sources. Idempotent. */\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n for (const dispose of this.disposers) dispose()\n this.disposers.length = 0\n this.listeners.clear()\n }\n\n /**\n * The credential reference the section names, or the provider default. A\n * user who renamed `apiKeyEnv` in `settings.yaml` (or the composition\n * config) gets a page that addresses the renamed ref instead of silently\n * writing the default — mirroring the Models page's `refFor()`.\n */\n private recomputeCredentialRef(): void {\n const snapshot = this.scope.getSnapshot()\n const named = typeof snapshot.value?.apiKeyEnv === 'string' && snapshot.value.apiKeyEnv.length > 0\n ? snapshot.value.apiKeyEnv\n : DEFAULT_API_KEY_REF\n if (named === this.credentialRef) return\n this.credentialRef = named\n this.credentialStates.delete(named)\n }\n\n /** Subscribe to state projections. @returns the disposer. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** Build the current page state face. */\n state(): SettingsPageState {\n const snapshot = this.scope.getSnapshot()\n const plan = this.plan()\n const credential = this.credentialStates.get(this.credentialRef)\n const accounts = this.effectiveAccounts()\n return {\n available: snapshot.status === 'ready',\n writable: snapshot.writable,\n apiKeyConfigured: credential?.configured ?? false,\n anyAccountConfigured: (credential?.configured ?? false) || accounts.some((account) => account.configured),\n apiKeyWritable: credential?.writable ?? true,\n apiKey: {\n text: this.staged.get('apiKey')?.text ?? '',\n clear: false,\n overridden: false,\n invalid: false,\n invalidReason: undefined,\n },\n apiKeyClearStaged: this.keyClears.has(this.credentialRef),\n apiBase: this.field('apiBase'),\n workingDir: this.field('workingDir'),\n defaultWorkingDir: this.defaultWorkingDir,\n requestTimeoutMs: this.field('requestTimeoutMs'),\n streamIdleTimeoutMs: this.field('streamIdleTimeoutMs'),\n filterModelsByPlan: this.field('filterModelsByPlan'),\n activeAccount: this.field('activeAccount'),\n accounts,\n accountsRemoving: [...this.removedRefs],\n dirty: plan.length > 0 || this.accountsDirty(),\n invalid: plan.some((item) => item.run === undefined),\n saving: this.saving,\n failed: this.failed,\n savedCount: this.savedCount,\n }\n }\n\n /** Stage a new extra account (saved on the next `save()`). */\n addAccount(): void {\n const used = new Set([\n this.credentialRef,\n ...this.storedExtras().map((extra) => extra.ref),\n ...this.addedAccounts.map((extra) => extra.ref),\n ])\n let n = 2\n while (used.has(`COMMANDCODE_API_KEY_${n}`)) n += 1\n const index = this.storedExtras().length + this.addedAccounts.length + 2\n this.addedAccounts.push({ label: `Account ${index}`, ref: `COMMANDCODE_API_KEY_${n}` })\n this.failed = false\n void this.describeAll()\n this.publish()\n }\n\n /** Stage one extra account's removal (or drop an unsaved addition). */\n removeAccount(id: string): void {\n const addedIndex = this.addedAccounts.findIndex((extra) => extra.ref === id)\n if (addedIndex >= 0) this.addedAccounts.splice(addedIndex, 1)\n else this.removedRefs.add(id)\n this.labelDrafts.delete(id)\n this.keyDrafts.delete(id)\n // A pinned active account that is going away must not linger as a ghost\n // selection: stage its clear alongside the removal (the host would fall\n // back to rotation order, but the stored value would be meaningless).\n const stagedActive = this.staged.get('activeAccount')\n const activeValue = stagedActive !== undefined\n ? stagedActive.clear ? '' : stagedActive.text\n : typeof this.sectionValue('activeAccount') === 'string' ? this.sectionValue('activeAccount') as string : ''\n if (activeValue === id) {\n this.staged.set('activeAccount', { text: '', clear: true })\n }\n this.failed = false\n this.publish()\n }\n\n /** Stage one extra account's label draft. */\n editAccountLabel(id: string, text: string): void {\n this.labelDrafts.set(id, text)\n this.failed = false\n this.publish()\n }\n\n /** Stage one extra account's key draft (blank keeps the stored key). */\n editAccountKey(id: string, text: string): void {\n this.keyDrafts.set(id, text)\n // Typing a replacement cancels a staged removal — the two intents are\n // mutually exclusive (replace vs remove), and a staged clear would\n // otherwise silently discard what is being typed.\n this.keyClears.delete(id)\n this.failed = false\n this.publish()\n }\n\n /**\n * Toggle the staged removal of one account's stored key: the next save\n * unsets the credential so the account reports unconfigured and falls back\n * to its other key sources. Only meaningful while a key is actually\n * stored. `target` is `'default'` (the implicit first account) or an extra\n * account's credential reference.\n */\n toggleKeyClear(target: string): void {\n const ref = target === 'default' ? this.credentialRef : target\n if (this.keyClears.has(ref)) {\n this.keyClears.delete(ref)\n } else {\n if (this.credentialStates.get(ref)?.configured !== true) return\n // A staged replacement and a staged removal are mutually exclusive.\n this.keyDrafts.delete(ref)\n if (ref === this.credentialRef) this.staged.delete('apiKey')\n this.keyClears.add(ref)\n }\n this.failed = false\n void this.describeAll()\n this.publish()\n }\n\n /** Stage one field's draft text. */\n edit(field: string, text: string): void {\n this.staged.set(field, { text, clear: false })\n // Typing a replacement for the default key cancels a staged removal.\n if (field === 'apiKey') this.keyClears.delete(this.credentialRef)\n this.failed = false\n this.publish()\n }\n\n /** Reset one section field to its inherited (composition) value. */\n resetField(field: string): void {\n if (field === 'apiKey') {\n this.staged.delete('apiKey')\n this.failed = false\n this.publish()\n return\n }\n const spec = this.spec(field)\n this.staged.set(field, { text: spec.format(this.baseValue(field)), clear: true })\n this.failed = false\n this.publish()\n }\n\n /** Discard every staged edit. */\n discard(): void {\n if (this.staged.size === 0 && !this.accountsStaged() && !this.failed) return\n this.staged.clear()\n this.clearAccountStaging()\n this.failed = false\n this.publish()\n }\n\n /**\n * Re-read the Host's credential facts without any staged edit. The browser\n * login stores a key Host-side behind the page's back; the plugin entry\n * calls this when a login lands so the configured/writable badges follow.\n */\n refreshCredentials(): void {\n void this.describeAll()\n }\n\n /** Write every staged edit, then re-read the Host's accepted state. */\n async save(): Promise<void> {\n const plan = this.plan()\n const accountRuns = this.accountPlan()\n if ((plan.length === 0 && accountRuns.length === 0) || this.saving) return\n const runs: Array<() => Promise<boolean>> = []\n for (const item of plan) {\n if (item.run === undefined) return\n runs.push(item.run)\n }\n this.saving = true\n this.failed = false\n this.publish()\n let landed = true\n // Keys land first so a saved accounts list never names a ref whose key\n // write failed silently; the accounts list itself writes last. Stop at\n // the first failure: running later writes after a failed one would\n // persist a partial state the staged drafts no longer describe.\n for (const run of [...runs, ...accountRuns]) {\n if (!(await run())) {\n landed = false\n break\n }\n }\n this.saving = false\n this.failed = !landed\n if (landed) {\n this.savedCount += 1\n this.staged.clear()\n this.clearAccountStaging()\n } else {\n // A failed save may still have landed earlier writes (e.g. the accounts\n // list made it while a key write did not). Reconcile the staging with\n // the stored section so a landed account is not simultaneously stored\n // AND staged-for-addition (which a retry would persist twice).\n this.reconcileAccountStaging()\n }\n this.publish()\n }\n\n /**\n * Drop account staging the stored section already reflects: additions whose\n * ref is now stored, removals whose ref is gone, and label drafts matching\n * the stored label. Key drafts are kept — a landed key write is idempotent\n * on retry, and the draft carries the user's intent when it was the\n * accounts write that failed.\n */\n private reconcileAccountStaging(): void {\n const stored = new Set(this.storedExtras().map((extra) => extra.ref))\n this.addedAccounts = this.addedAccounts.filter((extra) => !stored.has(extra.ref))\n for (const ref of [...this.removedRefs]) {\n if (!stored.has(ref)) this.removedRefs.delete(ref)\n }\n for (const [ref, text] of [...this.labelDrafts]) {\n const storedLabel = this.storedExtras().find((extra) => extra.ref === ref)?.label\n if (storedLabel === undefined || storedLabel === text.trim()) this.labelDrafts.delete(ref)\n }\n // A landed clear already did its job (the Host reports unconfigured);\n // keep only clears that failed so a retry re-attempts them.\n for (const ref of [...this.keyClears]) {\n if (this.credentialStates.get(ref)?.configured !== true) this.keyClears.delete(ref)\n }\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private spec(field: string): FieldSpec {\n const spec = this.specs.get(field)\n if (spec === undefined) throw new Error(`commandcode settings page has no field ${field}`)\n return spec\n }\n\n /** One field's rendered state: draft text, whether it is user-overridden, invalid. */\n private field(field: string): StagedField {\n const spec = this.spec(field)\n const staged = this.staged.get(field)\n if (staged === undefined) {\n return {\n text: spec.format(this.sectionValue(field)),\n clear: false,\n overridden: this.stored(field),\n invalid: false,\n invalidReason: undefined,\n }\n }\n const parsed = staged.clear ? { kind: 'clear' as const } : spec.parse(staged.text)\n return {\n text: staged.text,\n clear: staged.clear,\n overridden: parsed.kind === 'set',\n invalid: parsed.kind === 'invalid',\n invalidReason: parsed.kind === 'invalid' ? parsed.reason : undefined,\n }\n }\n\n private sectionValue(field: string): unknown {\n return this.scope.getSnapshot().value?.[field]\n }\n\n private baseValue(field: string): unknown {\n const base = this.scope.getSnapshot().base\n return typeof base === 'object' && base !== null && !Array.isArray(base)\n ? (base as Record<string, unknown>)[field]\n : undefined\n }\n\n private userLayer(): Record<string, unknown> | undefined {\n const user = this.scope.getSnapshot().user\n return typeof user === 'object' && user !== null && !Array.isArray(user)\n ? (user as Record<string, unknown>)\n : undefined\n }\n\n private stored(field: string): boolean {\n const user = this.userLayer()\n return user !== undefined && Object.prototype.hasOwnProperty.call(user, field)\n }\n\n /**\n * The writes a save would perform, in staged order. A field whose draft is\n * not a value its spec accepts carries no write (the save refuses).\n */\n private plan(): Array<{ field: string; run: (() => Promise<boolean>) | undefined }> {\n const plan: Array<{ field: string; run: (() => Promise<boolean>) | undefined }> = []\n for (const [field, staged] of this.staged) {\n if (field === 'apiKey') {\n const value = staged.text.trim()\n if (value !== '') {\n plan.push({ field, run: () => this.writeKey(value) })\n }\n continue\n }\n const spec = this.spec(field)\n if (staged.clear) {\n if (this.stored(field)) plan.push({ field, run: () => this.clear(field) })\n continue\n }\n if (staged.text === spec.format(this.sectionValue(field))) continue\n const parsed = spec.parse(staged.text)\n if (parsed.kind === 'invalid') plan.push({ field, run: undefined })\n else if (parsed.kind === 'clear') plan.push({ field, run: () => this.clear(field) })\n else plan.push({ field, run: () => this.store(field, parsed.value) })\n }\n return plan\n }\n\n private async clear(field: string): Promise<boolean> {\n await this.scope.unset(field)\n return !this.stored(field)\n }\n\n private async store(field: string, value: string | number | boolean): Promise<boolean> {\n await this.scope.set(field, value)\n return this.userLayer()?.[field] === value\n }\n\n /** Write the staged default key, then re-read whether the Host holds it. */\n private async writeKey(value: string): Promise<boolean> {\n return this.writeKeyTo(this.credentialRef, value)\n }\n\n /** Write one account's key, then re-read the Host's credential states. */\n private async writeKeyTo(ref: string, value: string): Promise<boolean> {\n try {\n const response = await this.api.credentials.set(ref, value)\n if (!response.ok) return false\n } catch {\n return false\n }\n await this.describeAll()\n return this.credentialStates.get(ref)?.configured ?? false\n }\n\n /** Ask the credentials domain about every reference this page writes. */\n private async describeAll(): Promise<void> {\n const refs = [\n this.credentialRef,\n ...this.storedExtras().map((extra) => extra.ref),\n ...this.addedAccounts.map((extra) => extra.ref),\n ]\n let response: Awaited<ReturnType<SettingsPageApi['credentials']['describe']>>\n try {\n response = await this.api.credentials.describe(refs)\n } catch {\n return\n }\n if (!response.ok) return\n let changed = false\n for (const ref of refs) {\n const view = response.value?.[ref]\n const next = {\n configured: view?.configured ?? false,\n writable: view?.writable ?? true,\n }\n const prev = this.credentialStates.get(ref)\n if (prev === undefined || prev.configured !== next.configured || prev.writable !== next.writable) {\n this.credentialStates.set(ref, next)\n changed = true\n }\n }\n if (changed) this.publish()\n }\n\n // -----------------------------------------------------------------------\n // Multi-account staging\n // -----------------------------------------------------------------------\n\n /** The stored extra accounts from the settings section (`accounts`). */\n private storedExtras(): Array<{ label: string; ref: string }> {\n const raw = this.scope.getSnapshot().value?.accounts\n if (!Array.isArray(raw)) return []\n const out: Array<{ label: string; ref: string }> = []\n for (const entry of raw) {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) continue\n const record = entry as Record<string, unknown>\n const ref = record.apiKeyEnv\n if (typeof ref !== 'string' || ref === '') continue\n const label = record.label\n out.push({ label: typeof label === 'string' && label !== '' ? label : ref, ref })\n }\n return out\n }\n\n /** Every extra account row: stored (minus staged removals) + staged adds. */\n private effectiveAccounts(): AccountItemState[] {\n const stored = this.storedExtras()\n .filter((extra) => !this.removedRefs.has(extra.ref))\n .map((extra) => ({ ...extra, added: false }))\n const added = this.addedAccounts.map((extra) => ({ ...extra, added: true }))\n return [...stored, ...added].map((extra) => ({\n id: extra.ref,\n ref: extra.ref,\n label: this.labelDrafts.get(extra.ref) ?? extra.label,\n keyText: this.keyDrafts.get(extra.ref) ?? '',\n configured: this.credentialStates.get(extra.ref)?.configured ?? false,\n writable: this.credentialStates.get(extra.ref)?.writable ?? true,\n added: extra.added,\n clearStaged: this.keyClears.has(extra.ref),\n }))\n }\n\n /** Whether any account-level staging (add/remove/label/key/clear) exists. */\n private accountsStaged(): boolean {\n return this.addedAccounts.length > 0\n || this.removedRefs.size > 0\n || this.labelDrafts.size > 0\n || this.keyDrafts.size > 0\n || this.keyClears.size > 0\n }\n\n /** Whether the staged account edits differ from the stored section. */\n private accountsDirty(): boolean {\n if (this.addedAccounts.length > 0 || this.removedRefs.size > 0) return true\n for (const [ref, text] of this.labelDrafts) {\n const base = this.storedExtras().find((extra) => extra.ref === ref)?.label\n if (base !== undefined && text.trim() !== '' && text !== base) return true\n }\n for (const text of this.keyDrafts.values()) {\n if (text.trim() !== '') return true\n }\n // A staged clear is only meaningful while the key is actually stored —\n // staging one against an unconfigured ref is a no-op, not dirt.\n for (const ref of this.keyClears) {\n if (this.credentialStates.get(ref)?.configured === true) return true\n }\n return false\n }\n\n /** Reset every account-level staged edit. */\n private clearAccountStaging(): void {\n this.addedAccounts = []\n this.removedRefs.clear()\n this.labelDrafts.clear()\n this.keyDrafts.clear()\n this.keyClears.clear()\n }\n\n /** Unset one stored credential, then re-read the Host's credential states. */\n private async unsetKey(ref: string): Promise<boolean> {\n try {\n const response = await this.api.credentials.unset(ref)\n if (!response.ok) return false\n } catch {\n return false\n }\n await this.describeAll()\n return this.credentialStates.get(ref)?.configured !== true\n }\n\n /** The account-level writes a save performs (empty when nothing staged). */\n private accountPlan(): Array<() => Promise<boolean>> {\n if (!this.accountsDirty()) return []\n const runs: Array<() => Promise<boolean>> = []\n // Staged removals land first: a cleared credential must be gone before\n // the accounts list write, or a removed row would leave an orphaned\n // secret behind. Removed rows keep their clear (clean removal).\n for (const ref of this.keyClears) {\n if (this.credentialStates.get(ref)?.configured === true) {\n runs.push(() => this.unsetKey(ref))\n }\n }\n for (const [ref, text] of this.keyDrafts) {\n const value = text.trim()\n if (value !== '' && !this.removedRefs.has(ref) && !this.keyClears.has(ref)) {\n runs.push(() => this.writeKeyTo(ref, value))\n }\n }\n runs.push(() => this.writeAccounts())\n return runs\n }\n\n /** Persist the staged accounts list into the settings section. */\n private async writeAccounts(): Promise<boolean> {\n const base = [\n ...this.storedExtras().filter((extra) => !this.removedRefs.has(extra.ref)),\n ...this.addedAccounts,\n ]\n // Defensive dedupe by ref: a partially landed earlier save can leave an\n // account both stored and staged-for-addition; never persist duplicates.\n const seen = new Set<string>()\n const list = base.filter((extra) => !seen.has(extra.ref) && (seen.add(extra.ref), true)).map((extra) => {\n const draft = this.labelDrafts.get(extra.ref)?.trim()\n return { label: draft !== undefined && draft !== '' ? draft : extra.label, apiKeyEnv: extra.ref }\n })\n await this.scope.set('accounts', list)\n const after = this.storedExtras()\n return after.length === list.length\n && list.every((item, index) => after[index]?.ref === item.apiKeyEnv)\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of this.listeners) listener()\n }\n}\n","/** Legacy ApiProxy credentials adapter for pre-0.1.2 DSH clients. */\n\nimport type { SettingsPageApi } from './settings.ts'\n\ninterface LegacyFailure {\n message: string\n}\n\ninterface LegacyResponse<T> {\n result:\n | { ok: true; value: T }\n | { ok: false; error: LegacyFailure }\n}\n\n/** The pre-0.1.2 `connection.api.credentials` face. */\nexport interface LegacyCredentialsApi {\n describe(request: { refs: string[] }): Promise<LegacyResponse<{\n credentials: Record<string, { configured: boolean; writable: boolean }>\n }>>\n set(request: { ref: string; value: string }): Promise<LegacyResponse<unknown>>\n unset(request: { ref: string }): Promise<LegacyResponse<unknown>>\n}\n\n/** Convert a legacy credentials ApiProxy into the current settings-page face. */\nexport function adaptLegacyCredentials(\n legacy: LegacyCredentialsApi | undefined,\n): SettingsPageApi | undefined {\n if (legacy === undefined) return undefined\n return {\n credentials: {\n describe: async (refs) => {\n const response = await legacy.describe({ refs })\n return response.result.ok\n ? { ok: true, value: response.result.value.credentials }\n : { ok: false, error: response.result.error }\n },\n set: async (ref, value) => {\n const response = await legacy.set({ ref, value })\n return response.result.ok\n ? { ok: true, value: undefined }\n : { ok: false, error: response.result.error }\n },\n unset: async (ref) => {\n const response = await legacy.unset({ ref })\n return response.result.ok\n ? { ok: true, value: undefined }\n : { ok: false, error: response.result.error }\n },\n },\n }\n}\n","/**\n * Browser controller for the settings page's account-usage card.\n *\n * The card renders the same account/usage/credit facts the `/commandcode`\n * command prints, fetched Host-side through the `commandcode/report` Remote\n * (the browser never holds the API key). This controller owns the fetch\n * lifecycle — idle/loading/ready/error, one in-flight request at a time,\n * stale-response dropping — and the display formatting, so the React\n * component stays a thin renderer and node tests can drive everything.\n *\n * Deliberately JSX-free, mirroring `./settings.ts`.\n *\n * @module dsh-commandcode-provider/client/usage\n */\n\nimport type { CommandCodeAccountsReport } from '../usage-wire.ts'\nimport type { CommandCodeLoginStatus } from '../login-wire.ts'\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\n\n/**\n * Merge the plugin's Remote endpoints into the harness's typed client Remote\n * surface (the same declaration pattern the harness's generated\n * typert.remote-client files use), so `ctx.remote.commandcode.*()` is typed\n * once each contribution is mounted. The `commandcode` namespace member is\n * declared exactly once (interface merging forbids duplicate members), so\n * this one declaration carries the usage report AND the login endpoints —\n * the endpoint-level declarations live beside their controllers.\n */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/report': () => Promise<RemoteResult<CommandCodeAccountsReport>>\n }\n interface TypertRemoteNamespaceMap {\n commandcode: {\n report: () => Promise<RemoteResult<CommandCodeAccountsReport>>\n loginBegin: () => Promise<RemoteResult<CommandCodeLoginStatus>>\n loginStatus: () => Promise<RemoteResult<CommandCodeLoginStatus>>\n loginCancel: () => Promise<RemoteResult<CommandCodeLoginStatus>>\n }\n }\n}\n\n/** The narrow slice of the mounted Remote this controller calls. */\nexport interface UsageRemote {\n report(): Promise<\n | { ok: true; value: CommandCodeAccountsReport }\n | { ok: false; error: { message: string } }\n >\n}\n\n/** The card's fetch lifecycle. */\nexport type UsageStatus =\n /** Never fetched (no API key configured yet, or not requested). */\n | 'idle'\n /** A fetch is in flight; `report` retains the last good data if any. */\n | 'loading'\n /** The last fetch succeeded. */\n | 'ready'\n /** The last fetch failed (no key, unreachable host, old plugin). */\n | 'error'\n\n/** The card's full state face. */\nexport interface UsagePageState {\n status: UsageStatus\n /** The last successfully fetched report (retained across refetches). */\n report: CommandCodeAccountsReport | undefined\n /** The last failure's message (error status). */\n error: string | undefined\n /** Millis timestamp of the last successful fetch. */\n fetchedAt: number | undefined\n}\n\nconst IDLE: UsagePageState = { status: 'idle', report: undefined, error: undefined, fetchedAt: undefined }\n\n/**\n * Controller bridging the `commandcode/report` Remote onto the card. Public\n * API mirrors {@link CommandCodeSettingsController}: `state()` projections,\n * `subscribe`, and one `refresh()` action.\n */\nexport class CommandCodeUsageController {\n private readonly remote: UsageRemote\n private readonly listeners = new Set<() => void>()\n private current: UsagePageState = IDLE\n private generation = 0\n private inFlight = false\n private disposed = false\n\n constructor(remote: UsageRemote) {\n this.remote = remote\n }\n\n /** Release every subscription. Idempotent; in-flight results are dropped. */\n dispose(): void {\n this.disposed = true\n this.generation += 1\n this.listeners.clear()\n }\n\n /** Subscribe to state projections. @returns the disposer. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** The current card state face. */\n state(): UsagePageState {\n return this.current\n }\n\n /**\n * Fetch (or refetch) the report. Concurrent refreshes collapse onto one\n * request; a superseded fetch's late result is dropped, never published.\n */\n async refresh(): Promise<void> {\n if (this.disposed || this.inFlight) return\n const generation = ++this.generation\n this.inFlight = true\n this.current = { ...this.current, status: 'loading', error: undefined }\n this.publish()\n try {\n const response = await this.remote.report()\n if (this.disposed || generation !== this.generation) return\n if (response.ok) {\n this.current = { status: 'ready', report: response.value, error: undefined, fetchedAt: Date.now() }\n } else {\n this.current = { ...this.current, status: 'error', error: response.error.message }\n }\n } catch (error: unknown) {\n if (this.disposed || generation !== this.generation) return\n this.current = {\n ...this.current,\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n }\n } finally {\n if (generation === this.generation) this.inFlight = false\n }\n this.publish()\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of this.listeners) listener()\n }\n}\n\n// ---------------------------------------------------------------------------\n// Display formatting (shared by the component, covered by node tests)\n// ---------------------------------------------------------------------------\n\n/** Format a dollar amount compactly (2 decimals). */\nexport function formatMoney(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\n/** Format a dollar amount precisely (4 decimals) for small totals. */\nexport function formatMoneyExact(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\n/** Format a large token count compactly (1.9M style). */\nexport function formatTokensCompact(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/** One window's fill ratio in [0, 1]; 0 when uncapped. */\nexport function windowRatio(used: number, cap: number): number {\n if (cap <= 0) return 0\n return Math.max(0, Math.min(1, used / cap))\n}\n\n/** Format a millis timestamp as a local short date-time; empty when unset. */\nexport function formatResetAt(ms: number): string {\n if (ms <= 0) return ''\n return new Date(ms).toLocaleString()\n}\n","/**\n * Browser controller for the settings page's login panel.\n *\n * The panel drives the Host-half browser login (the official\n * `command-code login` loopback dance) through the Typert Gateway: `begin`\n * asks the Host to bind the callback server and returns the Studio URL, the\n * controller polls `loginStatus` once a second while the attempt is live, and\n * `cancel` tears it down. The key itself never crosses to the browser — the\n * Host validates and stores it through the credentials seam.\n *\n * Transport-level failures (no mounted Remote, an older Host without the\n * login endpoints) land in the dedicated `unavailable` phase so the page can\n * point back at manual paste. Deliberately JSX-free, mirroring\n * `./settings.ts` and `./usage.ts`.\n *\n * @module dsh-commandcode-provider/client/login\n */\n\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nimport type { CommandCodeLoginFailureReason, CommandCodeLoginStatus } from '../login-wire.ts'\n\n/** The endpoint-level Remote surface this controller calls. */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/loginBegin': () => Promise<RemoteResult<CommandCodeLoginStatus>>\n 'commandcode/loginStatus': () => Promise<RemoteResult<CommandCodeLoginStatus>>\n 'commandcode/loginCancel': () => Promise<RemoteResult<CommandCodeLoginStatus>>\n }\n}\n\n/** The narrow slice of the mounted Remote this controller calls. */\nexport interface LoginRemote {\n loginBegin(): Promise<LoginCallResult>\n loginStatus(): Promise<LoginCallResult>\n loginCancel(): Promise<LoginCallResult>\n}\n\n/** One Remote call's outcome as the controller sees it. */\nexport type LoginCallResult =\n | { ok: true; value: CommandCodeLoginStatus }\n | { ok: false; error: { message: string } }\n\n/** The panel's full state face. */\nexport interface LoginPageState {\n /**\n * `idle` — nothing started; `starting` — begin() in flight; `waiting` —\n * the Studio URL is live and polling; `success`/`failed` — terminal;\n * `unavailable` — the Remote itself could not be reached (old Host, mount\n * failure), manual paste is the way.\n */\n phase: 'idle' | 'starting' | 'waiting' | 'success' | 'failed' | 'unavailable'\n /** The Studio authorization URL while `waiting`. */\n authUrl: string | undefined\n /** The account display name on `success`. */\n userName: string | undefined\n /** The key's Studio label on `success`. */\n keyName: string | undefined\n /** The stable failure reason when `failed`. */\n reason: CommandCodeLoginFailureReason | undefined\n /** Secondary failure detail when `failed`/`unavailable`. */\n message: string | undefined\n}\n\n/** How often a live attempt is polled. */\nconst POLL_INTERVAL_MS = 1_000\n\n/**\n * The login panel's fetch/poll lifecycle. One poll loop at a time; a fresh\n * `begin()` supersedes any previous loop via a generation token.\n */\nexport class CommandCodeLoginController {\n private readonly remote: () => LoginRemote | undefined\n private readonly listeners = new Set<() => void>()\n private readonly pollMs: number\n /** Monotonic token; only the latest loop may publish polling results. */\n private generation = 0\n private disposed = false\n\n private phase: LoginPageState['phase'] = 'idle'\n private authUrl: string | undefined\n private userName: string | undefined\n private keyName: string | undefined\n private reason: CommandCodeLoginFailureReason | undefined\n private message: string | undefined\n\n constructor(remote: () => LoginRemote | undefined, pollMs = POLL_INTERVAL_MS) {\n this.remote = remote\n this.pollMs = pollMs\n }\n\n /** Subscribe to state projections. @returns the disposer. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** Build the current panel state face. */\n state(): LoginPageState {\n return {\n phase: this.phase,\n authUrl: this.authUrl,\n userName: this.userName,\n keyName: this.keyName,\n reason: this.reason,\n message: this.message,\n }\n }\n\n /** Start (or rejoin) a login attempt and begin polling its status. */\n async begin(): Promise<void> {\n if (this.disposed || this.phase === 'starting' || this.phase === 'waiting') return\n const generation = ++this.generation\n this.set({ phase: 'starting', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: undefined })\n const remote = this.remote()\n if (remote === undefined) {\n this.set({ phase: 'unavailable', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: 'login remote is not mounted' })\n return\n }\n let result: LoginCallResult\n try {\n result = await remote.loginBegin()\n } catch (error: unknown) {\n // A transport throw (gateway hiccup) reads the same as a rejected call.\n result = { ok: false, error: { message: error instanceof Error ? error.message : String(error) } }\n }\n if (this.superseded(generation)) return\n if (!result.ok) {\n this.set({ phase: 'unavailable', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: result.error.message })\n return\n }\n this.apply(result.value)\n if (this.currentPhase === 'waiting') void this.poll(generation)\n }\n\n /** Cancel a waiting attempt. */\n async cancel(): Promise<void> {\n if (this.disposed || (this.phase !== 'starting' && this.phase !== 'waiting')) return\n const generation = ++this.generation\n const remote = this.remote()\n if (remote === undefined) return\n let result: LoginCallResult\n try {\n result = await remote.loginCancel()\n } catch {\n // The Host may be gone; reflect the local cancel regardless.\n this.set({ phase: 'failed', authUrl: undefined, userName: undefined, keyName: undefined, reason: 'cancelled', message: undefined })\n return\n }\n if (this.superseded(generation)) return\n if (result.ok) this.apply(result.value)\n else this.set({ phase: 'failed', authUrl: undefined, userName: undefined, keyName: undefined, reason: 'cancelled', message: undefined })\n }\n\n /** Stop polling and release listeners. Idempotent. */\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n this.generation += 1\n this.listeners.clear()\n }\n\n // -----------------------------------------------------------------------\n // Internals\n // -----------------------------------------------------------------------\n\n /** Poll until the attempt leaves `waiting` or a newer loop supersedes us. */\n private async poll(generation: number): Promise<void> {\n // A getter read (not the field) so control-flow narrowing across `await`\n // cannot claim the phase is frozen.\n while (!this.disposed && !this.superseded(generation) && this.currentPhase === 'waiting') {\n await sleep(this.pollMs)\n if (this.disposed || this.superseded(generation) || this.currentPhase !== 'waiting') return\n const remote = this.remote()\n if (remote === undefined) {\n this.set({ phase: 'unavailable', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: 'login remote is not mounted' })\n return\n }\n let result: LoginCallResult\n try {\n result = await remote.loginStatus()\n } catch {\n continue // one missed poll is not an outage; the next tick retries\n }\n if (this.superseded(generation) || this.currentPhase !== 'waiting') return\n if (result.ok) this.apply(result.value)\n }\n }\n\n private get currentPhase(): LoginPageState['phase'] {\n return this.phase\n }\n\n /** Project one Host status onto the panel face. */\n private apply(status: CommandCodeLoginStatus): void {\n const base = { authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: undefined }\n if (status.state === 'waiting') {\n this.set({ ...base, phase: 'waiting', authUrl: status.authUrl })\n return\n }\n if (status.state === 'success') {\n this.set({ ...base, phase: 'success', userName: status.userName, keyName: status.keyName })\n return\n }\n if (status.state === 'failed') {\n this.set({ ...base, phase: 'failed', reason: status.reason, message: status.message })\n return\n }\n // `idle` mid-poll means the Host restarted; the attempt is gone.\n this.set({ ...base, phase: 'failed', reason: 'cancelled', message: 'the login attempt is no longer active' })\n }\n\n /** Replace the whole state face and notify. Explicit over partial patches. */\n private set(state: LoginPageState): void {\n this.phase = state.phase\n this.authUrl = state.authUrl\n this.userName = state.userName\n this.keyName = state.keyName\n this.reason = state.reason\n this.message = state.message\n this.publish()\n }\n\n private superseded(generation: number): boolean {\n return this.disposed || generation !== this.generation\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of [...this.listeners]) listener()\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\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 * 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 * The plugin's own version, read from package.json at build time.\n *\n * The client bundle inlines the JSON import (rolldown resolves it during the\n * tsdown build; node tests read it through tsx), so the rendered value always\n * matches the published package version with no second constant to keep in\n * sync. Rendered as a muted footer line on the settings page so a user can\n * report the exact build they run.\n *\n * @module dsh-commandcode-provider/client/version\n */\n\nimport pkg from '../../package.json'\n\n/** The published package version (e.g. `'0.6.0'`). */\nexport const PLUGIN_VERSION: string = pkg.version\n\n/**\n * This package's GitHub releases page, derived from the repository field so\n * the update hint's link target can never drift from the published home.\n */\nexport const PLUGIN_RELEASES_URL: string =\n `${pkg.repository.url.replace(/^git\\+/, '').replace(/\\.git$/, '')}/releases`\n","/**\n * Plugin update hint (browser half).\n *\n * A deliberately small feature: when the \"Command Code\" settings page opens,\n * ask the npm registry for the package's published `latest` version and —\n * only when it is newer than the running build — let the page's footer show a\n * muted \"newer version available\" link to the GitHub releases. Everything\n * here is React-free and side-effect-seamed so node tests can drive it.\n *\n * Behaviour contract:\n *\n * - The registry is queried at most once per {@link UPDATE_CHECK_INTERVAL_MS}\n * per browser profile; the learned version is cached in `localStorage`\n * alongside the attempt time, so re-opening the settings page is free.\n * - A failed check records the attempt time too (an offline browser must not\n * hammer the registry on every page open) but keeps any previously learned\n * version, so the hint survives transient outages until it expires.\n * - Every failure mode (blocked network, non-OK status, malformed payload,\n * unavailable storage) degrades to \"no hint\"; nothing ever throws out of\n * {@link checkForUpdate}.\n *\n * The registry serves `access-control-allow-origin: *`, so the plain browser\n * fetch works from the GUI origin without any Host-side proxying.\n *\n * @module dsh-commandcode-provider/client/update\n */\n\n/** How often the page may hit the registry: once a day. */\nexport const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000\n\n/** Abort a hung registry request rather than keep the footer waiting. */\nexport const FETCH_TIMEOUT_MS = 5000\n\n/**\n * The npm registry document for this package's `latest` dist-tag. The scoped\n * name is path-escaped (`%2F`) so no client normalizes the slash away.\n */\nexport const NPM_LATEST_URL =\n 'https://registry.npmjs.org/@mars-sea%2Fdsh-commandcode-provider/latest'\n\n/**\n * Compare two version strings (`major.minor.patch[-pre]`). Returns a negative\n * number when `a` sorts before `b`, positive when after, zero when equal.\n *\n * Tolerant by design: a leading `v` is stripped, unparsable numeric parts\n * count as `0`, and semver prerelease rules apply (release > prerelease;\n * numeric identifiers compare numerically, everything else lexically, a\n * shorter identifier list sorts first). Enough for release tags; not a full\n * semver validator.\n */\nexport function compareVersions(a: string, b: string): number {\n const left = splitVersion(a)\n const right = splitVersion(b)\n const depth = Math.max(left.core.length, right.core.length)\n for (let index = 0; index < depth; index += 1) {\n const delta = (left.core[index] ?? 0) - (right.core[index] ?? 0)\n if (delta !== 0) return Math.sign(delta)\n }\n // A release outranks any prerelease of the same core version.\n if (left.pre.length === 0 && right.pre.length === 0) return 0\n if (left.pre.length === 0) return 1\n if (right.pre.length === 0) return -1\n const width = Math.max(left.pre.length, right.pre.length)\n for (let index = 0; index < width; index += 1) {\n const l = left.pre[index]\n const r = right.pre[index]\n if (l === undefined) return -1\n if (r === undefined) return 1\n const lNumeric = /^\\d+$/.test(l)\n const rNumeric = /^\\d+$/.test(r)\n let delta: number\n if (lNumeric && rNumeric) delta = Number(l) - Number(r)\n else if (lNumeric) delta = -1 // numeric identifiers sort below alphanumeric\n else if (rNumeric) delta = 1\n else delta = l < r ? -1 : l > r ? 1 : 0\n if (delta !== 0) return Math.sign(delta)\n }\n return 0\n}\n\n/** True when `candidate` is strictly newer than `current`. */\nexport function isNewerVersion(candidate: string, current: string): boolean {\n return compareVersions(candidate, current) > 0\n}\n\n/** Split a tolerant version string into numeric core + prerelease ids. */\nfunction splitVersion(value: string): { core: number[]; pre: string[] } {\n const [coreText = '', preText] = value.trim().replace(/^v/i, '').split('-')\n const core = coreText === ''\n ? [0]\n : coreText.split('.').map((part) => {\n const parsed = Number.parseInt(part, 10)\n return Number.isFinite(parsed) ? parsed : 0\n })\n const pre = preText === undefined ? [] : preText.split('.')\n return { core, pre }\n}\n\n/**\n * Extract the published version from the registry's `/latest` manifest\n * (`{ name, version, … }`). Throws on anything unexpected so callers treat a\n * shape change as a failed attempt, never as bogus data.\n */\nexport function parseLatestVersion(payload: unknown): string {\n if (typeof payload !== 'object' || payload === null) {\n throw new Error('npm latest payload is not an object')\n }\n const version = (payload as { version?: unknown }).version\n if (typeof version !== 'string' || !/^\\d+\\.\\d+\\./.test(version)) {\n throw new Error('npm latest payload has no usable version')\n }\n return version\n}\n\n/** Fetch and parse the published `latest` version. Rejects on any failure. */\nexport async function fetchLatestVersion(\n fetchImpl: typeof fetch = fetch,\n): Promise<string> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n try {\n const response = await fetchImpl(NPM_LATEST_URL, { signal: controller.signal })\n if (!response.ok) {\n throw new Error(`registry responded ${response.status}`)\n }\n return parseLatestVersion(await response.json())\n } finally {\n clearTimeout(timer)\n }\n}\n\n/** What the cache remembers about the last check. */\nexport interface UpdateCheckRecord {\n /** When the last attempt completed (success or failure), epoch ms. */\n at: number\n /** The last successfully learned upstream version, if any. */\n version?: string | undefined\n}\n\n/** Storage seam so tests can stand in for `localStorage`. */\nexport interface UpdateCheckStore {\n read(): UpdateCheckRecord | undefined\n write(record: UpdateCheckRecord): void\n}\n\n/** The `localStorage` key holding {@link UpdateCheckRecord}. */\nexport const UPDATE_CHECK_CACHE_KEY = '@mars-sea/dsh-commandcode-provider/update-check'\n\n/**\n * A {@link UpdateCheckStore} backed by `localStorage`. Tolerates a missing or\n * throwing storage (SSR-ish contexts, private modes): reads yield `undefined`,\n * writes are dropped.\n */\nexport function localStorageUpdateStore(\n storage: Storage | undefined = typeof localStorage === 'undefined' ? undefined : localStorage,\n): UpdateCheckStore {\n return {\n read(): UpdateCheckRecord | undefined {\n if (storage === undefined) return undefined\n try {\n const raw = storage.getItem(UPDATE_CHECK_CACHE_KEY)\n if (raw === null) return undefined\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== 'object' || parsed === null) return undefined\n const at = (parsed as { at?: unknown }).at\n if (typeof at !== 'number' || !Number.isFinite(at)) return undefined\n const version = (parsed as { version?: unknown }).version\n return {\n at,\n version: typeof version === 'string' && version !== '' ? version : undefined,\n }\n } catch {\n return undefined\n }\n },\n write(record: UpdateCheckRecord): void {\n if (storage === undefined) return\n try {\n storage.setItem(UPDATE_CHECK_CACHE_KEY, JSON.stringify(record))\n } catch {\n // Quota/private-mode failures must never break the page.\n }\n },\n }\n}\n\n/**\n * Run one throttled update check. Resolves with the newest published version\n * when it is newer than `currentVersion`, otherwise `undefined`.\n *\n * Within the throttle window (or on failure) the cached version answers, so\n * the hint keeps working offline; past the window the registry is consulted\n * again and the attempt time is refreshed either way.\n */\nexport async function checkForUpdate(options: {\n currentVersion: string\n now: number\n store: UpdateCheckStore\n fetchImpl?: typeof fetch\n}): Promise<string | undefined> {\n const { currentVersion, now, store } = options\n const hintOf = (version: string | undefined): string | undefined =>\n version !== undefined && isNewerVersion(version, currentVersion) ? version : undefined\n\n const cache = store.read()\n if (cache !== undefined && now - cache.at < UPDATE_CHECK_INTERVAL_MS) {\n return hintOf(cache.version)\n }\n\n let learned: string | undefined\n try {\n learned = await fetchLatestVersion(options.fetchImpl)\n } catch {\n // Degrade silently: record the attempt below and fall back to the cache.\n }\n const version = learned ?? cache?.version\n store.write({ at: now, version })\n return hintOf(version)\n}\n","/**\n * React component for the \"Command Code\" settings page (browser half).\n *\n * Renders as a `settings.section` entry — a page at the same settings-nav\n * level as General / Models / Plugins. The shell supplies the nav row and\n * renders this body inside the content column. All copy comes from the\n * `settings.commandcode` locale namespace; all state comes from the\n * `CommandCodeSettingsController` injected by the slot registration.\n *\n * The layout mirrors the harness's settings pages: a max-width content\n * column, labelled fields with hints, a reset affordance, and a\n * save/discard footer. Rarely touched connection facts (API base, working\n * directory, timeouts, plan filter) fold into a collapsed Advanced card\n * (`AdvancedSection`) so the page leads with the key and the usage facts.\n * Styles are injected once by the client entry\n * (see src/client/index.ts) and class-prefixed `cc-` to stay local.\n */\n\nimport { useEffect, useState } from 'react'\nimport { Button } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { CommandCodeCredits } from '../adapter.ts'\nimport type { CommandCodeAccountUsage, CommandCodeUsageReport } from '../usage-wire.ts'\nimport type { SettingsCommandCodeKey } from './locales.ts'\nimport type { AccountItemState, SettingsPageState, StagedField } from './settings.ts'\nimport type { CommandCodeLoginFailureReason } from '../login-wire.ts'\nimport type { LoginPageState } from './login.ts'\nimport type { UsagePageState } from './usage.ts'\nimport { formatMoney, formatMoneyExact, formatResetAt, formatTokensCompact, windowRatio } from './usage.ts'\nimport { PLUGIN_RELEASES_URL, PLUGIN_VERSION } from './version.ts'\nimport { checkForUpdate, localStorageUpdateStore } from './update.ts'\n\n/** Props composed by the slot registration: locale seat + injected face. */\nexport interface CommandCodeSettingsProps {\n t: Translate<SettingsCommandCodeKey>\n useCommandCodeSettings<T>(selector: (state: SettingsPageState) => T): T\n useCommandCodeUsage<T>(selector: (state: UsagePageState) => T): T\n useCommandCodeLogin<T>(selector: (state: LoginPageState) => T): T\n edit(field: string, text: string): void\n resetField(field: string): void\n save(): void\n discard(): void\n refreshUsage(): void\n beginLogin(): void\n cancelLogin(): void\n addAccount(): void\n removeAccount(id: string): void\n editAccountLabel(id: string, text: string): void\n editAccountKey(id: string, text: string): void\n toggleKeyClear(id: string): void\n}\n\n/** The section fields folded into the collapsible Advanced card. */\ntype AdvancedField = 'apiBase' | 'workingDir' | 'requestTimeoutMs' | 'streamIdleTimeoutMs' | 'filterModelsByPlan'\nconst ADVANCED_FIELDS: readonly AdvancedField[] = [\n 'apiBase',\n 'workingDir',\n 'requestTimeoutMs',\n 'streamIdleTimeoutMs',\n 'filterModelsByPlan',\n]\n\n/** One labelled field row in the page body. */\nfunction Field({\n id,\n label,\n hint,\n state,\n disabled,\n numeric,\n placeholder,\n onEdit,\n onReset,\n t,\n}: {\n id: string\n label: string\n hint: string\n state: StagedField\n disabled: boolean\n numeric?: boolean\n placeholder?: string | undefined\n onEdit(text: string): void\n onReset(): void\n t: Translate<SettingsCommandCodeKey>\n}) {\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor={id}>{label}</label>\n <span className=\"cc-badges\">\n {state.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null}\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onReset}>{t('reset')}</button>\n </span>\n </div>\n <input\n id={id}\n className={state.invalid ? 'cc-input cc-inputInvalid' : 'cc-input'}\n type=\"text\"\n inputMode={numeric ? 'numeric' : undefined}\n value={state.text}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n <p className={state.invalid ? 'cc-invalid' : 'cc-hint'}>\n {state.invalid ? invalidCopy(state.invalidReason, t) : hint}\n </p>\n </div>\n )\n}\n\n/** The per-field error copy for a staged draft's failure reason. */\nfunction invalidCopy(reason: StagedField['invalidReason'], t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'tooSmall') return t('numberTooSmall')\n if (reason === 'tooLarge') return t('numberTooLarge')\n return t('invalidNumber')\n}\n\n/**\n * The collapsed \"Advanced\" card: API base, working dir, both timeouts, and\n * the plan filter live here so the page leads with the facts a user actually\n * touches. Starts collapsed on every visit; expands on demand. While\n * collapsed, a badge names the customized count so a nonzero override stays\n * visible (a number field's error blocks save and must be reachable).\n */\nfunction AdvancedSection({\n state,\n disabled,\n t,\n onEdit,\n onReset,\n}: {\n state: SettingsPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onEdit(field: string, text: string): void\n onReset(field: string): void\n}) {\n const [expanded, setExpanded] = useState(false)\n const overridden = ADVANCED_FIELDS.filter((field) => state[field].overridden).length\n const invalid = ADVANCED_FIELDS.some((field) => state[field].invalid)\n return (\n <div className=\"cc-card\">\n <button\n type=\"button\"\n className=\"cc-advancedHead\"\n aria-expanded={expanded}\n aria-controls=\"cc-advanced-body\"\n onClick={() => setExpanded((value) => !value)}\n >\n <span className=\"cc-advancedTitle\">{t('advancedSettings')}</span>\n {overridden > 0 ? (\n <span className=\"cc-badge\">\n {overridden === 1 ? t('advancedOverriddenOne') : t('advancedOverriddenMany').replace('{count}', String(overridden))}\n </span>\n ) : null}\n <span className=\"cc-advancedSpacer\" />\n <span className={expanded ? 'cc-chevron cc-chevronUp' : 'cc-chevron'} aria-hidden=\"true\" />\n </button>\n {expanded ? (\n <div id=\"cc-advanced-body\" className=\"cc-advancedBody\">\n <p className=\"cc-hint\">{t('advancedSettingsHint')}</p>\n <Field\n id=\"cc-api-base\"\n label={t('apiBase')}\n hint={t('apiBaseHint')}\n state={state.apiBase}\n disabled={disabled}\n onEdit={(text) => onEdit('apiBase', text)}\n onReset={() => onReset('apiBase')}\n t={t}\n />\n <Field\n id=\"cc-working-dir\"\n label={t('workingDir')}\n hint={t('workingDirHint')}\n state={state.workingDir}\n disabled={disabled}\n placeholder={state.defaultWorkingDir}\n onEdit={(text) => onEdit('workingDir', text)}\n onReset={() => onReset('workingDir')}\n t={t}\n />\n <Field\n id=\"cc-request-timeout\"\n label={t('requestTimeoutMs')}\n hint={t('requestTimeoutMsHint')}\n state={state.requestTimeoutMs}\n disabled={disabled}\n numeric\n onEdit={(text) => onEdit('requestTimeoutMs', text)}\n onReset={() => onReset('requestTimeoutMs')}\n t={t}\n />\n <Field\n id=\"cc-stream-idle-timeout\"\n label={t('streamIdleTimeoutMs')}\n hint={t('streamIdleTimeoutMsHint')}\n state={state.streamIdleTimeoutMs}\n disabled={disabled}\n numeric\n onEdit={(text) => onEdit('streamIdleTimeoutMs', text)}\n onReset={() => onReset('streamIdleTimeoutMs')}\n t={t}\n />\n <ToggleField\n id=\"cc-filter-models-by-plan\"\n label={t('filterModelsByPlan')}\n hint={t('filterModelsByPlanHint')}\n state={state.filterModelsByPlan}\n disabled={disabled}\n defaultChecked\n onEdit={(text) => onEdit('filterModelsByPlan', text)}\n onReset={() => onReset('filterModelsByPlan')}\n t={t}\n />\n </div>\n ) : null}\n {expanded && invalid ? (\n <p className=\"cc-invalid\" role=\"status\">{t('advancedInvalid')}</p>\n ) : null}\n </div>\n )\n}\n\n/**\n * One boolean field row rendered as a toggle. The staged text is `'true'` /\n * `'false'` / `''` (unset → `defaultChecked`); toggling stages the string the\n * boolean field spec parses back into a real boolean on save.\n */\nfunction ToggleField({\n id,\n label,\n hint,\n state,\n disabled,\n defaultChecked,\n onEdit,\n onReset,\n t,\n}: {\n id: string\n label: string\n hint: string\n state: StagedField\n disabled: boolean\n defaultChecked: boolean\n onEdit(text: string): void\n onReset(): void\n t: Translate<SettingsCommandCodeKey>\n}) {\n const checked = state.text === '' ? defaultChecked : state.text === 'true'\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor={id}>{label}</label>\n <span className=\"cc-badges\">\n {state.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null}\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onReset}>{t('reset')}</button>\n </span>\n </div>\n <label className=\"cc-toggleRow\">\n <input\n id={id}\n className=\"cc-toggle\"\n type=\"checkbox\"\n role=\"switch\"\n checked={checked}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.checked ? 'true' : 'false')}\n />\n <span className=\"cc-hint\">{hint}</span>\n </label>\n </div>\n )\n}\n\n/**\n * The API-key control: write-only, reports configured state, never echoes the\n * key. The input is masked by default with a Show/Hide toggle so a pasted key\n * can be spot-checked without leaving the field, and a stored key can be\n * staged for removal (the next save unsets it) when it is bad or unwanted.\n */\nfunction SecretKeyField({\n label,\n hint,\n state,\n disabled,\n configured,\n configuredLabel,\n unconfiguredLabel,\n clearStaged,\n showLabel,\n hideLabel,\n clearLabel,\n clearStagedLabel,\n undoClearLabel,\n onEdit,\n onToggleClear,\n}: {\n label: string\n hint: string\n state: StagedField\n disabled: boolean\n configured: boolean\n configuredLabel: string\n unconfiguredLabel: string\n clearStaged: boolean\n showLabel: string\n hideLabel: string\n clearLabel: string\n clearStagedLabel: string\n undoClearLabel: string\n onEdit(text: string): void\n onToggleClear(): void\n}) {\n const [visible, setVisible] = useState(false)\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor=\"cc-api-key\">{label}</label>\n <span className=\"cc-badges\">\n <span className={configured ? 'cc-badge' : 'cc-badgeMuted'}>\n {configured ? configuredLabel : unconfiguredLabel}\n </span>\n {clearStaged ? <span className=\"cc-badge cc-badgeWarn\">{clearStagedLabel}</span> : null}\n {configured ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onToggleClear}>\n {clearStaged ? undoClearLabel : clearLabel}\n </button>\n ) : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={disabled}\n onClick={() => setVisible((value) => !value)}\n >\n {visible ? hideLabel : showLabel}\n </button>\n </span>\n </div>\n <input\n id=\"cc-api-key\"\n className=\"cc-input\"\n type={visible ? 'text' : 'password'}\n autoComplete=\"off\"\n spellCheck={false}\n value={state.text}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n <p className=\"cc-hint\">{hint}</p>\n </div>\n )\n}\n\n/** The per-reason copy for a failed login attempt. */\nfunction loginFailureCopy(reason: CommandCodeLoginFailureReason | undefined, t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'denied') return t('loginDenied')\n if (reason === 'timeout') return t('loginTimeout')\n if (reason === 'invalid-key') return t('loginInvalidKey')\n if (reason === 'network') return t('loginNetwork')\n if (reason === 'unavailable') return t('loginStoreFailed')\n if (reason === 'cancelled') return t('loginCancelled')\n return t('loginFailedGeneric')\n}\n\n/**\n * The sign-in alternative to pasting a key: one field row that starts the\n * Host-side browser login, links to the Studio authorization page while the\n * attempt is live, and reports the outcome. The key itself never crosses to\n * the browser — only \"who signed in\" does.\n */\nfunction LoginPanel({ state, disabled, t, onBegin, onCancel }: {\n state: LoginPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onBegin(): void\n onCancel(): void\n}) {\n const busy = state.phase === 'starting' || state.phase === 'waiting'\n let hint = t('loginHintIdle')\n let hintTitle: string | undefined\n let hintClass = 'cc-hint'\n if (state.phase === 'starting' || state.phase === 'waiting') hint = t(state.phase === 'starting' ? 'loginStarting' : 'loginWaiting')\n else if (state.phase === 'success') {\n const keyName = state.keyName !== undefined && state.keyName !== '' ? ` · ${state.keyName}` : ''\n hint = `${t('loginSuccess')} ${state.userName ?? ''}${keyName}`.trim()\n hintClass = 'cc-loginDone'\n } else if (state.phase === 'failed') {\n hint = loginFailureCopy(state.reason, t)\n hintClass = 'cc-loginError'\n if (state.message !== undefined) hintTitle = state.message\n } else if (state.phase === 'unavailable') {\n hint = `${t('loginUnavailable')} ${state.message ?? ''}`.trim()\n hintClass = 'cc-loginError'\n }\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\">{t('loginTitle')}</label>\n <span className=\"cc-badges\">\n {busy ? (\n <button type=\"button\" className=\"cc-reset\" onClick={onCancel}>{t('loginCancel')}</button>\n ) : (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onBegin}>{t('loginButton')}</button>\n )}\n </span>\n </div>\n {state.authUrl !== undefined ? (\n <p className=\"cc-hint\">\n <a className=\"cc-loginLink\" href={state.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n </p>\n ) : null}\n <p className={hintClass} title={hintTitle}>{hint}</p>\n </div>\n )\n}\n\n/** One stat tile in the account card's summary grid. */\nfunction UsageStat({ label, value, sub }: { label: string; value: string; sub?: string | undefined }) {\n return (\n <div className=\"cc-usageStat\">\n <span className=\"cc-usageStatLabel\">{label}</span>\n <span className=\"cc-usageStatValue\">{value}</span>\n {sub !== undefined && sub !== '' ? <span className=\"cc-usageStatSub\">{sub}</span> : null}\n </div>\n )\n}\n\n/** One window-limit row: label, used/cap, a fill bar, and the reset time. */\nfunction UsageWindow({\n label,\n limit: { used, cap, exceeded, resetAt },\n t,\n}: {\n label: string\n limit: CommandCodeCredits['fiveHour']\n t: Translate<SettingsCommandCodeKey>\n}) {\n const ratio = windowRatio(used, cap)\n const reset = formatResetAt(resetAt)\n return (\n <div className=\"cc-usageWindow\">\n <div className=\"cc-usageWindowHead\">\n <span className=\"cc-usageWindowLabel\">{label}</span>\n {exceeded ? <span className=\"cc-usageExceeded\">{t('usageExceeded')}</span> : null}\n <span className=\"cc-usageWindowValue\">{cap > 0 ? `${formatMoney(used)} / ${formatMoney(cap)}` : formatMoney(used)}</span>\n </div>\n <div className=\"cc-usageBar\" role=\"progressbar\" aria-valuemin={0} aria-valuemax={100} aria-valuenow={Math.round(ratio * 100)}>\n <div className={exceeded ? 'cc-usageBarFill cc-usageBarFillWarn' : 'cc-usageBarFill'} style={{ width: `${ratio * 100}%` }} />\n </div>\n {reset !== '' ? <p className=\"cc-usageWindowReset\">{t('usageReset')} {reset}</p> : null}\n </div>\n )\n}\n\n/** One account's rotation state as a short badge next to its label. */\nfunction AccountMark({ entry, t }: { entry: CommandCodeAccountUsage; t: Translate<SettingsCommandCodeKey> }) {\n if (entry.active) return <span className=\"cc-usagePlan\">{t('usageActive')}</span>\n if (entry.mark === 'invalid-credential') return <span className=\"cc-usagePlanStatus\">{t('usageInvalidKey')}</span>\n if (entry.cooldownUntil > 0) {\n return <span className=\"cc-usagePlanStatus\">{t('usageCooldown')} {formatResetAt(entry.cooldownUntil)}</span>\n }\n if (entry.mark === 'rate-limit') return <span className=\"cc-usagePlanStatus\">{t('usageCooldown')}</span>\n return null\n}\n\n/**\n * One pool account's facts (identity, totals, credits, window limits)\n * rendered inside the account-usage card.\n */\nfunction AccountReport({ entry, fetchedAt, t, onRemove }: {\n entry: CommandCodeAccountUsage\n /**\n * When the shared usage snapshot was fetched — shares the account's bottom\n * meta row with the billing period end so the two timestamps occupy one\n * line (period/partial facts left, fetch freshness right).\n */\n fetchedAt?: number | undefined\n t: Translate<SettingsCommandCodeKey>\n /** Present only for removable (non-default) accounts on a writable page. */\n onRemove?: (() => void) | undefined\n}) {\n const report = entry.report\n const account = report.account\n const accountName = account === undefined ? '' : account.userName || account.name\n const credits = report.credits\n const plan = report.plan\n const planName = plan?.name ?? ''\n const planStatus = plan !== undefined && plan.status !== '' && plan.status !== 'active' ? plan.status : ''\n const showPeriod = plan !== undefined && plan.currentPeriodEnd > 0\n const showPartial = report.failures.length > 0 && report.blocked === undefined\n\n return (\n <div className=\"cc-accountReport\">\n <div className=\"cc-usageHead\">\n <h4 className=\"cc-usageTitle\">{entry.label}</h4>\n <AccountMark entry={entry} t={t} />\n {accountName !== '' ? <span className=\"cc-usageAccount\">{accountName}</span> : null}\n {planName !== '' ? <span className=\"cc-usagePlan\">{planName}</span> : null}\n {planStatus !== '' ? <span className=\"cc-usagePlanStatus\">{planStatus}</span> : null}\n <span className=\"cc-usageMetaSpacer\" />\n {onRemove !== undefined ? (\n <button type=\"button\" className=\"cc-usageRefresh\" onClick={onRemove}>{t('accountRemove')}</button>\n ) : null}\n </div>\n\n {!entry.configured ? <p className=\"cc-usageHint\">{t('usageUnconfigured')}</p> : null}\n\n {report.blocked !== undefined ? (\n <div className=\"cc-usageBlocked\" role=\"alert\">\n <p className=\"cc-usageBlockedTitle\">{blockedTitle(report.blocked, t)}</p>\n <p className=\"cc-usageBlockedHint\">{blockedHint(report.blocked, t)}</p>\n </div>\n ) : null}\n\n {report.usage !== undefined ? (\n <div className=\"cc-usageStats\">\n <UsageStat\n label={t('usageRequests')}\n value={String(report.usage.completedCount)}\n sub={`${t('usageFailed')} ${report.usage.failedCount}`}\n />\n <UsageStat label={t('usageSuccessRate')} value={`${report.usage.successRate}%`} />\n <UsageStat\n label={t('usageCost')}\n value={formatMoneyExact(report.usage.totalCost)}\n sub={`${formatMoney(report.usage.totalCredits)} credits`}\n />\n <UsageStat\n label={t('usageTokens')}\n value={formatTokensCompact(report.usage.totalTokensIn + report.usage.totalTokensOut)}\n sub={`${formatTokensCompact(report.usage.totalTokensIn)} ${t('usageTokensIn')} / ${formatTokensCompact(report.usage.totalTokensOut)} ${t('usageTokensOut')}`}\n />\n </div>\n ) : null}\n\n {credits !== undefined ? (\n <div className=\"cc-usageStats\">\n <UsageStat label={t('usageMonthly')} value={formatMoney(credits.monthlyCredits)} />\n <UsageStat label={t('usagePurchased')} value={formatMoney(credits.purchasedCredits)} />\n <UsageStat label={t('usageFree')} value={formatMoney(credits.freeCredits)} />\n </div>\n ) : null}\n\n {credits !== undefined ? (\n <div className=\"cc-usageWindows\">\n <UsageWindow label={t('usageFiveHour')} limit={credits.fiveHour} t={t} />\n <UsageWindow label={t('usageWeekly')} limit={credits.weekly} t={t} />\n </div>\n ) : null}\n\n {showPeriod || showPartial || fetchedAt !== undefined ? (\n <div className=\"cc-usageMeta\">\n {showPeriod ? (\n <p className=\"cc-usageUpdated\">{t('usagePeriodEnd')} {new Date(plan.currentPeriodEnd).toLocaleDateString()}</p>\n ) : null}\n {showPartial ? (\n <p className=\"cc-usagePartial\" title={report.failures.join('; ')}>{t('usagePartial')}</p>\n ) : null}\n <span className=\"cc-usageMetaSpacer\" />\n {fetchedAt !== undefined ? (\n <p className=\"cc-usageUpdated\">{t('usageUpdated')} {new Date(fetchedAt).toLocaleTimeString()}</p>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n\n/** The headline copy for a report whose every endpoint failed the same way. */\nfunction blockedTitle(reason: CommandCodeUsageReport['blocked'], t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'invalid-key') return t('usageKeyInvalid')\n if (reason === 'service-unavailable') return t('usageServiceUnavailable')\n return t('usageNetworkError')\n}\n\n/** The actionable hint under a blocked report's headline. */\nfunction blockedHint(reason: CommandCodeUsageReport['blocked'], t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'invalid-key') return t('usageKeyInvalidHint')\n if (reason === 'service-unavailable') return t('usageServiceUnavailableHint')\n return t('usageNetworkHint')\n}\n\n/** The status dot on an account tab: cooling/invalid warn, everything else ok. */\nfunction AccountTabDot({ entry }: { entry: CommandCodeAccountUsage }) {\n const cls = entry.mark === 'invalid-credential'\n ? 'cc-tabDot cc-tabDotError'\n : entry.mark !== '' || entry.cooldownUntil > 0\n ? 'cc-tabDot cc-tabDotWarn'\n : 'cc-tabDot cc-tabDotOk'\n return <span className={cls} />\n}\n\n/**\n * The account-usage card: the `/commandcode` dashboard's facts rendered as\n * a native settings card. With several accounts the card is a carousel — a\n * tab strip (label + status dot) switches between accounts so the page stays\n * short; each account's report carries its own remove affordance (the\n * default account is not removable). Accounts staged for removal in the\n * management card are hidden here immediately. Data arrives through the\n * `commandcode/report` Remote; the API keys never leave the Host.\n */\nfunction UsageCard({ t, usage, apiKeyConfigured, removingIds, removableIds, canManage, onRefresh, onRemoveAccount }: {\n t: Translate<SettingsCommandCodeKey>\n usage: UsagePageState\n apiKeyConfigured: boolean\n /** Ids of accounts staged for removal (hidden from the carousel). */\n removingIds: string[]\n /**\n * Ids of accounts the settings document can actually remove (the stored\n * extra accounts' refs). Composition-only accounts (literal-key slots with\n * positional `account-N` ids) are NOT removable from the page — the\n * settings document cannot name them — so they get no remove button.\n */\n removableIds: string[]\n /** Whether the page accepts writes (the remove affordance follows it). */\n canManage: boolean\n onRefresh(): void\n onRemoveAccount(id: string): void\n}) {\n // First paint with a configured key fetches automatically; later fetches\n // are explicit (refresh button) or follow a landed save.\n useEffect(() => {\n if (apiKeyConfigured && usage.status === 'idle') onRefresh()\n }, [apiKeyConfigured, usage.status, onRefresh])\n\n const loading = usage.status === 'loading'\n const report = usage.report\n // Locally remembered removals: the usage controller keeps the old report\n // until the post-save refresh lands, and removedRefs clears at save-land —\n // without this the just-removed account would pop back in for one refresh\n // round-trip. Cleared when a fresh report arrives (fetchedAt changes).\n const [locallyRemoved, setLocallyRemoved] = useState<readonly string[]>([])\n useEffect(() => {\n setLocallyRemoved([])\n }, [usage.fetchedAt])\n const hidden = new Set([...removingIds, ...locallyRemoved])\n const seenIds = new Set<string>()\n const entries = (report?.accounts ?? []).filter((entry) => {\n if (hidden.has(entry.id)) return false\n // Hand-edited settings can name the same credential ref twice; dedupe so\n // the tab strip never carries duplicate keys/selections.\n if (seenIds.has(entry.id)) return false\n seenIds.add(entry.id)\n return true\n })\n const [selectedId, setSelectedId] = useState<string | undefined>(undefined)\n // The selected tab: the explicit choice while it still exists, else the\n // serving (active) account, else the first entry.\n const selected = entries.find((entry) => entry.id === selectedId)\n ?? entries.find((entry) => entry.active)\n ?? entries[0]\n const removeSelected = canManage && selected !== undefined && removableIds.includes(selected.id)\n ? () => {\n const id = selected.id\n setLocallyRemoved((prev) => [...prev, id])\n onRemoveAccount(id)\n }\n : undefined\n\n return (\n <div className=\"cc-usageCard\" aria-label={t('usageTitle')}>\n <div className=\"cc-usageHead\">\n <h3 className=\"cc-usageTitle\">{t('usageTitle')}</h3>\n <span className=\"cc-usageMetaSpacer\" />\n <button type=\"button\" className=\"cc-usageRefresh\" disabled={loading || !apiKeyConfigured} onClick={onRefresh}>\n {loading ? t('usageRefreshing') : t('usageRefresh')}\n </button>\n </div>\n\n {!apiKeyConfigured ? <p className=\"cc-usageHint\">{t('usageNoKey')}</p> : null}\n {apiKeyConfigured && report === undefined && loading ? <p className=\"cc-usageHint\">{t('usageLoading')}</p> : null}\n {usage.status === 'error' ? (\n <p className=\"cc-usageError\" role=\"status\">\n <span>{t('usageError')}{usage.error !== undefined && usage.error !== '' ? ` — ${usage.error}` : ''}</span>\n </p>\n ) : null}\n\n {entries.length > 1 ? (\n <div className=\"cc-tabs\" role=\"tablist\" aria-label={t('accountsTitle')}>\n {entries.map((entry) => (\n <button\n key={entry.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected?.id === entry.id}\n className={selected?.id === entry.id ? 'cc-tab cc-tabActive' : 'cc-tab'}\n onClick={() => setSelectedId(entry.id)}\n >\n <AccountTabDot entry={entry} />\n {entry.label}\n </button>\n ))}\n </div>\n ) : null}\n\n {selected !== undefined ? (\n <AccountReport\n key={selected.id}\n entry={selected}\n fetchedAt={usage.fetchedAt}\n t={t}\n onRemove={removeSelected}\n />\n ) : null}\n </div>\n )\n}\n\n/**\n * One extra account row: label, key, configured badge. Saved accounts are\n * removed from the usage card above; a NOT-YET-SAVED addition never appears\n * there (the usage report is Host-side), so it keeps its own remove button —\n * otherwise the only way to undo a mistaken Add would be discarding every\n * other staged edit.\n */\nfunction AccountRow({ account, disabled, t, onLabel, onKey, onToggleClear, onRemove }: {\n account: AccountItemState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onLabel(text: string): void\n onKey(text: string): void\n onToggleClear(): void\n onRemove(): void\n}) {\n const locked = !account.writable\n const [keyVisible, setKeyVisible] = useState(false)\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor={`cc-account-label-${account.id}`}>{t('accountLabel')}</label>\n <span className=\"cc-badges\">\n {account.added ? <span className=\"cc-badge\">{t('unsaved')}</span> : null}\n <span className={account.configured ? 'cc-badge' : 'cc-badgeMuted'}>\n {account.configured ? t('apiKeySet') : t('apiKeyUnset')}\n </span>\n {account.clearStaged ? <span className=\"cc-badge cc-badgeWarn\">{t('usageKeyClearStaged')}</span> : null}\n {account.configured && !account.clearStaged ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onToggleClear}>\n {t('usageKeyClear')}\n </button>\n ) : null}\n {account.clearStaged ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onToggleClear}>\n {t('usageUndoKeyClear')}\n </button>\n ) : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={disabled}\n onClick={() => setKeyVisible((value) => !value)}\n >\n {keyVisible ? t('hide') : t('show')}\n </button>\n {account.added ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onRemove}>{t('accountRemove')}</button>\n ) : null}\n </span>\n </div>\n <input\n id={`cc-account-label-${account.id}`}\n className=\"cc-input\"\n type=\"text\"\n value={account.label}\n disabled={disabled}\n onChange={(event) => onLabel(event.target.value)}\n />\n <input\n id={`cc-account-key-${account.id}`}\n className=\"cc-input\"\n type={keyVisible ? 'text' : 'password'}\n autoComplete=\"off\"\n spellCheck={false}\n placeholder={t('accountKey')}\n value={account.keyText}\n disabled={disabled || locked}\n onChange={(event) => onKey(event.target.value)}\n />\n <p className=\"cc-hint\">{locked ? t('apiKeyLocked') : t('accountKeyHint')}</p>\n </div>\n )\n}\n\n/** The multi-account card: the active-account selector + extra accounts in rotation order + add button. */\nfunction AccountsCard({ t, state, disabled, onAdd, onRemove, onLabel, onKey, onToggleClear, onActive, onActiveReset }: {\n t: Translate<SettingsCommandCodeKey>\n state: SettingsPageState\n disabled: boolean\n onAdd(): void\n onRemove(id: string): void\n onLabel(id: string, text: string): void\n onKey(id: string, text: string): void\n onToggleClear(id: string): void\n onActive(text: string): void\n onActiveReset(): void\n}) {\n const active = state.activeAccount\n return (\n <div className=\"cc-card\" aria-label={t('accountsTitle')}>\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\">{t('accountsTitle')}</label>\n <span className=\"cc-badges\">\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onAdd}>{t('accountAdd')}</button>\n </span>\n </div>\n <p className=\"cc-hint\">{t('accountsHint')}</p>\n </div>\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor=\"cc-active-account\">{t('activeAccount')}</label>\n <span className=\"cc-badges\">\n {active.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null}\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onActiveReset}>{t('reset')}</button>\n </span>\n </div>\n <select\n id=\"cc-active-account\"\n className=\"cc-input\"\n value={active.text}\n disabled={disabled}\n onChange={(event) => onActive(event.target.value)}\n >\n <option value=\"\">{t('activeAccountAuto')}</option>\n <option value=\"default\">{t('accountDefault')}</option>\n {state.accounts.filter((account) => !account.added).map((account) => (\n <option key={account.id} value={account.ref}>{account.label}</option>\n ))}\n </select>\n <p className=\"cc-hint\">{t('activeAccountHint')}</p>\n </div>\n {state.accounts.map((account) => (\n <AccountRow\n key={account.id}\n account={account}\n disabled={disabled}\n t={t}\n onLabel={(text) => onLabel(account.id, text)}\n onKey={(text) => onKey(account.id, text)}\n onToggleClear={() => onToggleClear(account.id)}\n onRemove={() => onRemove(account.id)}\n />\n ))}\n </div>\n )\n}\n\n/**\n * Show the \"Saved ✓\" affordance for a short window after each accepted save.\n * The controller only counts saves (`savedCount`); the flash timing lives\n * here so the state machine stays timer-free.\n */\nfunction useSavedFlash(tick: number): boolean {\n const [visible, setVisible] = useState(false)\n useEffect(() => {\n if (tick === 0) return\n setVisible(true)\n const timer = setTimeout(() => setVisible(false), 2500)\n return () => clearTimeout(timer)\n }, [tick])\n return visible\n}\n\n/**\n * The update hint: one throttled npm-registry check per page open (the\n * throttle and all failure handling live in ./update.ts). Resolves to the\n * newest published version when it is newer than this build, else undefined —\n * every failure mode degrades to no hint at all.\n */\nfunction usePluginUpdate(): string | undefined {\n const [available, setAvailable] = useState<string | undefined>(undefined)\n useEffect(() => {\n let cancelled = false\n void checkForUpdate({\n currentVersion: PLUGIN_VERSION,\n now: Date.now(),\n store: localStorageUpdateStore(),\n }).then((version) => {\n if (!cancelled) setAvailable(version)\n // A rejected checkForUpdate would be a bug (it catches internally);\n // swallow it regardless — the footer must never break the page.\n }, () => {})\n return () => {\n cancelled = true\n }\n }, [])\n return available\n}\n\n/** The settings page body: connection facts for the Command Code provider. */\nexport function CommandCodeSettingsPage(props: CommandCodeSettingsProps) {\n const { t } = props\n const state = props.useCommandCodeSettings((snapshot) => snapshot)\n const usage = props.useCommandCodeUsage((snapshot) => snapshot)\n const login = props.useCommandCodeLogin((snapshot) => snapshot)\n const disabled = !state.writable\n const keyLocked = !state.apiKeyWritable\n const savedVisible = useSavedFlash(state.savedCount)\n const updateVersion = usePluginUpdate()\n return (\n <section className=\"cc-section\" aria-label={t('title')}>\n <h2 className=\"cc-title\">{t('title')}</h2>\n <p className=\"cc-intro\">{t('intro')}</p>\n {!state.writable ? <p className=\"cc-readOnly\" role=\"status\">{t('readOnly')}</p> : null}\n <UsageCard\n t={t}\n usage={usage}\n apiKeyConfigured={state.anyAccountConfigured}\n removingIds={state.accountsRemoving}\n removableIds={state.accounts.map((account) => account.id)}\n canManage={state.writable}\n onRefresh={props.refreshUsage}\n onRemoveAccount={props.removeAccount}\n />\n <AccountsCard\n t={t}\n state={state}\n disabled={disabled}\n onAdd={props.addAccount}\n onRemove={props.removeAccount}\n onLabel={props.editAccountLabel}\n onKey={props.editAccountKey}\n onToggleClear={(id) => props.toggleKeyClear(id)}\n onActive={(text) => props.edit('activeAccount', text)}\n onActiveReset={() => props.resetField('activeAccount')}\n />\n <div className=\"cc-card\">\n <SecretKeyField\n label={t('apiKey')}\n hint={keyLocked ? t('apiKeyLocked') : t('apiKeyHint')}\n state={state.apiKey}\n disabled={disabled || keyLocked}\n configured={state.apiKeyConfigured}\n configuredLabel={t('apiKeySet')}\n unconfiguredLabel={t('apiKeyUnset')}\n clearStaged={state.apiKeyClearStaged}\n showLabel={t('show')}\n hideLabel={t('hide')}\n clearLabel={t('usageKeyClear')}\n clearStagedLabel={t('usageKeyClearStaged')}\n undoClearLabel={t('usageUndoKeyClear')}\n onEdit={(text) => props.edit('apiKey', text)}\n onToggleClear={() => props.toggleKeyClear('default')}\n />\n <LoginPanel\n state={login}\n disabled={disabled || keyLocked}\n t={t}\n onBegin={props.beginLogin}\n onCancel={props.cancelLogin}\n />\n </div>\n <AdvancedSection\n state={state}\n disabled={disabled}\n t={t}\n onEdit={props.edit}\n onReset={props.resetField}\n />\n <div className=\"cc-footer\">\n {state.failed ? <p className=\"cc-failed\" role=\"status\">{t('saveFailed')}</p> : null}\n {savedVisible ? <p className=\"cc-saved\" role=\"status\">{t('saved')}</p> : null}\n <Button variant=\"ghost\" size=\"sm\" disabled={!state.dirty || state.saving} onClick={props.discard}>\n {t('discard')}\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={!state.dirty || state.invalid || state.saving}\n onClick={props.save}\n >\n {t(state.saving ? 'saving' : 'save')}\n </Button>\n </div>\n <p className=\"cc-version\">\n Command Code Provider v{PLUGIN_VERSION}\n {updateVersion !== undefined ? (\n <>\n {' · '}\n <a\n className=\"cc-versionLink\"\n href={PLUGIN_RELEASES_URL}\n target=\"_blank\"\n rel=\"noreferrer\"\n title={t('updateHint')}\n >\n v{updateVersion} {t('updateAvailable')}\n </a>\n </>\n ) : null}\n </p>\n </section>\n )\n}\n","/**\n * The Command Code provider card inside the harness Models settings page\n * (browser half). Rendered through the `settings.models.provider-card` keyed\n * slot available in dsh 0.1.2-alpha.2, registered with\n * `entryKey = 'llm-commandcode'` (the plugin's settings namespace, the key the\n * Models page dispatches for every Command Code provider row).\n *\n * The slot's owner props (`configured`, `keyConfigured`) mirror what the\n * Models page already knows; the authoritative credential facts still come\n * from this plugin's `CommandCodeSettingsController` shared with the dedicated\n * settings page, so the two surfaces can never disagree about whether a key\n * is stored.\n *\n * Not configured: an \"Unconfigured\" badge, a paste-a-key field, and the\n * official sign-in button — the whole flow a first-run user needs, inline.\n * Configured: a green \"Configured\" badge plus a pointer to the full\n * Command Code settings page for rotation, usage, and connection facts.\n *\n * The card renders nothing until the shared controller's first snapshot is\n * ready (`available`), which also keeps the stale-facts window of the older\n * join from ever being visible. A controller-less render (card mounted before\n * the section registered its inject face — the composition runs one apply)\n * degrades to the stateless registration-notice form.\n *\n * Styles ride the page stylesheet the client entry injects once (`cc-`\n * prefixed classes); the card adds no CSS of its own.\n */\n\nimport { useState } from 'react'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsCommandCodeKey } from './locales.ts'\nimport type { SettingsPageState, StagedField } from './settings.ts'\nimport type { LoginPageState } from './login.ts'\nimport type { CommandCodeLoginFailureReason } from '../login-wire.ts'\n\n/**\n * The Models-page extension slots, merged into the SlotMap with the exact\n * declarations dsh 0.1.2-alpha.2's ui-settings-models ships. The merge must\n * stay structurally identical to upstream's (kind/scope/owner), or a future\n * dsh carrying its own declaration would fail the duplicate-merge check at\n * compile time.\n */\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n /** One provider card's adapter extension area, keyed by the row's settingsNs. */\n 'settings.models.provider-card': { kind: 'keyed'; scope: 'root'; owner: ProviderCardExtrasOwnerProps }\n /** Ordered extension area after the provider rows and the add controls. */\n 'settings.models.footer': { kind: 'list'; scope: 'root'; owner: ModelsFooterOwnerProps }\n }\n}\n\n/** The provider directory row as the Models page dispatches it. */\nexport interface ProviderDirectoryRow {\n /** The provider route id (`commandcode` for this plugin). */\n readonly provider: string\n /** The row's display name. */\n readonly displayName: string\n /** The settings namespace the row configures (the slot's dispatch key). */\n readonly settingsNs: string\n /** The settings path the row's profile lives at. */\n readonly settingsPath: readonly string[]\n /** Whether the provider route is live. */\n readonly active: boolean\n /** Whether the adapter declares the route as shipped. */\n readonly declared?: boolean\n}\n\n/** Owner share of one provider-card extension occurrence (upstream's shape). */\nexport interface ProviderCardExtrasOwnerProps {\n /** The card's directory row. */\n readonly provider: ProviderDirectoryRow\n /** Whether any layer configures this provider (its profile resolves). */\n readonly configured: boolean\n /** The row's referenced api-key credential, confirmed configured by the page's join. */\n readonly keyConfigured: boolean\n}\n\n/** Owner share of the footer area (the section supplies nothing). */\nexport interface ModelsFooterOwnerProps {\n /** Marker field: footer owner props are intentionally empty. */\n children?: never\n}\n\n/** Owner props the Models page supplies at its dispatch sites. */\nexport type ProviderCardOwnerProps = ProviderCardExtrasOwnerProps\n\n/** Injected face the card's slot registration supplies. */\nexport interface CommandCodeCardProps {\n t: Translate<SettingsCommandCodeKey>\n useCommandCodeSettings<T>(selector: (state: SettingsPageState) => T): T\n useCommandCodeLogin<T>(selector: (state: LoginPageState) => T): T\n edit(field: string, text: string): void\n save(): void\n beginLogin(): void\n cancelLogin(): void\n}\n\n/** The card's two postures. */\ntype CardMode =\n | { kind: 'registration' }\n | { kind: 'live'; ready: boolean; controllerConfigured: boolean; writable: boolean; apiKeyWritable: boolean }\n\n/** Decide the card's posture from the injected face and the owner facts. */\nexport function cardMode(props: CommandCodeCardProps & ProviderCardOwnerProps): CardMode {\n if (props.useCommandCodeSettings === undefined) return { kind: 'registration' }\n const snapshot = props.useCommandCodeSettings((state) => state)\n return {\n kind: 'live',\n ready: snapshot.available,\n controllerConfigured: snapshot.apiKeyConfigured,\n writable: snapshot.writable,\n apiKeyWritable: snapshot.apiKeyWritable,\n }\n}\n\n/** Status badge for the credential state (green when configured). */\nfunction StatusBadge({ ok, okLabel, pendingLabel }: {\n ok: boolean\n okLabel: string\n pendingLabel: string\n}) {\n return <span className={ok ? 'cc-badge' : 'cc-badgeMuted'}>{ok ? okLabel : pendingLabel}</span>\n}\n\n/**\n * The per-reason copy for a failed login attempt (mirrors the settings\n * page's LoginPanel; the same reasons can surface from this card).\n */\nfunction loginFailureCopy(reason: CommandCodeLoginFailureReason | undefined, t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'denied') return t('loginDenied')\n if (reason === 'timeout') return t('loginTimeout')\n if (reason === 'invalid-key') return t('loginInvalidKey')\n if (reason === 'network') return t('loginNetwork')\n if (reason === 'unavailable') return t('loginStoreFailed')\n if (reason === 'cancelled') return t('loginCancelled')\n return t('loginFailedGeneric')\n}\n\n/** The sign-in affordance row for the not-configured card (see LoginPanel). */\nfunction CardLoginRow({ state, disabled, t, onBegin, onCancel }: {\n state: LoginPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onBegin(): void\n onCancel(): void\n}) {\n const busy = state.phase === 'starting' || state.phase === 'waiting'\n let hint = t('loginHintIdle')\n let hintClass = 'cc-hint'\n if (state.phase === 'starting' || state.phase === 'waiting') hint = t(state.phase === 'starting' ? 'loginStarting' : 'loginWaiting')\n else if (state.phase === 'success') {\n const keyName = state.keyName !== undefined && state.keyName !== '' ? ` · ${state.keyName}` : ''\n hint = `${t('loginSuccess')} ${state.userName ?? ''}${keyName}`.trim()\n hintClass = 'cc-loginDone'\n } else if (state.phase === 'failed') {\n hint = loginFailureCopy(state.reason, t)\n hintClass = 'cc-loginError'\n } else if (state.phase === 'unavailable') {\n hint = `${t('loginUnavailable')} ${state.message ?? ''}`.trim()\n hintClass = 'cc-loginError'\n }\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <span className=\"cc-label\">{t('loginTitle')}</span>\n <span className=\"cc-badges\">\n {busy ? (\n <button type=\"button\" className=\"cc-reset\" onClick={onCancel}>{t('loginCancel')}</button>\n ) : (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onBegin}>{t('loginButton')}</button>\n )}\n </span>\n </div>\n {state.authUrl !== undefined ? (\n <p className=\"cc-hint\">\n <a className=\"cc-loginLink\" href={state.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n </p>\n ) : null}\n <p className={hintClass}>{hint}</p>\n </div>\n )\n}\n\n/** Compact key field for the not-configured card. */\nfunction CardKeyField({ state, disabled, t, onEdit }: {\n state: StagedField\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onEdit(text: string): void\n}) {\n const [visible, setVisible] = useState(false)\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor=\"cc-card-api-key\">{t('apiKey')}</label>\n <span className=\"cc-badges\">\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={() => setVisible((value) => !value)}>\n {visible ? t('hide') : t('show')}\n </button>\n </span>\n </div>\n <input\n id=\"cc-card-api-key\"\n className=\"cc-input\"\n type={visible ? 'text' : 'password'}\n autoComplete=\"off\"\n spellCheck={false}\n value={state.text}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n <p className=\"cc-hint\">{t('apiKeyHint')}</p>\n </div>\n )\n}\n\n/** One \"Configured\" badge + pointer to the full settings page (footer area). */\nfunction CardConfiguredBody({ t }: { t: Translate<SettingsCommandCodeKey> }) {\n return (\n <div className=\"cc-field\">\n <p className=\"cc-hint\">{t('cardConfiguredHint')}</p>\n </div>\n )\n}\n\n/**\n * The slot component body. Dispatched on every Command Code provider card of\n * the Models page (saved row, first-run setup posture, and add-provider\n * draft).\n */\nexport function CommandCodeProviderCard(props: CommandCodeCardProps & ProviderCardOwnerProps) {\n const { t } = props\n const mode = cardMode(props)\n const state = props.useCommandCodeSettings !== undefined\n ? props.useCommandCodeSettings((snapshot) => snapshot)\n : undefined\n const login = props.useCommandCodeLogin !== undefined\n ? props.useCommandCodeLogin((snapshot) => snapshot)\n : undefined\n const dirty = state?.dirty ?? false\n const saving = state?.saving ?? false\n const invalid = state?.invalid ?? false\n const failed = state?.failed ?? false\n const savingBlocked = !dirty || invalid\n const configured = mode.kind === 'live' && mode.ready ? mode.controllerConfigured : props.keyConfigured\n const disabled = mode.kind === 'live' && (!mode.writable || (state !== undefined && !mode.apiKeyWritable))\n const showBody = mode.kind === 'live' && mode.ready && state !== undefined\n return (\n <div className=\"cc-providerCard\" data-cc-models-card=\"true\">\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <span className=\"cc-label\">{t('cardTitle')}</span>\n <span className=\"cc-badges\">\n <StatusBadge ok={configured} okLabel={t('apiKeySet')} pendingLabel={t('apiKeyUnset')} />\n {props.provider.active ? <span className=\"cc-badge\">{t('cardRouteActive')}</span> : null}\n </span>\n </div>\n {mode.kind === 'registration' ? <p className=\"cc-hint\">{t('cardRegistrationHint')}</p> : null}\n {mode.kind === 'live' && !mode.ready ? <p className=\"cc-hint\">{t('cardLoadingHint')}</p> : null}\n </div>\n {showBody && !configured ? (\n <>\n <CardKeyField\n state={state.apiKey}\n disabled={disabled}\n t={t}\n onEdit={(text) => props.edit('apiKey', text)}\n />\n {login !== undefined ? (\n <CardLoginRow\n state={login}\n disabled={disabled}\n t={t}\n onBegin={props.beginLogin}\n onCancel={props.cancelLogin}\n />\n ) : null}\n <div className=\"cc-footer\">\n {failed ? <p className=\"cc-failed\" role=\"status\">{t('saveFailed')}</p> : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={savingBlocked || saving}\n onClick={props.save}\n >\n {t(saving ? 'saving' : 'save')}\n </button>\n </div>\n </>\n ) : null}\n {showBody && configured ? <CardConfiguredBody t={t} /> : null}\n </div>\n )\n}\n","/**\n * Locale copy for the \"Command Code\" settings page, and the declaration that\n * merges the page's namespace into the framework's `LocaleNamespaceMap` so\n * `ctx.locale.register` / `ctx.slots.register(..., { locale })` are typed.\n *\n * zh is the source of truth for the key set (repo convention); en must carry\n * the exact same keys — a mismatch is a compile error at the register site.\n */\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Copy of the Command Code settings page. */\n 'settings.commandcode': SettingsCommandCodeKey\n }\n}\n\n/** Dictionary keys of the Command Code settings page. */\nexport type SettingsCommandCodeKey =\n | 'nav'\n | 'title'\n | 'intro'\n | 'apiKey'\n | 'apiKeyHint'\n | 'apiKeySet'\n | 'apiKeyUnset'\n | 'apiKeyLocked'\n | 'apiBase'\n | 'apiBaseHint'\n | 'workingDir'\n | 'workingDirHint'\n | 'requestTimeoutMs'\n | 'requestTimeoutMsHint'\n | 'streamIdleTimeoutMs'\n | 'streamIdleTimeoutMsHint'\n | 'advancedSettings'\n | 'advancedSettingsHint'\n | 'advancedOverriddenOne'\n | 'advancedOverriddenMany'\n | 'advancedInvalid'\n | 'filterModelsByPlan'\n | 'filterModelsByPlanHint'\n | 'accountsTitle'\n | 'accountsHint'\n | 'accountAdd'\n | 'accountRemove'\n | 'accountLabel'\n | 'accountKey'\n | 'accountKeyHint'\n | 'accountDefault'\n | 'activeAccount'\n | 'activeAccountAuto'\n | 'activeAccountHint'\n | 'overridden'\n | 'reset'\n | 'invalidNumber'\n | 'numberTooSmall'\n | 'numberTooLarge'\n | 'readOnly'\n | 'unsaved'\n | 'save'\n | 'saving'\n | 'saved'\n | 'saveFailed'\n | 'discard'\n | 'cancel'\n | 'show'\n | 'hide'\n | 'usageTitle'\n | 'usageRefresh'\n | 'usageRefreshing'\n | 'usageLoading'\n | 'usageNoKey'\n | 'usageError'\n | 'usageRequests'\n | 'usageFailed'\n | 'usageSuccessRate'\n | 'usageCost'\n | 'usageTokens'\n | 'usageTokensIn'\n | 'usageTokensOut'\n | 'usageMonthly'\n | 'usagePurchased'\n | 'usageFree'\n | 'usageFiveHour'\n | 'usageWeekly'\n | 'usageExceeded'\n | 'usageReset'\n | 'usagePartial'\n | 'usageKeyClear'\n | 'usageKeyClearStaged'\n | 'usageUndoKeyClear'\n | 'usageKeyInvalid'\n | 'usageKeyInvalidHint'\n | 'usageServiceUnavailable'\n | 'usageServiceUnavailableHint'\n | 'usageNetworkError'\n | 'usageNetworkHint'\n | 'usageUpdated'\n | 'usagePeriodEnd'\n | 'usageActive'\n | 'usageCooldown'\n | 'usageInvalidKey'\n | 'usageUnconfigured'\n | 'updateAvailable'\n | 'updateHint'\n | 'loginTitle'\n | 'loginHintIdle'\n | 'loginButton'\n | 'loginStarting'\n | 'loginWaiting'\n | 'loginOpenLink'\n | 'loginCancel'\n | 'loginSuccess'\n | 'loginUnavailable'\n | 'loginDenied'\n | 'loginTimeout'\n | 'loginInvalidKey'\n | 'loginNetwork'\n | 'loginStoreFailed'\n | 'loginCancelled'\n | 'loginFailedGeneric'\n | 'cardTitle'\n | 'cardRouteActive'\n | 'cardLoadingHint'\n | 'cardRegistrationHint'\n | 'cardConfiguredHint'\n\nexport const zh: Record<SettingsCommandCodeKey, string> = {\n nav: 'Command Code',\n title: 'Command Code',\n intro:\n '配置 Command Code Provider 连接。API 密钥仅保存在本机凭据服务中,不会回显;'\n + '其他字段写入用户设置,下次请求即生效。',\n apiKey: 'API 密钥',\n apiKeyHint: '在 commandcode.ai 控制台创建。留空保存不会覆盖已存储的密钥。',\n apiKeySet: '已配置',\n apiKeyUnset: '未配置',\n apiKeyLocked: '密钥由只读来源提供',\n apiBase: 'API 地址',\n apiBaseHint: '默认 https://api.commandcode.ai,一般无需修改。',\n workingDir: '工作目录',\n workingDirHint: '可选。留空时使用占位符显示的进程工作目录;仅在需要固定路径时填写。',\n requestTimeoutMs: '请求超时(毫秒)',\n requestTimeoutMsHint: '等待响应首个字节的超时;默认 60000。',\n streamIdleTimeoutMs: '流空闲超时(毫秒)',\n streamIdleTimeoutMsHint: '生成流停滞多久视为断连;默认 300000(长思考模型可静默数分钟,默认值刻意放宽)。',\n advancedSettings: '高级设置',\n advancedSettingsHint: 'API 地址、工作目录、超时与模型过滤等不常修改的选项。',\n advancedOverriddenOne: '已自定义 1 项',\n advancedOverriddenMany: '已自定义 {count} 项',\n advancedInvalid: '高级设置中有未填好的数字,请展开修正后再保存。',\n filterModelsByPlan: '隐藏套餐外模型',\n filterModelsByPlanHint: '开启后,模型选择器只列出当前套餐可用的模型;账户持有按需余额时会显示全部。',\n accountsTitle: '多账户轮换',\n accountsHint: '当前账户达到用量限额(429)或密钥失效(401)时,请求自动切换到下一个账户;全部耗尽时会提示最早的重置时间。',\n accountAdd: '添加账户',\n accountRemove: '移除',\n accountLabel: '账户备注名',\n accountKey: 'API 密钥',\n accountKeyHint: '该账户的 API 密钥。留空保存不会覆盖已存储的密钥。',\n accountDefault: '默认账户',\n activeAccount: '当前使用账户',\n activeAccountAuto: '自动(第一个可用账户)',\n activeAccountHint: '手动指定优先使用的账户,保存后下次请求即生效;所选账户耗尽时仍会自动切换到其他可用账户。',\n overridden: '已覆盖',\n reset: '重置',\n invalidNumber: '无效数字',\n numberTooSmall: '不能小于 1(毫秒)',\n numberTooLarge: '超出允许上限(2147483647 毫秒)',\n readOnly: '当前配置为只读。',\n unsaved: '未保存',\n save: '保存',\n saving: '保存中',\n saved: '已保存 ✓',\n saveFailed: '保存失败,请重试。',\n discard: '放弃',\n cancel: '取消',\n show: '显示',\n hide: '隐藏',\n usageTitle: '账户用量',\n usageRefresh: '刷新',\n usageRefreshing: '刷新中…',\n usageLoading: '正在获取账户用量…',\n usageNoKey: '配置 API 密钥后,这里会显示账户的用量与额度状态。',\n usageError: '用量获取失败',\n usageRequests: '请求',\n usageFailed: '失败',\n usageSuccessRate: '成功率',\n usageCost: '花费',\n usageTokens: 'Token',\n usageTokensIn: '入',\n usageTokensOut: '出',\n usageMonthly: '月额度',\n usagePurchased: '已购',\n usageFree: '赠送',\n usageFiveHour: '5 小时窗口',\n usageWeekly: '每周窗口',\n usageExceeded: '已超限',\n usageReset: '重置于',\n usagePartial: '部分端点数据不可用',\n usageKeyClear: '清除已存密钥',\n usageKeyClearStaged: '将清除(保存后生效)',\n usageUndoKeyClear: '撤销清除',\n usageKeyInvalid: 'API 密钥无效或已过期',\n usageKeyInvalidHint: '服务端拒绝了全部请求(401)。请检查该账户配置的密钥,或到 commandcode.ai 控制台重新生成。',\n usageServiceUnavailable: 'Command Code 服务暂时不可用',\n usageServiceUnavailableHint: '服务端返回了错误(5xx),稍后点击刷新重试。',\n usageNetworkError: '无法连接 Command Code 服务',\n usageNetworkHint: '所有请求都没有到达服务端。请检查网络连接或 API 地址设置。',\n usageUpdated: '更新于',\n usagePeriodEnd: '账期截止',\n usageActive: '当前使用',\n usageCooldown: '限额冷却中',\n usageInvalidKey: '密钥无效',\n usageUnconfigured: '该账户尚未配置 API 密钥。',\n updateAvailable: '可更新',\n updateHint: '已发布新版本,点击查看发布说明;更新插件后刷新本页,提示会自动消失。',\n loginTitle: '通过官方登录获取密钥',\n loginHintIdle: '不想手动创建密钥?点击登录后浏览器会打开 commandcode.ai 授权页,完成后密钥自动写入本机凭据服务,下次请求即生效。',\n loginButton: '登录 Command Code',\n loginStarting: '正在启动本地回调服务…',\n loginWaiting: '等待在浏览器中完成授权…',\n loginOpenLink: '打开授权页面 ↗',\n loginCancel: '取消登录',\n loginSuccess: '已登录为',\n loginUnavailable: '此环境暂不支持登录流程,请手动粘贴密钥。',\n loginDenied: '授权被拒绝。可重试,或手动粘贴密钥。',\n loginTimeout: '等待超时:未在窗口期内收到授权回调,请重试。',\n loginInvalidKey: '获取到的密钥未通过校验(401),请重试或手动粘贴。',\n loginNetwork: '无法连接 Command Code 服务校验密钥,请检查网络后重试。',\n loginStoreFailed: '密钥无法写入本机凭据服务,请手动粘贴。',\n loginCancelled: '登录已取消。',\n loginFailedGeneric: '登录失败,请重试或手动粘贴密钥。',\n cardTitle: 'Command Code 连接',\n cardRouteActive: '已启用',\n cardLoadingHint: '正在读取 Command Code 配置…',\n cardRegistrationHint: '此卡片随 Command Code 插件注册,需要较新版本的 DeepSeek Harness 才会显示完整内容。',\n cardConfiguredHint: 'API 密钥已就绪。如需更换密钥、添加多账户轮换、查看用量或修改 API 地址,请前往设置中的「Command Code」页。',\n}\n\nexport const en: Record<SettingsCommandCodeKey, string> = {\n nav: 'Command Code',\n title: 'Command Code',\n intro:\n 'Configure the Command Code Provider connection. The API key is stored only'\n + ' in the local credential service and never echoed; other fields are written'\n + ' to user settings and take effect on the next request.',\n apiKey: 'API key',\n apiKeyHint: 'Create one in the commandcode.ai console. Saving with this field'\n + ' blank keeps the stored key.',\n apiKeySet: 'Configured',\n apiKeyUnset: 'Not configured',\n apiKeyLocked: 'Key provided by a read-only source',\n apiBase: 'API base URL',\n apiBaseHint: 'Defaults to https://api.commandcode.ai; usually leave as-is.',\n workingDir: 'Working directory',\n workingDirHint: 'Optional. Leave blank to use the process cwd shown as the'\n + ' placeholder; fill in only to pin a specific path.',\n requestTimeoutMs: 'Request timeout (ms)',\n requestTimeoutMsHint: 'Time to wait for the first response byte; default 60000.',\n streamIdleTimeoutMs: 'Stream idle timeout (ms)',\n streamIdleTimeoutMsHint: 'How long a stalled stream is treated as dead; default 300000'\n + ' (deliberately generous — long-thinking models can stay silent for minutes).',\n advancedSettings: 'Advanced',\n advancedSettingsHint: 'Rarely touched options: API base URL, working directory, timeouts, and model filtering.',\n advancedOverriddenOne: '1 customized',\n advancedOverriddenMany: '{count} customized',\n advancedInvalid: 'A number in Advanced settings is not ready to save; expand to fix it.',\n filterModelsByPlan: 'Hide out-of-plan models',\n filterModelsByPlanHint: 'When on, the model picker lists only models your subscription'\n + ' includes; any on-demand credit balance shows the full catalog.',\n accountsTitle: 'Account rotation',\n accountsHint: 'When the active account hits its usage limit (429) or its key'\n + ' fails (401), requests switch to the next account; when every account is'\n + ' exhausted the error names the earliest window reset.',\n accountAdd: 'Add account',\n accountRemove: 'Remove',\n accountLabel: 'Account label',\n accountKey: 'API key',\n accountKeyHint: 'This account’s API key. Saving with the field blank keeps the stored key.',\n accountDefault: 'Default account',\n activeAccount: 'Active account',\n activeAccountAuto: 'Auto (first usable account)',\n activeAccountHint: 'Pin the preferred account; applies to the next request after saving.'\n + ' If the selected account is exhausted, requests still rotate to another usable account.',\n overridden: 'Overridden',\n reset: 'Reset',\n invalidNumber: 'Invalid number',\n numberTooSmall: 'Must be at least 1 (ms)',\n numberTooLarge: 'Above the allowed maximum (2147483647 ms)',\n readOnly: 'Settings are read-only.',\n unsaved: 'Unsaved',\n save: 'Save',\n saving: 'Saving',\n saved: 'Saved ✓',\n saveFailed: 'Save failed, please retry.',\n discard: 'Discard',\n cancel: 'Cancel',\n show: 'Show',\n hide: 'Hide',\n usageTitle: 'Account usage',\n usageRefresh: 'Refresh',\n usageRefreshing: 'Refreshing…',\n usageLoading: 'Fetching account usage…',\n usageNoKey: 'Configure an API key to see this account’s usage and credit state here.',\n usageError: 'Could not fetch usage',\n usageRequests: 'Requests',\n usageFailed: 'failed',\n usageSuccessRate: 'Success rate',\n usageCost: 'Spend',\n usageTokens: 'Tokens',\n usageTokensIn: 'in',\n usageTokensOut: 'out',\n usageMonthly: 'Monthly',\n usagePurchased: 'Purchased',\n usageFree: 'Free',\n usageFiveHour: '5-hour window',\n usageWeekly: 'Weekly window',\n usageExceeded: 'Exceeded',\n usageReset: 'Resets',\n usagePartial: 'Some endpoint data unavailable',\n usageKeyClear: 'Clear stored key',\n usageKeyClearStaged: 'Will be cleared on save',\n usageUndoKeyClear: 'Undo clear',\n usageKeyInvalid: 'API key invalid or expired',\n usageKeyInvalidHint: 'The server rejects every request (401). Check the key configured for this account, or generate a new one in the commandcode.ai console.',\n usageServiceUnavailable: 'The Command Code service is temporarily unavailable',\n usageServiceUnavailableHint: 'The server returned errors (5xx); try Refresh again later.',\n usageNetworkError: 'Could not reach the Command Code service',\n usageNetworkHint: 'No request reached the server. Check your network connection or the API base setting.',\n usageUpdated: 'Updated',\n usagePeriodEnd: 'Period ends',\n usageActive: 'Active',\n usageCooldown: 'Cooling down',\n usageInvalidKey: 'Invalid key',\n usageUnconfigured: 'No API key configured for this account yet.',\n updateAvailable: 'update available',\n updateHint: 'A newer version has been published; click for release notes. The notice disappears once the plugin is updated.',\n loginTitle: 'Sign in to fetch a key',\n loginHintIdle: 'Rather not create a key by hand? Sign in and your browser opens the commandcode.ai authorization page; the approved key is stored in the local credential service and applies to the next request.',\n loginButton: 'Sign in to Command Code',\n loginStarting: 'Starting the local callback server…',\n loginWaiting: 'Waiting for authorization in your browser…',\n loginOpenLink: 'Open the authorization page ↗',\n loginCancel: 'Cancel sign-in',\n loginSuccess: 'Signed in as',\n loginUnavailable: 'Sign-in is unavailable in this environment; paste the API key instead.',\n loginDenied: 'Authorization was denied. Try again or paste the key manually.',\n loginTimeout: 'Timed out waiting for the authorization callback; try again.',\n loginInvalidKey: 'The delivered key failed validation (401). Try again or paste it manually.',\n loginNetwork: 'Could not reach the Command Code service to validate the key; check your network and retry.',\n loginStoreFailed: 'The key could not be stored in the local credential service; paste it manually.',\n loginCancelled: 'Sign-in cancelled.',\n loginFailedGeneric: 'Sign-in failed; try again or paste the key manually.',\n cardTitle: 'Command Code connection',\n cardRouteActive: 'Active',\n cardLoadingHint: 'Loading the Command Code configuration…',\n cardRegistrationHint: 'This card is contributed by the Command Code plugin; a newer DeepSeek Harness is needed to show the full controls.',\n cardConfiguredHint: 'The API key is ready. To replace it, add account rotation, review usage, or change the API base, open the \"Command Code\" page in Settings.',\n}\n","/**\n * Browser half of the dsh-commandcode-provider bundle.\n *\n * Two responsibilities:\n *\n * 1. A \"Command Code\" settings page (a `settings.section` entry at the same\n * nav level as General / Models / Plugins). The Models page renders an\n * unknown-adapter-family card for the `commandcode` provider and disables\n * its submit, so the API key cannot be configured there; this page is the\n * dedicated surface. It writes the API key through the credentials domain\n * (the `COMMANDCODE_API_KEY` reference the plugin resolves via\n * `ctx.remote.credentials`) and the connection facts through the\n * `llm-commandcode` settings namespace, so a saved key or endpoint reaches\n * the very next request.\n *\n * 2. The Models-page provider card (settings.models.provider-card) and the\n * friendly image-gate error wrapper — see `./card.tsx` / `./sessions.ts`.\n * The wrapper is deliberately narrow: only the `model-unavailable` code is\n * rewritten, only when the message matches the image-session gate, and only\n * the message text changes.\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { createSnapshotStore } from './snapshot-store.ts'\n// Type-only imports that pull in the client-service augmentations\n// (`slots`/`remote`/`locale` on Context) and the `settings.section` SlotMap\n// entry (`settingsScope` arrives through dsh-client-ui-settings).\nimport type {} from '@deepseek-ai/dsh-api-remotes/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { installFriendlyImageError } from './sessions.ts'\nimport type { ConnectionLike } from './sessions.ts'\nimport { CommandCodeSettingsController, COMMANDCODE_NS, type SettingsPageState } from './settings.ts'\nimport type { HostDescriptionSource, SettingsPageApi } from './settings.ts'\nimport { adaptLegacyCredentials, type LegacyCredentialsApi } from './legacy-credentials.ts'\nimport { CommandCodeUsageController, type UsagePageState, type UsageRemote } from './usage.ts'\nimport { CommandCodeLoginController, type LoginPageState, type LoginRemote } from './login.ts'\nimport { USAGE_REMOTE_CONTRIBUTION } from '../usage-wire.ts'\nimport { LOGIN_REMOTE_CONTRIBUTION } from '../login-wire.ts'\nimport type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { CommandCodeSettingsPage } from './section.tsx'\nimport { CommandCodeProviderCard } from './card.tsx'\nimport { zh, en } from './locales.ts'\n\nexport { isImageSessionRejection, withFriendlyImageError } from './sessions.ts'\n\n/** CSS for the settings page, injected once (harness bundle convention). */\nconst PAGE_CSS = `\n.cc-section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}\n.cc-title{margin:0;font-size:18px;font-weight:600}\n.cc-intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px;line-height:1.5}\n.cc-readOnly{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.cc-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px}\n.cc-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}\n.cc-field+.cc-field{border-top:1px solid var(--dsw-alias-border-l2)}\n.cc-fieldHead{align-items:center;gap:8px;display:flex}\n.cc-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}\n.cc-badges{align-items:center;gap:8px;display:inline-flex}\n.cc-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}\n.cc-badgeMuted{white-space:nowrap;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-size:11px;line-height:17px}\n.cc-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}\n.cc-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.cc-reset:disabled{cursor:default;opacity:.5}\n.cc-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}\n.cc-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}\n.cc-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}\n/* Selects need their own treatment to sit flush with the text inputs:\n * the UA stylesheet renders <select> border-box (34px total vs the inputs'\n * 36px) and forces its own menulist text metrics, so drop the native\n * chrome entirely (appearance:none), restore content-box so the outer box\n * matches the inputs again, and draw the chevron ourselves. Longhand\n * background-* only — the shorthand would reset .cc-input's background. */\nselect.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box-sizing:content-box;padding-right:32px;background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23888f98' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 11px center}\n.cc-inputInvalid{border-color:var(--dsw-alias-label-error)}\n.cc-invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}\n/* The Advanced card: its header row is one full-width toggle button; the\n * chevron is two borders on a rotated square (no icon dependency). */\n.cc-advancedHead{align-items:center;gap:8px;display:flex;width:100%;padding:12px 0;background:0 0;border:none;cursor:pointer;font:inherit;text-align:left}\n.cc-advancedHead:hover .cc-advancedTitle{color:var(--dsw-alias-label-primary)}\n.cc-advancedTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}\n.cc-advancedSpacer{flex:1}\n.cc-chevron{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:8px;height:8px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg);transition:transform .15s ease}\n.cc-chevronUp{transform:rotate(-135deg);margin-bottom:-3px}\n.cc-advancedBody{flex-direction:column;display:flex}\n.cc-advancedBody>.cc-field:first-of-type{border-top:1px solid var(--dsw-alias-border-l2)}\n.cc-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.cc-footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}\n.cc-toggleRow{align-items:center;gap:8px;cursor:pointer;display:flex}\n.cc-toggleRow:has(.cc-toggle:disabled){cursor:default}\n.cc-toggle{appearance:none;flex-shrink:0;background:var(--dsw-alias-border-l2);border-radius:999px;width:30px;height:18px;margin:0;cursor:pointer;position:relative;transition:background .15s ease}\n.cc-toggle:checked{background:var(--dsw-alias-brand-primary)}\n.cc-toggle::after{content:'';background:#fff;border-radius:50%;width:14px;height:14px;position:absolute;top:2px;left:2px;transition:left .15s ease}\n.cc-toggle:checked::after{left:14px}\n.cc-toggle:disabled{cursor:default;opacity:.5}\n.cc-failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}\n.cc-usageCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:14px 16px;flex-direction:column;gap:12px;display:flex}\n.cc-usageHead{align-items:center;gap:8px;display:flex}\n.cc-usageTitle{color:var(--dsw-alias-label-primary);flex:1;margin:0;font-size:13px;font-weight:600;line-height:1.5}\n.cc-usageAccount{max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}\n.cc-usagePlan{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:600;line-height:17px}\n.cc-usagePlanStatus{white-space:nowrap;color:var(--dsw-alias-label-error);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}\n.cc-usageRefresh{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}\n.cc-usageRefresh:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.cc-usageRefresh:disabled{cursor:default;opacity:.5}\n.cc-usageHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.cc-usageError{align-items:center;gap:8px;color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5;display:flex}\n.cc-usageStats{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;display:grid}\n.cc-usageStat{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:8px;padding:8px 10px;flex-direction:column;gap:2px;display:flex}\n.cc-usageStatLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}\n.cc-usageStatValue{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}\n.cc-usageStatSub{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}\n.cc-usageWindows{flex-direction:column;gap:16px;display:flex}\n.cc-usageWindow{flex-direction:column;gap:6px;display:flex}\n.cc-usageWindowHead{align-items:baseline;gap:8px;display:flex}\n.cc-usageWindowLabel{color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;font-weight:500;line-height:1.5}\n.cc-usageWindowValue{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500;line-height:1.5}\n.cc-usageExceeded{color:var(--dsw-alias-label-error);font-size:11px;font-weight:500;line-height:1.5}\n.cc-usageBar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:6px}\n.cc-usageBarFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}\n.cc-usageBarFillWarn{background:var(--dsw-alias-label-error)}\n.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}\n.cc-usageMeta{align-items:center;gap:8px;display:flex}\n.cc-accountReport{flex-direction:column;gap:12px;display:flex}\n.cc-tabs{flex-wrap:wrap;gap:6px;display:flex}\n.cc-tab{align-items:center;font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:2px 10px;font-size:12px;line-height:18px;display:inline-flex;gap:6px}\n.cc-tab:hover:not(.cc-tabActive){color:var(--dsw-alias-label-primary)}\n.cc-tabActive{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}\n.cc-tabDotOk{background:var(--dsw-alias-brand-primary);border-radius:50%;width:6px;height:6px}\n.cc-tabDotWarn{background:#d97706;border-radius:50%;width:6px;height:6px}\n.cc-tabDotError{background:var(--dsw-alias-label-error);border-radius:50%;width:6px;height:6px}\n.cc-usageMetaSpacer{flex:1}\n.cc-usageUpdated{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}\n.cc-usagePartial{color:var(--dsw-alias-label-error);margin:0;font-size:11px;line-height:1.5}\n.cc-usageBlocked{border:1px solid var(--dsw-alias-label-error);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:4px}\n.cc-usageBlockedTitle{color:var(--dsw-alias-label-error);margin:0;font-size:13px;font-weight:600;line-height:1.5}\n.cc-usageBlockedHint{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:1.5}\n.cc-version{margin:4px 0 0;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n/* The update hint rides the footer version line: warning-tinted (with a\n * muted fallback for themes without the alias), quiet until hovered. */\n.cc-versionLink{color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary));text-decoration:none}\n.cc-versionLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-position:under}\n/* The login panel rides the connection card as one more field row; the\n * authorization link is the only branded element on it. */\n.cc-loginLink{color:var(--dsw-alias-brand-primary);text-decoration:none;font-size:12px;line-height:1.5}\n.cc-loginLink:hover{text-decoration:underline;text-underline-position:under}\n.cc-loginBusy{color:var(--dsw-alias-label-tertiary)}\n.cc-loginDone{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary))}\n.cc-loginError{color:var(--dsw-alias-label-error)}\n.cc-saved{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary));margin:0;font-size:12px;font-weight:500;line-height:1.5}\n.cc-badgeWarn{background:var(--dsw-alias-state-warning-secondary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary))}\n`\n\n/** Inject the page stylesheet once (idempotent per tag). */\nfunction injectPageCss(): void {\n if (typeof document === 'undefined') return\n const id = '@mars-sea/dsh-commandcode-provider/CommandCodeSettingsPage.module.css'\n if (document.querySelector(`style[data-plugin-css=\"${id}\"]`) !== null) return\n const tag = document.createElement('style')\n tag.dataset.plugin = '@mars-sea/dsh-commandcode-provider'\n tag.dataset.pluginCss = id\n tag.textContent = PAGE_CSS\n document.head.appendChild(tag)\n}\n\n/** Connection fields retained by pre-0.1.2 clients and absent from the current transport handle. */\ninterface LegacyConnectionLike extends ConnectionLike {\n api?: ConnectionLike['api'] & { credentials?: LegacyCredentialsApi }\n hostDescription?: HostDescriptionSource\n}\n\n/**\n * Client plugin body. Gates on the services shared by both client generations\n * (`slots`, `locale`, `connection`, `remote`, `settingsScope`). Current clients\n * mount the page after `remote.credentials` appears; legacy clients mount it\n * from the connection ApiProxy credential face.\n */\nexport function apply(ctx: Context): void {\n injectPageCss()\n\n const connection = ctx.get('connection') as LegacyConnectionLike | undefined\n if (connection !== undefined) {\n // The wrapper is reached from a non-React path that has no `t` in scope;\n // it reads the active client locale at call time, so a language switch\n // immediately applies to the next selectModel failure. On legacy builds\n // it wraps `connection.api.sessions`; 0.1.2 replaced that façade with\n // `remote.session`, so the helper safely skips this UX-only rewrite there\n // instead of preventing the whole plugin from activating.\n installFriendlyImageError(connection, () => ctx.locale.getLocale().active === 'zh' ? 'zh' : 'en')\n }\n\n // The \"Command Code\" settings page: register the section once the\n // `settings.section` declaration is on the ledger (ui-settings-general\n // owns the shell; registration order relative to it is not constrained —\n // `slots.inject` waits for the declaration).\n ctx.effect(() => ctx.locale.register('settings.commandcode', { zh, en }), 'dsh-commandcode-provider: page copy')\n\n const legacyApi = adaptLegacyCredentials(connection?.api?.credentials)\n if (legacyApi !== undefined) {\n applyClientSurfaces(ctx, legacyApi, connection?.hostDescription)\n return\n }\n\n // DSH 0.1.2 exposes credentials through a Typert Remote namespace. Keep it\n // optional at the root so a legacy client without `remote.credentials` can\n // still activate through the ApiProxy branch above.\n ctx.inject(['remote.credentials'], (remoteCtx) => {\n const credentials = (remoteCtx.remote as unknown as {\n credentials: SettingsPageApi['credentials']\n }).credentials\n applyClientSurfaces(remoteCtx, { credentials })\n })\n}\n\n/** Mount the one shared UI implementation over either credential transport. */\nfunction applyClientSurfaces(\n ctx: Context,\n api: SettingsPageApi,\n hostDescription?: HostDescriptionSource,\n): void {\n const scope = ctx.settingsScope.bind<Record<string, unknown>>({ namespace: COMMANDCODE_NS })\n const controller = new CommandCodeSettingsController(scope, api, hostDescription)\n ctx.effect(() => () => controller.dispose(), 'dsh-commandcode-provider: settings controller')\n const store = createSnapshotStore<SettingsPageState>(controller.state())\n controller.subscribe(() => store.set(controller.state()))\n ctx.effect(\n () => (ctx.remote as unknown as {\n $on(event: 'credentials/reference-updated', listener: (ref: string) => void): () => void\n }).$on('credentials/reference-updated', () => { controller.refreshCredentials() }),\n 'dsh-commandcode-provider: credential invalidations',\n )\n\n // The account-usage card + login panel: mount the shared Remote contribution\n // (one mount carries every endpoint this plugin serves — report and login —\n // so the Client's bookkeeping stays 1:1 with the Host's single registry\n // registration), then resolve the `remote.commandcode` namespace through a\n // scoped inject. Cordis only serves services a fiber declares in `inject`,\n // and the namespace service exists only after the mount — a static inject\n // would deadlock the plugin (the mounter would wait for its own mount), so\n // the inject is registered dynamically once the mount lands. A Host half\n // that predates the Remote fails the calls instead, and the surfaces render\n // their error branches.\n let usageNamespace: (typeof ctx.remote)['commandcode'] | undefined\n let usageMountError: string | undefined\n const contribution: TypertRemoteContribution = {\n package: USAGE_REMOTE_CONTRIBUTION.package,\n descriptors: [...USAGE_REMOTE_CONTRIBUTION.descriptors, ...LOGIN_REMOTE_CONTRIBUTION.descriptors],\n }\n ctx.effect(() => {\n let cancelled = false\n let unmount: (() => Promise<void>) | undefined\n void ctx.remote.$mount(contribution).then((dispose: () => Promise<void>) => {\n if (cancelled) {\n void dispose()\n return\n }\n unmount = dispose\n ctx.inject(['remote.commandcode'], (namespaceCtx) => {\n usageNamespace = namespaceCtx.remote.commandcode\n namespaceCtx.effect(() => () => {\n usageNamespace = undefined\n }, 'dsh-commandcode-provider: usage namespace')\n })\n }, (error: unknown) => {\n // A mount failure (e.g. a harness without the Remote mount) leaves the\n // namespace unset; keep the reason so the card can surface it.\n usageMountError = error instanceof Error ? error.message : String(error)\n })\n return () => {\n cancelled = true\n usageNamespace = undefined\n if (unmount !== undefined) void unmount()\n }\n }, 'dsh-commandcode-provider: usage remote')\n const usageRemote: UsageRemote = {\n report: async () => {\n const namespace = usageNamespace\n if (namespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode/report remote is not mounted' } }\n }\n return namespace.report()\n },\n }\n const usageController = new CommandCodeUsageController(usageRemote)\n ctx.effect(() => () => usageController.dispose(), 'dsh-commandcode-provider: usage controller')\n const usageStore = createSnapshotStore<UsagePageState>(usageController.state())\n usageController.subscribe(() => usageStore.set(usageController.state()))\n\n // The login panel: same namespace, three endpoints; the key never crosses\n // to the browser — the Host validates and stores it through the credentials\n // seam, and a landed login re-reads the credential badges + usage card.\n const loginRemote: LoginRemote = {\n loginBegin: async () => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginBegin()\n },\n loginStatus: async () => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginStatus()\n },\n loginCancel: async () => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginCancel()\n },\n }\n const loginController = new CommandCodeLoginController(() => loginRemote)\n ctx.effect(() => () => loginController.dispose(), 'dsh-commandcode-provider: login controller')\n const loginStore = createSnapshotStore<LoginPageState>(loginController.state())\n let lastLoginPhase = loginController.state().phase\n loginController.subscribe(() => {\n const phase = loginController.state().phase\n // A landed login stored the key Host-side behind the page's back; the\n // badges must follow and the account card can finally fetch.\n if (phase === 'success' && lastLoginPhase !== 'success') {\n controller.refreshCredentials()\n void usageController.refresh()\n }\n lastLoginPhase = phase\n loginStore.set(loginController.state())\n })\n\n const injected = () => ({\n hooks: { commandCodeSettings: store, commandCodeUsage: usageStore, commandCodeLogin: loginStore },\n edit: (field: string, text: string) => controller.edit(field, text),\n resetField: (field: string) => controller.resetField(field),\n // A landed save can change the key or endpoint the usage endpoints read,\n // so the account card refetches; a failed save keeps the old data.\n save: () => void controller.save().then(() => {\n const settled = controller.state()\n if (!settled.failed && settled.anyAccountConfigured) void usageController.refresh()\n }),\n discard: () => controller.discard(),\n refreshUsage: () => void usageController.refresh(),\n beginLogin: () => void loginController.begin(),\n cancelLogin: () => void loginController.cancel(),\n addAccount: () => controller.addAccount(),\n removeAccount: (id: string) => controller.removeAccount(id),\n editAccountLabel: (id: string, text: string) => controller.editAccountLabel(id, text),\n editAccountKey: (id: string, text: string) => controller.editAccountKey(id, text),\n toggleKeyClear: (id: string) => controller.toggleKeyClear(id),\n })\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'commandcode',\n order: 12,\n label: () => ctx.locale.bind('settings.commandcode')('nav'),\n locale: 'settings.commandcode',\n inject: injected,\n }, CommandCodeSettingsPage))\n\n // The Models-page provider card (dsh 0.1.2-alpha.2): a keyed slot the\n // Models section dispatches with `entryKey = settingsNs` on every provider\n // card of an adapter family. Registering under `llm-commandcode` renders\n // the card's extension area on every Command Code row — including the\n // first-run setup posture, exactly where a user without a key lands.\n // The registration carries its own inject face (store hooks + actions)\n // because the declaring entry is ui-settings-models', not ours; the `t`\n // seat comes from the registration's own `locale` namespace.\n //\n // On dsh builds without this slot the declaration never exists and\n // `slots.inject` never fires its callback — the registration silently\n // does not happen, and nothing else about the plugin changes.\n ctx.slots.inject('settings.models.provider-card', () => ctx.slots.register({\n name: 'settings.models.provider-card',\n key: 'llm-commandcode',\n locale: 'settings.commandcode',\n inject: () => ({\n hooks: { commandCodeSettings: store, commandCodeLogin: loginStore },\n edit: (field: string, text: string) => controller.edit(field, text),\n save: () => void controller.save().then(() => {\n const settled = controller.state()\n if (!settled.failed && settled.anyAccountConfigured) void usageController.refresh()\n }),\n beginLogin: () => void loginController.begin(),\n cancelLogin: () => void loginController.cancel(),\n }),\n }, CommandCodeProviderCard))\n}\n\nexport const inject: readonly string[] = [\n 'slots',\n 'locale',\n 'connection',\n 'remote',\n 'settingsScope',\n]\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["numberField","booleanField","reject","pkg.version","useState","loginFailureCopy","Menu","Button","useState","useRef"],"sources":["../src/client/snapshot-store.ts","../src/command-locales.ts","../src/client/sessions.ts","../src/client/settings.ts","../src/client/legacy-credentials.ts","../src/client/usage.ts","../src/client/login.ts","../src/usage-wire.ts","../src/login-wire.ts","../package.json","../src/client/version.ts","../src/client/update.ts","../src/client/section.tsx","../src/client/card.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * A tiny observable snapshot store — the `getSnapshot` / `subscribe` / `set`\n * triple React's `useSyncExternalStore` consumes through the harness slot kit\n * (the host builds each slot's `useFoo(selector)` hook from one of these).\n *\n * Vendored on purpose. DSH 0.1.2 seeds `@deepseek-ai/dsh-client-store` as a\n * platform module, but older Web shells do not and the package is not yet\n * published independently on npm. Inlining the small subset used here avoids\n * a version-specific module request while preserving the slot-hook contract.\n */\n\n/** Mutable observable snapshot consumed by slot hooks. */\nexport interface SnapshotStore<T> {\n getSnapshot(): T\n subscribe(listener: () => void): () => void\n set(value: T): void\n}\n\n/** Notify every subscriber without letting one faulty UI consumer suppress the rest. */\nfunction notifyListeners(listeners: ReadonlySet<() => void>): void {\n for (const listener of listeners) {\n try {\n listener()\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] snapshot subscriber failed:', error)\n }\n }\n}\n\n/** Create one observable snapshot store. */\nexport function createSnapshotStore<T>(initial: T): SnapshotStore<T> {\n let snapshot = initial\n const listeners = new Set<() => void>()\n return {\n getSnapshot: () => snapshot,\n subscribe(listener: () => void) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n set(value: T) {\n if (Object.is(value, snapshot)) return\n snapshot = value\n notifyListeners(listeners)\n },\n }\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 * Friendly-error wrapper for the harness's image-session gate.\n *\n * The host rejects switching to a text-only model while the session already\n * contains images with a `model-unavailable` error\n * (`dsh-host-apiproxy`'s `session.selectModel` handler). That rejection is\n * intentional and cannot be relaxed from the plugin side — the adapter's\n * `inputModalities` is exactly what makes the guard work. What we CAN do is\n * make the error message friendlier: wrap the shared\n * `connection.api.sessions.selectModel` face so a `model-unavailable`\n * rejection shows a clear, actionable hint (with the requested model name)\n * instead of the raw English harness message.\n *\n * The wrapper is deliberately narrow: only the `model-unavailable` code is\n * rewritten, only when the message matches the image-session gate, and only\n * the message text changes — the error code and details pass through\n * untouched so any caller that switches on `error.code` keeps working.\n *\n * The wire types are spelled structurally here (not imported from\n * `@deepseek-ai/dsh-host-apiproxy`) so this client bundle does not drag an\n * extra peer dependency into the package; the shapes are stable and the\n * client build inlines them anyway.\n *\n * The wrapper takes a `getLocale` thunk because it is reached from a\n * non-React path that has no `t` in scope; the supplied thunk reads the\n * active locale at call time (typically `() => ctx.locale.getLocale().active`\n * in the client entry), and the message template lives in the shared\n * `commandcodeCommand` dictionary used by the Host-side `/commandcode`\n * command — the same bilingual surface serves both.\n *\n * This module is deliberately free of React and other client-platform\n * imports so the node test runner can exercise it directly.\n */\n\nimport { commandcodeCommand, type LocaleId } from '../command-locales.ts'\n\n/** The `model-unavailable` error details: provider + model id. */\ninterface ModelUnavailableDetails {\n provider: string\n model: string\n}\n\n/** The narrow slice of the RPC error we need to inspect and rewrite. */\ninterface RpcErrorLike {\n code: string\n message: string\n details?: ModelUnavailableDetails\n}\n\n/**\n * The narrow slice of a unary RPC result we need to inspect and rewrite.\n * The wire shape from `sessions.selectModel` (via `AbstractApiClient.callUnary`)\n * is the full envelope `{ rpcId, result: { ok, error? } }` — the error lives\n * under `result.result`, not at the top level. `RpcResultLike` models that.\n */\ninterface RpcResultLike {\n rpcId: string\n result:\n | { ok: true; value?: unknown }\n | { ok: false; error: RpcErrorLike }\n}\n\n/** One selectModel call: payload in, envelope out. */\ntype SelectModelCall = (\n payload: { sessionId: string; provider: string; model: string; reasoningEffort?: string },\n signal?: AbortSignal,\n) => Promise<RpcResultLike>\n\n/** The shared sessions wire face we wrap. */\ninterface SessionsLike {\n selectModel: SelectModelCall\n}\n\n/** Whether a selectModel rejection is the harness's image-session gate. */\nexport function isImageSessionRejection(\n result: RpcResultLike,\n): result is RpcResultLike & { result: { ok: false; error: RpcErrorLike } } {\n return (\n !result.result.ok &&\n result.result.error.code === 'model-unavailable' &&\n result.result.error.message.includes('does not accept image input')\n )\n}\n\n/** Wrap the shared sessions API so selectModel failures read friendlier. */\nexport function withFriendlyImageError(\n sessions: SessionsLike,\n getLocale: () => LocaleId,\n): SessionsLike {\n const selectModel = sessions.selectModel.bind(sessions)\n return {\n ...sessions,\n selectModel: async (payload, signal) => {\n const result = await selectModel(payload, signal)\n if (!isImageSessionRejection(result)) return result\n const model = result.result.error.details?.model ?? payload.model\n const template = commandcodeCommand[getLocale()].imageGate\n ?? commandcodeCommand.en.imageGate\n return {\n ...result,\n result: {\n ...result.result,\n error: {\n ...result.result.error,\n message: template.replace('{model}', model),\n },\n },\n }\n },\n }\n}\n\n/**\n * The pre-0.1.2 connection handle that exposed the shared session API under\n * `connection.api.sessions`. In 0.1.2 the connection service became a\n * transport/generation handle and model selection moved to `remote.session`,\n * so this legacy field is deliberately optional.\n */\nexport interface ConnectionLike {\n api?: { sessions?: SessionsLike }\n}\n\n/**\n * Install the friendly-error wrapper when a legacy sessions face is present.\n *\n * @returns whether the wrapper was installed. The rewrite is only UX polish;\n * a 0.1.2 connection has no `api.sessions`, and its absence must never block\n * the plugin from mounting its settings, credential, or usage surfaces.\n */\nexport function installFriendlyImageError(\n connection: ConnectionLike,\n getLocale: () => LocaleId,\n): boolean {\n const api = connection.api\n const sessions = api?.sessions\n if (api === undefined || sessions === undefined || typeof sessions.selectModel !== 'function') return false\n api.sessions = withFriendlyImageError(sessions, getLocale)\n return true\n}\n","/**\n * Browser controller for the \"Command Code\" settings page.\n *\n * The page lives at the same settings-nav level as General / Models / Plugins\n * (a `settings.section` entry, id `commandcode`). It exists because the\n * Models page renders an unknown-adapter-family card for the `commandcode`\n * provider and deliberately disables its submit — the API key cannot be\n * configured there. This page owns the connection facts the plugin resolves\n * per request:\n *\n * - API key -> written through the credentials domain under the reference\n * the plugin resolves (`apiKeyEnv`, default\n * `COMMANDCODE_API_KEY`). The literal never rides a response,\n * so the control only reports whether one is configured.\n * - API base -> the `llm-commandcode` settings namespace (`apiBase`), same\n * namespace the Models page card addresses.\n * - Working dir, request/stream timeouts -> the same namespace.\n *\n * The controller mirrors the plugin-card pattern from the harness's own\n * settings UI: it binds the `llm-commandcode` namespace through the\n * `settingsScope` service, keeps a staged draft of edits, and writes them on\n * save through `scope.set` / the credentials domain. The Host stays the\n * single fact source; the snapshot is republished after each accepted write.\n *\n * This module is deliberately free of JSX — it only produces the state face\n * the React component renders.\n */\n\n/** The settings namespace the plugin registers (host half, src/index.ts). */\nexport const COMMANDCODE_NS = 'llm-commandcode'\n/** Default credential reference the plugin resolves when none is named. */\nexport const DEFAULT_API_KEY_REF = 'COMMANDCODE_API_KEY'\n\n/** The settings-scope snapshot fields consumed by this controller. */\nexport interface SettingsScopeSnapshot<T> {\n status: 'loading' | 'ready' | 'unavailable'\n value: T | undefined\n base: unknown\n user: unknown\n revision: number | undefined\n writable: boolean\n mode: 'host' | 'memory'\n}\n\n/** Current settings-scope service face used without importing a browser plugin value. */\nexport interface SettingsScope<T> {\n getSnapshot(): SettingsScopeSnapshot<T>\n subscribe(listener: () => void): () => void\n set(field: string, value: unknown): Promise<void>\n unset(field: string): Promise<void>\n}\n\n/** Result envelope returned by one current Typert Remote call. */\ninterface RemoteResult<T> {\n ok: boolean\n value?: T\n error?: { message: string }\n}\n\n/** Credential facts returned without exposing the credential value. */\ninterface CredentialInfo {\n configured: boolean\n writable: boolean\n}\n\n/** The narrow slice of the wire face this controller needs. */\nexport interface SettingsPageApi {\n /** Credential methods exposed by the current Typert Remote namespace. */\n credentials: {\n describe(refs: string[]): Promise<RemoteResult<Record<string, CredentialInfo>>>\n set(ref: string, value: string): Promise<RemoteResult<void>>\n unset(ref: string): Promise<RemoteResult<void>>\n }\n /**\n * The model catalog for the routing-rule editor (Host-side). Absent on\n * legacy transports without the Remote mount — the editor degrades to the\n * empty-catalog state.\n */\n models?(): Promise<RemoteResult<{ models: CatalogModelOption[] }>>\n}\n\n/** The Host-description observable the page reads the process cwd from. */\nexport interface HostDescriptionSource {\n getSnapshot(): { cwd?: string } | undefined\n subscribe(fn: () => void): () => void\n}\n\n/** One editable text field's staged state (blank = keep stored value). */\nexport interface StagedField {\n /** Live draft text the input shows. */\n text: string\n /** Whether the user explicitly cleared the field (reset to inherited). */\n clear: boolean\n /** Whether the user layer carries this field (marks it overridden). */\n overridden: boolean\n /** Whether the staged draft fails to parse (blocks save). */\n invalid: boolean\n /**\n * Why the draft is invalid — a non-number (`format`) or an out-of-range\n * number (`tooSmall`/`tooLarge`); undefined when valid.\n */\n invalidReason: InvalidReason | undefined\n}\n\n/** Why a staged draft fails validation (drives the per-field error copy). */\nexport type InvalidReason = 'format' | 'tooSmall' | 'tooLarge'\n\n/** One extra account row's staged state (the default account uses `apiKey`). */\nexport interface AccountItemState {\n /** Stable id — the account's credential reference. */\n id: string\n /** Credential reference this account's key lives under. */\n ref: string\n /** Label draft text (the stored/generated label until edited). */\n label: string\n /** The API key draft (write-only; starts blank, never echoes the stored key). */\n keyText: string\n /** Whether a key is stored for this account (Host-reported). */\n configured: boolean\n /** Whether the credentials domain can store the key. */\n writable: boolean\n /** Staged for addition (not yet saved). */\n added: boolean\n /** Staged for key removal on the next save (the stored key is bad/unwanted). */\n clearStaged: boolean\n}\n\n/** One model → account routing rule row's staged state. */\nexport interface RuleItemState {\n /** Stable row id (`rule-N` for stored rows, `new-N` for staged adds). */\n id: string\n /** Model ids the rule routes to the account (multi-select). */\n models: string[]\n /** Account slot id the rule routes matching models to. */\n account: string\n /** Staged for addition (not yet saved). */\n added: boolean\n}\n\n/** One selectable catalog model in the routing-rule editor. */\nexport interface CatalogModelOption {\n id: string\n name: string\n}\n\n/** The page's full state face, projected from the scope + drafts + credential. */\nexport interface SettingsPageState {\n /** Whether the namespace snapshot is ready. */\n available: boolean\n /** Whether the Host document accepts writes. */\n writable: boolean\n /** Whether the API key is currently configured (Host-reported). */\n apiKeyConfigured: boolean\n /** Whether ANY account (default or extra) has a stored key — gates the usage card. */\n anyAccountConfigured: boolean\n /** Whether the credentials domain can store the key. */\n apiKeyWritable: boolean\n /** The API key draft (write-only; starts blank, never echoes the stored key). */\n apiKey: StagedField\n /** Whether the default account's stored key is staged for removal on the next save. */\n apiKeyClearStaged: boolean\n /** apiBase draft. */\n apiBase: StagedField\n /** workingDir draft. */\n workingDir: StagedField\n /**\n * The working directory a blank `workingDir` resolves to: the Host\n * process cwd (`host.describe().cwd`). Shown as the field's placeholder so\n * the user sees what \"leave it empty\" means — no configuration needed.\n */\n defaultWorkingDir: string | undefined\n /** requestTimeoutMs draft. */\n requestTimeoutMs: StagedField\n /** streamIdleTimeoutMs draft. */\n streamIdleTimeoutMs: StagedField\n /**\n * filterModelsByPlan draft, staged as `'true'`/`'false'`/`''` (unset). The\n * component renders it as a toggle; `''` means \"inherit the default\" (on).\n */\n filterModelsByPlan: StagedField\n /**\n * The manually selected active account, staged as a slot id (`default`\n * or an extra account's credential reference); `''` means \"auto — first\n * usable account\". The component renders it as a select.\n */\n activeAccount: StagedField\n /** Extra accounts (multi-account rotation), in rotation order. */\n accounts: AccountItemState[]\n /** Refs of stored accounts staged for removal (the usage card hides them). */\n accountsRemoving: string[]\n /** Model → account routing rules, in list order (first match wins). */\n rules: RuleItemState[]\n /** The catalog the rule editor offers (Host-side, empty until loaded). */\n catalogModels: CatalogModelOption[]\n /** Whether the catalog fetch failed (rule editor falls back to typing). */\n catalogFailed: boolean\n /** Whether any staged edit differs from the stored section. */\n dirty: boolean\n /** Whether a staged numeric field fails to parse (save blocked). */\n invalid: boolean\n /** Whether a save is in flight. */\n saving: boolean\n /** Whether the last save failed (drafts retained for correction). */\n failed: boolean\n /**\n * Monotonic counter bumped once per accepted save. The component watches it\n * to flash the \"Saved ✓\" affordance (timing lives in the component; the\n * controller stays a plain state machine with no timers).\n */\n savedCount: number\n}\n\n/** Parsed outcome of one field's draft. */\ntype Parsed =\n | { kind: 'set'; value: string | number | boolean }\n | { kind: 'clear' }\n | { kind: 'invalid'; reason: InvalidReason }\n\n/** One field's staged draft (internal; the public face adds derived flags). */\ninterface Staged {\n text: string\n clear: boolean\n}\n\n/** A field conversion spec. */\ninterface FieldSpec {\n field: string\n format(value: unknown): string\n parse(text: string): Parsed\n}\n\n/** A free-text field; an empty draft clears it. */\nfunction textField(field: string): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'string' ? value : ''),\n parse: (text) => {\n const trimmed = text.trim()\n return trimmed === '' ? { kind: 'clear' } : { kind: 'set', value: trimmed }\n },\n }\n}\n\n/**\n * A numeric field; an empty draft clears it, anything non-numeric blocks\n * save, and an optional inclusive `bounds` range rejects out-of-range values\n * with a specific reason (the Host schema would reject them at save time with\n * only a generic failure — catching it here names the problem while typing).\n * Decimals pass: the Host schema is `z.number()` too, and a fractional\n * millisecond value is harmless even if pointless.\n */\nfunction numberField(field: string, bounds?: { min?: number; max?: number }): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'number' ? String(value) : ''),\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return { kind: 'clear' }\n const parsed = Number(trimmed)\n if (!Number.isFinite(parsed)) return { kind: 'invalid', reason: 'format' }\n if (bounds?.min !== undefined && parsed < bounds.min) return { kind: 'invalid', reason: 'tooSmall' }\n if (bounds?.max !== undefined && parsed > bounds.max) return { kind: 'invalid', reason: 'tooLarge' }\n return { kind: 'set', value: parsed }\n },\n }\n}\n\n/**\n * A boolean field, staged as the strings `'true'`/`'false'` (an empty draft\n * clears it). The component renders a toggle and only ever stages these two\n * strings; anything else blocks save.\n */\nfunction booleanField(field: string): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'boolean' ? String(value) : ''),\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return { kind: 'clear' }\n if (trimmed === 'true') return { kind: 'set', value: true }\n if (trimmed === 'false') return { kind: 'set', value: false }\n return { kind: 'invalid', reason: 'format' }\n },\n }\n}\n\n/**\n * Inclusive bounds for the millisecond timeout fields, mirroring the Host\n * Config schema (`z.number().min(1).max(MAX_TIMER_DELAY_MS)` in src/index.ts;\n * `MAX_TIMER_DELAY_MS` is dsh-timeout's 2^31-1 timer ceiling). The client\n * bundle cannot import the node-side package, so the bound is pinned here —\n * the host remains the final gate.\n */\nexport const MIN_TIMEOUT_MS = 1\nexport const MAX_TIMEOUT_MS = 2147483647\n\n/** The fields this page edits inside the `llm-commandcode` namespace. */\nconst SECTION_FIELDS: FieldSpec[] = [\n textField('apiBase'),\n textField('workingDir'),\n numberField('requestTimeoutMs', { min: MIN_TIMEOUT_MS, max: MAX_TIMEOUT_MS }),\n numberField('streamIdleTimeoutMs', { min: MIN_TIMEOUT_MS, max: MAX_TIMEOUT_MS }),\n booleanField('filterModelsByPlan'),\n textField('activeAccount'),\n]\n\n/** Whether two model-id lists are equal as sets (order-insensitive). */\nfunction sameModels(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) return false\n const set = new Set(a)\n return b.every((id) => set.has(id))\n}\n\n/**\n * Controller bridging the `llm-commandcode` scope and the credentials domain\n * onto the page. Public API mirrors the harness's CardForm actions, so the\n * component stays thin.\n */\nexport class CommandCodeSettingsController {\n private readonly scope: SettingsScope<Record<string, unknown>>\n private readonly api: SettingsPageApi\n private readonly specs = new Map(SECTION_FIELDS.map((spec) => [spec.field, spec]))\n private readonly staged = new Map<string, Staged>()\n private readonly listeners = new Set<() => void>()\n private readonly disposers: Array<() => void> = []\n private disposed = false\n private defaultWorkingDir: string | undefined\n /** The credential reference the default account resolves. */\n private credentialRef = DEFAULT_API_KEY_REF\n /** Host-reported configured/writable state per credential reference. */\n private readonly credentialStates = new Map<string, { configured: boolean; writable: boolean }>()\n /** Staged account additions (not yet saved). */\n private addedAccounts: Array<{ label: string; ref: string }> = []\n /** Staged removals of stored extra accounts, by credential reference. */\n private readonly removedRefs = new Set<string>()\n /** Staged label drafts, by credential reference. */\n private readonly labelDrafts = new Map<string, string>()\n /** Staged key drafts, by credential reference (blank = keep stored key). */\n private readonly keyDrafts = new Map<string, string>()\n /** Credential references staged for removal on the next save. */\n private readonly keyClears = new Set<string>()\n /** Staged model→account routing rules (not yet saved). */\n private addedRules: Array<{ models: string[]; account: string }> = []\n /** Staged edits to stored routing rules, by stored row id. */\n private readonly ruleDrafts = new Map<string, { models: string[]; account: string }>()\n /** Stored routing rule rows staged for removal. */\n private readonly removedRuleIds = new Set<string>()\n /** The catalog the rule editor offers (Host-side). */\n private catalogModels: CatalogModelOption[] = []\n private catalogFailed = false\n private saving = false\n private failed = false\n private savedCount = 0\n\n /**\n * @param scope - bound scope for the `llm-commandcode` namespace.\n * @param api - credentials wire face.\n * @param hostDescription - the Host-description observable whose `cwd` is\n * shown as the placeholder a blank `workingDir` field resolves to.\n */\n constructor(\n scope: SettingsScope<Record<string, unknown>>,\n api: SettingsPageApi,\n hostDescription?: HostDescriptionSource,\n ) {\n this.scope = scope\n this.api = api\n this.disposers.push(scope.subscribe(() => {\n this.recomputeCredentialRef()\n void this.describeAll()\n this.publish()\n }))\n if (hostDescription !== undefined) {\n this.defaultWorkingDir = hostDescription.getSnapshot()?.cwd\n this.disposers.push(hostDescription.subscribe(() => {\n if (this.disposed) return\n const cwd = hostDescription.getSnapshot()?.cwd\n if (cwd !== this.defaultWorkingDir) {\n this.defaultWorkingDir = cwd\n this.publish()\n }\n }))\n }\n this.recomputeCredentialRef()\n void this.describeAll()\n this.refreshCatalog()\n }\n\n /** Release every subscription held on external sources. Idempotent. */\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n for (const dispose of this.disposers) dispose()\n this.disposers.length = 0\n this.listeners.clear()\n }\n\n /**\n * The credential reference the section names, or the provider default. A\n * user who renamed `apiKeyEnv` in `settings.yaml` (or the composition\n * config) gets a page that addresses the renamed ref instead of silently\n * writing the default — mirroring the Models page's `refFor()`.\n */\n private recomputeCredentialRef(): void {\n const snapshot = this.scope.getSnapshot()\n const named = typeof snapshot.value?.apiKeyEnv === 'string' && snapshot.value.apiKeyEnv.length > 0\n ? snapshot.value.apiKeyEnv\n : DEFAULT_API_KEY_REF\n if (named === this.credentialRef) return\n this.credentialRef = named\n this.credentialStates.delete(named)\n }\n\n /** Subscribe to state projections. @returns the disposer. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** Build the current page state face. */\n state(): SettingsPageState {\n const snapshot = this.scope.getSnapshot()\n const plan = this.plan()\n const credential = this.credentialStates.get(this.credentialRef)\n const accounts = this.effectiveAccounts()\n return {\n available: snapshot.status === 'ready',\n writable: snapshot.writable,\n apiKeyConfigured: credential?.configured ?? false,\n anyAccountConfigured: (credential?.configured ?? false) || accounts.some((account) => account.configured),\n apiKeyWritable: credential?.writable ?? true,\n apiKey: {\n text: this.staged.get('apiKey')?.text ?? '',\n clear: false,\n overridden: false,\n invalid: false,\n invalidReason: undefined,\n },\n apiKeyClearStaged: this.keyClears.has(this.credentialRef),\n apiBase: this.field('apiBase'),\n workingDir: this.field('workingDir'),\n defaultWorkingDir: this.defaultWorkingDir,\n requestTimeoutMs: this.field('requestTimeoutMs'),\n streamIdleTimeoutMs: this.field('streamIdleTimeoutMs'),\n filterModelsByPlan: this.field('filterModelsByPlan'),\n activeAccount: this.field('activeAccount'),\n accounts,\n accountsRemoving: [...this.removedRefs],\n rules: this.effectiveRules(),\n catalogModels: this.catalogModels,\n catalogFailed: this.catalogFailed,\n dirty: plan.length > 0 || this.accountsDirty() || this.rulesDirty(),\n invalid: plan.some((item) => item.run === undefined),\n saving: this.saving,\n failed: this.failed,\n savedCount: this.savedCount,\n }\n }\n\n /** Stage a new extra account (saved on the next `save()`). */\n addAccount(): void {\n const used = new Set([\n this.credentialRef,\n ...this.storedExtras().map((extra) => extra.ref),\n ...this.addedAccounts.map((extra) => extra.ref),\n ])\n let n = 2\n while (used.has(`COMMANDCODE_API_KEY_${n}`)) n += 1\n const index = this.storedExtras().length + this.addedAccounts.length + 2\n this.addedAccounts.push({ label: `Account ${index}`, ref: `COMMANDCODE_API_KEY_${n}` })\n this.failed = false\n void this.describeAll()\n this.publish()\n }\n\n /** Stage one extra account's removal (or drop an unsaved addition). */\n removeAccount(id: string): void {\n const addedIndex = this.addedAccounts.findIndex((extra) => extra.ref === id)\n if (addedIndex >= 0) this.addedAccounts.splice(addedIndex, 1)\n else this.removedRefs.add(id)\n this.labelDrafts.delete(id)\n this.keyDrafts.delete(id)\n // A pinned active account that is going away must not linger as a ghost\n // selection: stage its clear alongside the removal (the host would fall\n // back to rotation order, but the stored value would be meaningless).\n const stagedActive = this.staged.get('activeAccount')\n const activeValue = stagedActive !== undefined\n ? stagedActive.clear ? '' : stagedActive.text\n : typeof this.sectionValue('activeAccount') === 'string' ? this.sectionValue('activeAccount') as string : ''\n if (activeValue === id) {\n this.staged.set('activeAccount', { text: '', clear: true })\n }\n this.failed = false\n this.publish()\n }\n\n /** Stage one extra account's label draft. */\n editAccountLabel(id: string, text: string): void {\n this.labelDrafts.set(id, text)\n this.failed = false\n this.publish()\n }\n\n /** Stage one extra account's key draft (blank keeps the stored key). */\n editAccountKey(id: string, text: string): void {\n this.keyDrafts.set(id, text)\n // Typing a replacement cancels a staged removal — the two intents are\n // mutually exclusive (replace vs remove), and a staged clear would\n // otherwise silently discard what is being typed.\n this.keyClears.delete(id)\n this.failed = false\n this.publish()\n }\n\n /**\n * Toggle the staged removal of one account's stored key: the next save\n * unsets the credential so the account reports unconfigured and falls back\n * to its other key sources. Only meaningful while a key is actually\n * stored. `target` is `'default'` (the implicit first account) or an extra\n * account's credential reference.\n */\n toggleKeyClear(target: string): void {\n const ref = target === 'default' ? this.credentialRef : target\n if (this.keyClears.has(ref)) {\n this.keyClears.delete(ref)\n } else {\n if (this.credentialStates.get(ref)?.configured !== true) return\n // A staged replacement and a staged removal are mutually exclusive.\n this.keyDrafts.delete(ref)\n if (ref === this.credentialRef) this.staged.delete('apiKey')\n this.keyClears.add(ref)\n }\n this.failed = false\n void this.describeAll()\n this.publish()\n }\n\n /** Stage a new model → account routing rule (saved on the next `save()`). */\n addRule(): void {\n this.addedRules.push({ models: [], account: 'default' })\n this.failed = false\n this.publish()\n }\n\n /** Stage one routing rule's removal (or drop an unsaved addition). */\n removeRule(id: string): void {\n const addedIndex = this.addedRules.findIndex((_, index) => `new-${index}` === id)\n if (addedIndex >= 0) this.addedRules.splice(addedIndex, 1)\n else this.removedRuleIds.add(id)\n this.ruleDrafts.delete(id)\n this.failed = false\n this.publish()\n }\n\n /** Stage one routing rule's selected model ids (multi-select). */\n editRuleModels(id: string, models: string[]): void {\n const addedIndex = this.addedRules.findIndex((_, index) => `new-${index}` === id)\n if (addedIndex >= 0) {\n this.addedRules[addedIndex] = { ...this.addedRules[addedIndex]!, models }\n } else {\n const current = this.ruleDrafts.get(id) ?? this.storedRules().find((rule) => rule.id === id) ?? { models: [], account: 'default' }\n this.ruleDrafts.set(id, { ...current, models })\n }\n this.failed = false\n this.publish()\n }\n\n /** Stage one routing rule's target account draft. */\n editRuleAccount(id: string, text: string): void {\n const addedIndex = this.addedRules.findIndex((_, index) => `new-${index}` === id)\n if (addedIndex >= 0) {\n this.addedRules[addedIndex] = { ...this.addedRules[addedIndex]!, account: text }\n } else {\n const current = this.ruleDrafts.get(id) ?? this.storedRules().find((rule) => rule.id === id) ?? { models: [], account: 'default' }\n this.ruleDrafts.set(id, { ...current, account: text })\n }\n this.failed = false\n this.publish()\n }\n\n /** Stage one field's draft text. */\n edit(field: string, text: string): void {\n this.staged.set(field, { text, clear: false })\n // Typing a replacement for the default key cancels a staged removal.\n if (field === 'apiKey') this.keyClears.delete(this.credentialRef)\n this.failed = false\n this.publish()\n }\n\n /** Reset one section field to its inherited (composition) value. */\n resetField(field: string): void {\n if (field === 'apiKey') {\n this.staged.delete('apiKey')\n this.failed = false\n this.publish()\n return\n }\n const spec = this.spec(field)\n this.staged.set(field, { text: spec.format(this.baseValue(field)), clear: true })\n this.failed = false\n this.publish()\n }\n\n /** Discard every staged edit. */\n discard(): void {\n if (this.staged.size === 0 && !this.accountsStaged() && !this.rulesStaged() && !this.failed) return\n this.staged.clear()\n this.clearAccountStaging()\n this.clearRuleStaging()\n this.failed = false\n this.publish()\n }\n\n /**\n * Re-read the Host's credential facts without any staged edit. The browser\n * login stores a key Host-side behind the page's back; the plugin entry\n * calls this when a login lands so the configured/writable badges follow.\n */\n refreshCredentials(): void {\n void this.describeAll()\n }\n\n /** Write every staged edit, then re-read the Host's accepted state. */\n async save(): Promise<void> {\n const plan = this.plan()\n const accountRuns = this.accountPlan()\n const ruleRuns = this.rulesPlan()\n if ((plan.length === 0 && accountRuns.length === 0 && ruleRuns.length === 0) || this.saving) return\n const runs: Array<() => Promise<boolean>> = []\n for (const item of plan) {\n if (item.run === undefined) return\n runs.push(item.run)\n }\n this.saving = true\n this.failed = false\n this.publish()\n let landed = true\n // Keys land first so a saved accounts list never names a ref whose key\n // write failed silently; the accounts list itself writes last. Stop at\n // the first failure: running later writes after a failed one would\n // persist a partial state the staged drafts no longer describe.\n for (const run of [...runs, ...accountRuns, ...ruleRuns]) {\n if (!(await run())) {\n landed = false\n break\n }\n }\n this.saving = false\n this.failed = !landed\n if (landed) {\n this.savedCount += 1\n this.staged.clear()\n this.clearAccountStaging()\n this.clearRuleStaging()\n } else {\n // A failed save may still have landed earlier writes (e.g. the accounts\n // list made it while a key write did not). Reconcile the staging with\n // the stored section so a landed account is not simultaneously stored\n // AND staged-for-addition (which a retry would persist twice).\n this.reconcileAccountStaging()\n this.reconcileRuleStaging()\n }\n this.publish()\n }\n\n /**\n * Drop account staging the stored section already reflects: additions whose\n * ref is now stored, removals whose ref is gone, and label drafts matching\n * the stored label. Key drafts are kept — a landed key write is idempotent\n * on retry, and the draft carries the user's intent when it was the\n * accounts write that failed.\n */\n private reconcileAccountStaging(): void {\n const stored = new Set(this.storedExtras().map((extra) => extra.ref))\n this.addedAccounts = this.addedAccounts.filter((extra) => !stored.has(extra.ref))\n for (const ref of [...this.removedRefs]) {\n if (!stored.has(ref)) this.removedRefs.delete(ref)\n }\n for (const [ref, text] of [...this.labelDrafts]) {\n const storedLabel = this.storedExtras().find((extra) => extra.ref === ref)?.label\n if (storedLabel === undefined || storedLabel === text.trim()) this.labelDrafts.delete(ref)\n }\n // A landed clear already did its job (the Host reports unconfigured);\n // keep only clears that failed so a retry re-attempts them.\n for (const ref of [...this.keyClears]) {\n if (this.credentialStates.get(ref)?.configured !== true) this.keyClears.delete(ref)\n }\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private spec(field: string): FieldSpec {\n const spec = this.specs.get(field)\n if (spec === undefined) throw new Error(`commandcode settings page has no field ${field}`)\n return spec\n }\n\n /** One field's rendered state: draft text, whether it is user-overridden, invalid. */\n private field(field: string): StagedField {\n const spec = this.spec(field)\n const staged = this.staged.get(field)\n if (staged === undefined) {\n return {\n text: spec.format(this.sectionValue(field)),\n clear: false,\n overridden: this.stored(field),\n invalid: false,\n invalidReason: undefined,\n }\n }\n const parsed = staged.clear ? { kind: 'clear' as const } : spec.parse(staged.text)\n return {\n text: staged.text,\n clear: staged.clear,\n overridden: parsed.kind === 'set',\n invalid: parsed.kind === 'invalid',\n invalidReason: parsed.kind === 'invalid' ? parsed.reason : undefined,\n }\n }\n\n private sectionValue(field: string): unknown {\n return this.scope.getSnapshot().value?.[field]\n }\n\n private baseValue(field: string): unknown {\n const base = this.scope.getSnapshot().base\n return typeof base === 'object' && base !== null && !Array.isArray(base)\n ? (base as Record<string, unknown>)[field]\n : undefined\n }\n\n private userLayer(): Record<string, unknown> | undefined {\n const user = this.scope.getSnapshot().user\n return typeof user === 'object' && user !== null && !Array.isArray(user)\n ? (user as Record<string, unknown>)\n : undefined\n }\n\n private stored(field: string): boolean {\n const user = this.userLayer()\n return user !== undefined && Object.prototype.hasOwnProperty.call(user, field)\n }\n\n /**\n * The writes a save would perform, in staged order. A field whose draft is\n * not a value its spec accepts carries no write (the save refuses).\n */\n private plan(): Array<{ field: string; run: (() => Promise<boolean>) | undefined }> {\n const plan: Array<{ field: string; run: (() => Promise<boolean>) | undefined }> = []\n for (const [field, staged] of this.staged) {\n if (field === 'apiKey') {\n const value = staged.text.trim()\n if (value !== '') {\n plan.push({ field, run: () => this.writeKey(value) })\n }\n continue\n }\n const spec = this.spec(field)\n if (staged.clear) {\n if (this.stored(field)) plan.push({ field, run: () => this.clear(field) })\n continue\n }\n if (staged.text === spec.format(this.sectionValue(field))) continue\n const parsed = spec.parse(staged.text)\n if (parsed.kind === 'invalid') plan.push({ field, run: undefined })\n else if (parsed.kind === 'clear') plan.push({ field, run: () => this.clear(field) })\n else plan.push({ field, run: () => this.store(field, parsed.value) })\n }\n return plan\n }\n\n private async clear(field: string): Promise<boolean> {\n await this.scope.unset(field)\n return !this.stored(field)\n }\n\n private async store(field: string, value: string | number | boolean): Promise<boolean> {\n await this.scope.set(field, value)\n return this.userLayer()?.[field] === value\n }\n\n /** Write the staged default key, then re-read whether the Host holds it. */\n private async writeKey(value: string): Promise<boolean> {\n return this.writeKeyTo(this.credentialRef, value)\n }\n\n /** Write one account's key, then re-read the Host's credential states. */\n private async writeKeyTo(ref: string, value: string): Promise<boolean> {\n try {\n const response = await this.api.credentials.set(ref, value)\n if (!response.ok) return false\n } catch {\n return false\n }\n await this.describeAll()\n return this.credentialStates.get(ref)?.configured ?? false\n }\n\n /** Ask the credentials domain about every reference this page writes. */\n private async describeAll(): Promise<void> {\n const refs = [\n this.credentialRef,\n ...this.storedExtras().map((extra) => extra.ref),\n ...this.addedAccounts.map((extra) => extra.ref),\n ]\n let response: Awaited<ReturnType<SettingsPageApi['credentials']['describe']>>\n try {\n response = await this.api.credentials.describe(refs)\n } catch {\n return\n }\n if (!response.ok) return\n let changed = false\n for (const ref of refs) {\n const view = response.value?.[ref]\n const next = {\n configured: view?.configured ?? false,\n writable: view?.writable ?? true,\n }\n const prev = this.credentialStates.get(ref)\n if (prev === undefined || prev.configured !== next.configured || prev.writable !== next.writable) {\n this.credentialStates.set(ref, next)\n changed = true\n }\n }\n if (changed) this.publish()\n }\n\n /**\n * Fetch the model catalog for the routing-rule editor through the Host\n * Remote. Runs once at construction; call again (e.g. from the client entry\n * once the Remote mount lands) to (re)try — a later success clears a prior\n * failure flag so the editor recovers without a page reload.\n */\n refreshCatalog(): void {\n const models = this.api.models\n if (models === undefined) {\n this.catalogFailed = true\n this.publish()\n return\n }\n void models().then((response) => {\n if (response.ok && Array.isArray(response.value?.models)) {\n this.catalogModels = response.value.models\n this.catalogFailed = false\n } else {\n this.catalogFailed = true\n }\n }, () => {\n this.catalogFailed = true\n }).then(() => this.publish())\n }\n\n // -----------------------------------------------------------------------\n // Multi-account staging\n // -----------------------------------------------------------------------\n\n /** The stored extra accounts from the settings section (`accounts`). */\n private storedExtras(): Array<{ label: string; ref: string }> {\n const raw = this.scope.getSnapshot().value?.accounts\n if (!Array.isArray(raw)) return []\n const out: Array<{ label: string; ref: string }> = []\n for (const entry of raw) {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) continue\n const record = entry as Record<string, unknown>\n const ref = record.apiKeyEnv\n if (typeof ref !== 'string' || ref === '') continue\n const label = record.label\n out.push({ label: typeof label === 'string' && label !== '' ? label : ref, ref })\n }\n return out\n }\n\n /** Every extra account row: stored (minus staged removals) + staged adds. */\n private effectiveAccounts(): AccountItemState[] {\n const stored = this.storedExtras()\n .filter((extra) => !this.removedRefs.has(extra.ref))\n .map((extra) => ({ ...extra, added: false }))\n const added = this.addedAccounts.map((extra) => ({ ...extra, added: true }))\n return [...stored, ...added].map((extra) => ({\n id: extra.ref,\n ref: extra.ref,\n label: this.labelDrafts.get(extra.ref) ?? extra.label,\n keyText: this.keyDrafts.get(extra.ref) ?? '',\n configured: this.credentialStates.get(extra.ref)?.configured ?? false,\n writable: this.credentialStates.get(extra.ref)?.writable ?? true,\n added: extra.added,\n clearStaged: this.keyClears.has(extra.ref),\n }))\n }\n\n /** Whether any account-level staging (add/remove/label/key/clear) exists. */\n private accountsStaged(): boolean {\n return this.addedAccounts.length > 0\n || this.removedRefs.size > 0\n || this.labelDrafts.size > 0\n || this.keyDrafts.size > 0\n || this.keyClears.size > 0\n }\n\n /** Whether the staged account edits differ from the stored section. */\n private accountsDirty(): boolean {\n if (this.addedAccounts.length > 0 || this.removedRefs.size > 0) return true\n for (const [ref, text] of this.labelDrafts) {\n const base = this.storedExtras().find((extra) => extra.ref === ref)?.label\n if (base !== undefined && text.trim() !== '' && text !== base) return true\n }\n for (const text of this.keyDrafts.values()) {\n if (text.trim() !== '') return true\n }\n // A staged clear is only meaningful while the key is actually stored —\n // staging one against an unconfigured ref is a no-op, not dirt.\n for (const ref of this.keyClears) {\n if (this.credentialStates.get(ref)?.configured === true) return true\n }\n return false\n }\n\n /** Reset every account-level staged edit. */\n private clearAccountStaging(): void {\n this.addedAccounts = []\n this.removedRefs.clear()\n this.labelDrafts.clear()\n this.keyDrafts.clear()\n this.keyClears.clear()\n }\n\n /** Unset one stored credential, then re-read the Host's credential states. */\n private async unsetKey(ref: string): Promise<boolean> {\n try {\n const response = await this.api.credentials.unset(ref)\n if (!response.ok) return false\n } catch {\n return false\n }\n await this.describeAll()\n return this.credentialStates.get(ref)?.configured !== true\n }\n\n /** The account-level writes a save performs (empty when nothing staged). */\n private accountPlan(): Array<() => Promise<boolean>> {\n if (!this.accountsDirty()) return []\n const runs: Array<() => Promise<boolean>> = []\n // Staged removals land first: a cleared credential must be gone before\n // the accounts list write, or a removed row would leave an orphaned\n // secret behind. Removed rows keep their clear (clean removal).\n for (const ref of this.keyClears) {\n if (this.credentialStates.get(ref)?.configured === true) {\n runs.push(() => this.unsetKey(ref))\n }\n }\n for (const [ref, text] of this.keyDrafts) {\n const value = text.trim()\n if (value !== '' && !this.removedRefs.has(ref) && !this.keyClears.has(ref)) {\n runs.push(() => this.writeKeyTo(ref, value))\n }\n }\n runs.push(() => this.writeAccounts())\n return runs\n }\n\n /** Persist the staged accounts list into the settings section. */\n private async writeAccounts(): Promise<boolean> {\n const base = [\n ...this.storedExtras().filter((extra) => !this.removedRefs.has(extra.ref)),\n ...this.addedAccounts,\n ]\n // Defensive dedupe by ref: a partially landed earlier save can leave an\n // account both stored and staged-for-addition; never persist duplicates.\n const seen = new Set<string>()\n const list = base.filter((extra) => !seen.has(extra.ref) && (seen.add(extra.ref), true)).map((extra) => {\n const draft = this.labelDrafts.get(extra.ref)?.trim()\n return { label: draft !== undefined && draft !== '' ? draft : extra.label, apiKeyEnv: extra.ref }\n })\n await this.scope.set('accounts', list)\n const after = this.storedExtras()\n return after.length === list.length\n && list.every((item, index) => after[index]?.ref === item.apiKeyEnv)\n }\n\n // -----------------------------------------------------------------------\n // Model → account routing-rule staging\n // -----------------------------------------------------------------------\n\n /** The stored routing rules from the settings section (`modelAccountRules`). */\n private storedRules(): Array<{ id: string; models: string[]; account: string }> {\n const raw = this.scope.getSnapshot().value?.modelAccountRules\n if (!Array.isArray(raw)) return []\n const out: Array<{ id: string; models: string[]; account: string }> = []\n for (const [index, entry] of raw.entries()) {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) continue\n const record = entry as Record<string, unknown>\n const models = record.models\n const account = record.account\n const modelsList = Array.isArray(models) && models.every((m) => typeof m === 'string')\n ? (models as string[]).filter((m) => m !== '')\n : []\n if (modelsList.length === 0) continue\n out.push({\n id: `rule-${index}`,\n models: modelsList,\n account: typeof account === 'string' && account !== '' ? account : 'default',\n })\n }\n return out\n }\n\n /** Every routing rule row: stored (minus staged removals, with drafts) + staged adds. */\n private effectiveRules(): RuleItemState[] {\n const stored = this.storedRules()\n .filter((rule) => !this.removedRuleIds.has(rule.id))\n .map((rule) => {\n const draft = this.ruleDrafts.get(rule.id)\n return {\n id: rule.id,\n models: draft?.models ?? rule.models,\n account: draft?.account ?? rule.account,\n added: false,\n }\n })\n const added = this.addedRules.map((rule, index) => ({\n id: `new-${index}`,\n models: rule.models,\n account: rule.account,\n added: true,\n }))\n return [...stored, ...added]\n }\n\n /** Whether any routing-rule staging (add/remove/edit) exists. */\n private rulesStaged(): boolean {\n return this.addedRules.length > 0 || this.removedRuleIds.size > 0 || this.ruleDrafts.size > 0\n }\n\n /** Whether the staged routing rules differ from the stored section. */\n private rulesDirty(): boolean {\n if (this.addedRules.length > 0 || this.removedRuleIds.size > 0) return true\n for (const [id, draft] of this.ruleDrafts) {\n const base = this.storedRules().find((rule) => rule.id === id)\n if (base === undefined) continue\n if (draft.models.length > 0 && !sameModels(draft.models, base.models)) return true\n if (draft.account !== base.account) return true\n }\n return false\n }\n\n /** Reset every routing-rule staged edit. */\n private clearRuleStaging(): void {\n this.addedRules = []\n this.ruleDrafts.clear()\n this.removedRuleIds.clear()\n }\n\n /** Drop rule staging the stored section already reflects (partial-save retry). */\n private reconcileRuleStaging(): void {\n const storedIds = new Set(this.storedRules().map((rule) => rule.id))\n for (const id of [...this.removedRuleIds]) {\n if (!storedIds.has(id)) this.removedRuleIds.delete(id)\n }\n // Drafts on rows that no longer exist (a failed save that landed the\n // removal) are stale; drop them so a retry does not resurrect the row.\n for (const id of [...this.ruleDrafts.keys()]) {\n if (!storedIds.has(id)) this.ruleDrafts.delete(id)\n }\n }\n\n /** The routing-rule writes a save performs (empty when nothing staged). */\n private rulesPlan(): Array<() => Promise<boolean>> {\n if (!this.rulesDirty()) return []\n return [() => this.writeRules()]\n }\n\n /** Persist the staged routing rules into the settings section. */\n private async writeRules(): Promise<boolean> {\n const base = this.storedRules().filter((rule) => !this.removedRuleIds.has(rule.id))\n const list = [\n ...base.map((rule) => {\n const draft = this.ruleDrafts.get(rule.id)\n return {\n models: draft !== undefined && draft.models.length > 0 ? draft.models : rule.models,\n account: draft?.account !== undefined && draft.account !== '' ? draft.account : rule.account,\n }\n }),\n ...this.addedRules.map((rule) => ({\n models: rule.models,\n account: rule.account,\n })),\n ].filter((rule) => rule.models.length > 0)\n await this.scope.set('modelAccountRules', list)\n const after = this.storedRules()\n return after.length === list.length\n && list.every((item, index) =>\n after[index] !== undefined\n && sameModels(after[index].models, item.models)\n && after[index].account === item.account)\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of this.listeners) listener()\n }\n}\n","/** Legacy ApiProxy credentials adapter for pre-0.1.2 DSH clients. */\n\nimport type { SettingsPageApi } from './settings.ts'\n\ninterface LegacyFailure {\n message: string\n}\n\ninterface LegacyResponse<T> {\n result:\n | { ok: true; value: T }\n | { ok: false; error: LegacyFailure }\n}\n\n/** The pre-0.1.2 `connection.api.credentials` face. */\nexport interface LegacyCredentialsApi {\n describe(request: { refs: string[] }): Promise<LegacyResponse<{\n credentials: Record<string, { configured: boolean; writable: boolean }>\n }>>\n set(request: { ref: string; value: string }): Promise<LegacyResponse<unknown>>\n unset(request: { ref: string }): Promise<LegacyResponse<unknown>>\n}\n\n/** Convert a legacy credentials ApiProxy into the current settings-page face. */\nexport function adaptLegacyCredentials(\n legacy: LegacyCredentialsApi | undefined,\n): SettingsPageApi | undefined {\n if (legacy === undefined) return undefined\n return {\n credentials: {\n describe: async (refs) => {\n const response = await legacy.describe({ refs })\n return response.result.ok\n ? { ok: true, value: response.result.value.credentials }\n : { ok: false, error: response.result.error }\n },\n set: async (ref, value) => {\n const response = await legacy.set({ ref, value })\n return response.result.ok\n ? { ok: true, value: undefined }\n : { ok: false, error: response.result.error }\n },\n unset: async (ref) => {\n const response = await legacy.unset({ ref })\n return response.result.ok\n ? { ok: true, value: undefined }\n : { ok: false, error: response.result.error }\n },\n },\n }\n}\n","/**\n * Browser controller for the settings page's account-usage card.\n *\n * The card renders the same account/usage/credit facts the `/commandcode`\n * command prints, fetched Host-side through the `commandcode/report` Remote\n * (the browser never holds the API key). This controller owns the fetch\n * lifecycle — idle/loading/ready/error, one in-flight request at a time,\n * stale-response dropping — and the display formatting, so the React\n * component stays a thin renderer and node tests can drive everything.\n *\n * Deliberately JSX-free, mirroring `./settings.ts`.\n *\n * @module dsh-commandcode-provider/client/usage\n */\n\nimport type { CommandCodeAccountsReport, CommandCodeCatalog } from '../usage-wire.ts'\nimport type { CommandCodeLoginStatus } from '../login-wire.ts'\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\n\n/**\n * Merge the plugin's Remote endpoints into the harness's typed client Remote\n * surface (the same declaration pattern the harness's generated\n * typert.remote-client files use), so `ctx.remote.commandcode.*()` is typed\n * once each contribution is mounted. The `commandcode` namespace member is\n * declared exactly once (interface merging forbids duplicate members), so\n * this one declaration carries the usage report, the model catalog, AND the\n * login endpoints — the endpoint-level declarations live beside their\n * controllers.\n */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/report': () => Promise<RemoteResult<CommandCodeAccountsReport>>\n 'commandcode/models': () => Promise<RemoteResult<CommandCodeCatalog>>\n }\n interface TypertRemoteNamespaceMap {\n commandcode: {\n report: () => Promise<RemoteResult<CommandCodeAccountsReport>>\n models: () => Promise<RemoteResult<CommandCodeCatalog>>\n loginBegin: () => Promise<RemoteResult<CommandCodeLoginStatus>>\n loginStatus: () => Promise<RemoteResult<CommandCodeLoginStatus>>\n loginCancel: () => Promise<RemoteResult<CommandCodeLoginStatus>>\n }\n }\n}\n\n/** The narrow slice of the mounted Remote this controller calls. */\nexport interface UsageRemote {\n report(): Promise<\n | { ok: true; value: CommandCodeAccountsReport }\n | { ok: false; error: { message: string } }\n >\n models(): Promise<\n | { ok: true; value: CommandCodeCatalog }\n | { ok: false; error: { message: string } }\n >\n}\n\n/** The card's fetch lifecycle. */\nexport type UsageStatus =\n /** Never fetched (no API key configured yet, or not requested). */\n | 'idle'\n /** A fetch is in flight; `report` retains the last good data if any. */\n | 'loading'\n /** The last fetch succeeded. */\n | 'ready'\n /** The last fetch failed (no key, unreachable host, old plugin). */\n | 'error'\n\n/** The card's full state face. */\nexport interface UsagePageState {\n status: UsageStatus\n /** The last successfully fetched report (retained across refetches). */\n report: CommandCodeAccountsReport | undefined\n /** The last failure's message (error status). */\n error: string | undefined\n /** Millis timestamp of the last successful fetch. */\n fetchedAt: number | undefined\n}\n\nconst IDLE: UsagePageState = { status: 'idle', report: undefined, error: undefined, fetchedAt: undefined }\n\n/**\n * Controller bridging the `commandcode/report` Remote onto the card. Public\n * API mirrors {@link CommandCodeSettingsController}: `state()` projections,\n * `subscribe`, and one `refresh()` action.\n */\nexport class CommandCodeUsageController {\n private readonly remote: UsageRemote\n private readonly listeners = new Set<() => void>()\n private current: UsagePageState = IDLE\n private generation = 0\n private inFlight = false\n private disposed = false\n\n constructor(remote: UsageRemote) {\n this.remote = remote\n }\n\n /** Release every subscription. Idempotent; in-flight results are dropped. */\n dispose(): void {\n this.disposed = true\n this.generation += 1\n this.listeners.clear()\n }\n\n /** Subscribe to state projections. @returns the disposer. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** The current card state face. */\n state(): UsagePageState {\n return this.current\n }\n\n /**\n * Fetch (or refetch) the report. Concurrent refreshes collapse onto one\n * request; a superseded fetch's late result is dropped, never published.\n */\n async refresh(): Promise<void> {\n if (this.disposed || this.inFlight) return\n const generation = ++this.generation\n this.inFlight = true\n this.current = { ...this.current, status: 'loading', error: undefined }\n this.publish()\n try {\n const response = await this.remote.report()\n if (this.disposed || generation !== this.generation) return\n if (response.ok) {\n this.current = { status: 'ready', report: response.value, error: undefined, fetchedAt: Date.now() }\n } else {\n this.current = { ...this.current, status: 'error', error: response.error.message }\n }\n } catch (error: unknown) {\n if (this.disposed || generation !== this.generation) return\n this.current = {\n ...this.current,\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n }\n } finally {\n if (generation === this.generation) this.inFlight = false\n }\n this.publish()\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of this.listeners) listener()\n }\n}\n\n// ---------------------------------------------------------------------------\n// Display formatting (shared by the component, covered by node tests)\n// ---------------------------------------------------------------------------\n\n/** Format a dollar amount compactly (2 decimals). */\nexport function formatMoney(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\n/** Format a dollar amount precisely (4 decimals) for small totals. */\nexport function formatMoneyExact(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\n/** Format a large token count compactly (1.9M style). */\nexport function formatTokensCompact(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/** One window's fill ratio in [0, 1]; 0 when uncapped. */\nexport function windowRatio(used: number, cap: number): number {\n if (cap <= 0) return 0\n return Math.max(0, Math.min(1, used / cap))\n}\n\n/** Format a millis timestamp as a local short date-time; empty when unset. */\nexport function formatResetAt(ms: number): string {\n if (ms <= 0) return ''\n return new Date(ms).toLocaleString()\n}\n","/**\n * Browser controller for the settings page's login panel.\n *\n * The panel drives the Host-half browser login (the official\n * `command-code login` loopback dance) through the Typert Gateway: `begin`\n * asks the Host to bind the callback server and returns the Studio URL, the\n * controller polls `loginStatus` once a second while the attempt is live, and\n * `cancel` tears it down. The key itself never crosses to the browser — the\n * Host validates and stores it through the credentials seam.\n *\n * Transport-level failures (no mounted Remote, an older Host without the\n * login endpoints) land in the dedicated `unavailable` phase so the page can\n * point back at manual paste. Deliberately JSX-free, mirroring\n * `./settings.ts` and `./usage.ts`.\n *\n * @module dsh-commandcode-provider/client/login\n */\n\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nimport type { CommandCodeLoginFailureReason, CommandCodeLoginStatus } from '../login-wire.ts'\n\n/** The endpoint-level Remote surface this controller calls. */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/loginBegin': () => Promise<RemoteResult<CommandCodeLoginStatus>>\n 'commandcode/loginStatus': () => Promise<RemoteResult<CommandCodeLoginStatus>>\n 'commandcode/loginCancel': () => Promise<RemoteResult<CommandCodeLoginStatus>>\n }\n}\n\n/** The narrow slice of the mounted Remote this controller calls. */\nexport interface LoginRemote {\n loginBegin(): Promise<LoginCallResult>\n loginStatus(): Promise<LoginCallResult>\n loginCancel(): Promise<LoginCallResult>\n}\n\n/** One Remote call's outcome as the controller sees it. */\nexport type LoginCallResult =\n | { ok: true; value: CommandCodeLoginStatus }\n | { ok: false; error: { message: string } }\n\n/** The panel's full state face. */\nexport interface LoginPageState {\n /**\n * `idle` — nothing started; `starting` — begin() in flight; `waiting` —\n * the Studio URL is live and polling; `success`/`failed` — terminal;\n * `unavailable` — the Remote itself could not be reached (old Host, mount\n * failure), manual paste is the way.\n */\n phase: 'idle' | 'starting' | 'waiting' | 'success' | 'failed' | 'unavailable'\n /** The Studio authorization URL while `waiting`. */\n authUrl: string | undefined\n /** The account display name on `success`. */\n userName: string | undefined\n /** The key's Studio label on `success`. */\n keyName: string | undefined\n /** The stable failure reason when `failed`. */\n reason: CommandCodeLoginFailureReason | undefined\n /** Secondary failure detail when `failed`/`unavailable`. */\n message: string | undefined\n}\n\n/** How often a live attempt is polled. */\nconst POLL_INTERVAL_MS = 1_000\n\n/**\n * The login panel's fetch/poll lifecycle. One poll loop at a time; a fresh\n * `begin()` supersedes any previous loop via a generation token.\n */\nexport class CommandCodeLoginController {\n private readonly remote: () => LoginRemote | undefined\n private readonly listeners = new Set<() => void>()\n private readonly pollMs: number\n /** Monotonic token; only the latest loop may publish polling results. */\n private generation = 0\n private disposed = false\n\n private phase: LoginPageState['phase'] = 'idle'\n private authUrl: string | undefined\n private userName: string | undefined\n private keyName: string | undefined\n private reason: CommandCodeLoginFailureReason | undefined\n private message: string | undefined\n\n constructor(remote: () => LoginRemote | undefined, pollMs = POLL_INTERVAL_MS) {\n this.remote = remote\n this.pollMs = pollMs\n }\n\n /** Subscribe to state projections. @returns the disposer. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n /** Build the current panel state face. */\n state(): LoginPageState {\n return {\n phase: this.phase,\n authUrl: this.authUrl,\n userName: this.userName,\n keyName: this.keyName,\n reason: this.reason,\n message: this.message,\n }\n }\n\n /** Start (or rejoin) a login attempt and begin polling its status. */\n async begin(): Promise<void> {\n if (this.disposed || this.phase === 'starting' || this.phase === 'waiting') return\n const generation = ++this.generation\n this.set({ phase: 'starting', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: undefined })\n const remote = this.remote()\n if (remote === undefined) {\n this.set({ phase: 'unavailable', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: 'login remote is not mounted' })\n return\n }\n let result: LoginCallResult\n try {\n result = await remote.loginBegin()\n } catch (error: unknown) {\n // A transport throw (gateway hiccup) reads the same as a rejected call.\n result = { ok: false, error: { message: error instanceof Error ? error.message : String(error) } }\n }\n if (this.superseded(generation)) return\n if (!result.ok) {\n this.set({ phase: 'unavailable', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: result.error.message })\n return\n }\n this.apply(result.value)\n if (this.currentPhase === 'waiting') void this.poll(generation)\n }\n\n /** Cancel a waiting attempt. */\n async cancel(): Promise<void> {\n if (this.disposed || (this.phase !== 'starting' && this.phase !== 'waiting')) return\n const generation = ++this.generation\n const remote = this.remote()\n if (remote === undefined) return\n let result: LoginCallResult\n try {\n result = await remote.loginCancel()\n } catch {\n // The Host may be gone; reflect the local cancel regardless.\n this.set({ phase: 'failed', authUrl: undefined, userName: undefined, keyName: undefined, reason: 'cancelled', message: undefined })\n return\n }\n if (this.superseded(generation)) return\n if (result.ok) this.apply(result.value)\n else this.set({ phase: 'failed', authUrl: undefined, userName: undefined, keyName: undefined, reason: 'cancelled', message: undefined })\n }\n\n /** Stop polling and release listeners. Idempotent. */\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n this.generation += 1\n this.listeners.clear()\n }\n\n // -----------------------------------------------------------------------\n // Internals\n // -----------------------------------------------------------------------\n\n /** Poll until the attempt leaves `waiting` or a newer loop supersedes us. */\n private async poll(generation: number): Promise<void> {\n // A getter read (not the field) so control-flow narrowing across `await`\n // cannot claim the phase is frozen.\n while (!this.disposed && !this.superseded(generation) && this.currentPhase === 'waiting') {\n await sleep(this.pollMs)\n if (this.disposed || this.superseded(generation) || this.currentPhase !== 'waiting') return\n const remote = this.remote()\n if (remote === undefined) {\n this.set({ phase: 'unavailable', authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: 'login remote is not mounted' })\n return\n }\n let result: LoginCallResult\n try {\n result = await remote.loginStatus()\n } catch {\n continue // one missed poll is not an outage; the next tick retries\n }\n if (this.superseded(generation) || this.currentPhase !== 'waiting') return\n if (result.ok) this.apply(result.value)\n }\n }\n\n private get currentPhase(): LoginPageState['phase'] {\n return this.phase\n }\n\n /** Project one Host status onto the panel face. */\n private apply(status: CommandCodeLoginStatus): void {\n const base = { authUrl: undefined, userName: undefined, keyName: undefined, reason: undefined, message: undefined }\n if (status.state === 'waiting') {\n this.set({ ...base, phase: 'waiting', authUrl: status.authUrl })\n return\n }\n if (status.state === 'success') {\n this.set({ ...base, phase: 'success', userName: status.userName, keyName: status.keyName })\n return\n }\n if (status.state === 'failed') {\n this.set({ ...base, phase: 'failed', reason: status.reason, message: status.message })\n return\n }\n // `idle` mid-poll means the Host restarted; the attempt is gone.\n this.set({ ...base, phase: 'failed', reason: 'cancelled', message: 'the login attempt is no longer active' })\n }\n\n /** Replace the whole state face and notify. Explicit over partial patches. */\n private set(state: LoginPageState): void {\n this.phase = state.phase\n this.authUrl = state.authUrl\n this.userName = state.userName\n this.keyName = state.keyName\n this.reason = state.reason\n this.message = state.message\n this.publish()\n }\n\n private superseded(generation: number): boolean {\n return this.disposed || generation !== this.generation\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of [...this.listeners]) listener()\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\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 * The plugin's own version, read from package.json at build time.\n *\n * The client bundle inlines the JSON import (rolldown resolves it during the\n * tsdown build; node tests read it through tsx), so the rendered value always\n * matches the published package version with no second constant to keep in\n * sync. Rendered as a muted footer line on the settings page so a user can\n * report the exact build they run.\n *\n * @module dsh-commandcode-provider/client/version\n */\n\nimport pkg from '../../package.json'\n\n/** The published package version (e.g. `'0.6.0'`). */\nexport const PLUGIN_VERSION: string = pkg.version\n\n/**\n * This package's GitHub releases page, derived from the repository field so\n * the update hint's link target can never drift from the published home.\n */\nexport const PLUGIN_RELEASES_URL: string =\n `${pkg.repository.url.replace(/^git\\+/, '').replace(/\\.git$/, '')}/releases`\n","/**\n * Plugin update hint (browser half).\n *\n * A deliberately small feature: when the \"Command Code\" settings page opens,\n * ask the npm registry for the package's published `latest` version and —\n * only when it is newer than the running build — let the page's footer show a\n * muted \"newer version available\" link to the GitHub releases. Everything\n * here is React-free and side-effect-seamed so node tests can drive it.\n *\n * Behaviour contract:\n *\n * - The registry is queried at most once per {@link UPDATE_CHECK_INTERVAL_MS}\n * per browser profile; the learned version is cached in `localStorage`\n * alongside the attempt time, so re-opening the settings page is free.\n * - A failed check records the attempt time too (an offline browser must not\n * hammer the registry on every page open) but keeps any previously learned\n * version, so the hint survives transient outages until it expires.\n * - Every failure mode (blocked network, non-OK status, malformed payload,\n * unavailable storage) degrades to \"no hint\"; nothing ever throws out of\n * {@link checkForUpdate}.\n *\n * The registry serves `access-control-allow-origin: *`, so the plain browser\n * fetch works from the GUI origin without any Host-side proxying.\n *\n * @module dsh-commandcode-provider/client/update\n */\n\n/** How often the page may hit the registry: once a day. */\nexport const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000\n\n/** Abort a hung registry request rather than keep the footer waiting. */\nexport const FETCH_TIMEOUT_MS = 5000\n\n/**\n * The npm registry document for this package's `latest` dist-tag. The scoped\n * name is path-escaped (`%2F`) so no client normalizes the slash away.\n */\nexport const NPM_LATEST_URL =\n 'https://registry.npmjs.org/@mars-sea%2Fdsh-commandcode-provider/latest'\n\n/**\n * Compare two version strings (`major.minor.patch[-pre]`). Returns a negative\n * number when `a` sorts before `b`, positive when after, zero when equal.\n *\n * Tolerant by design: a leading `v` is stripped, unparsable numeric parts\n * count as `0`, and semver prerelease rules apply (release > prerelease;\n * numeric identifiers compare numerically, everything else lexically, a\n * shorter identifier list sorts first). Enough for release tags; not a full\n * semver validator.\n */\nexport function compareVersions(a: string, b: string): number {\n const left = splitVersion(a)\n const right = splitVersion(b)\n const depth = Math.max(left.core.length, right.core.length)\n for (let index = 0; index < depth; index += 1) {\n const delta = (left.core[index] ?? 0) - (right.core[index] ?? 0)\n if (delta !== 0) return Math.sign(delta)\n }\n // A release outranks any prerelease of the same core version.\n if (left.pre.length === 0 && right.pre.length === 0) return 0\n if (left.pre.length === 0) return 1\n if (right.pre.length === 0) return -1\n const width = Math.max(left.pre.length, right.pre.length)\n for (let index = 0; index < width; index += 1) {\n const l = left.pre[index]\n const r = right.pre[index]\n if (l === undefined) return -1\n if (r === undefined) return 1\n const lNumeric = /^\\d+$/.test(l)\n const rNumeric = /^\\d+$/.test(r)\n let delta: number\n if (lNumeric && rNumeric) delta = Number(l) - Number(r)\n else if (lNumeric) delta = -1 // numeric identifiers sort below alphanumeric\n else if (rNumeric) delta = 1\n else delta = l < r ? -1 : l > r ? 1 : 0\n if (delta !== 0) return Math.sign(delta)\n }\n return 0\n}\n\n/** True when `candidate` is strictly newer than `current`. */\nexport function isNewerVersion(candidate: string, current: string): boolean {\n return compareVersions(candidate, current) > 0\n}\n\n/** Split a tolerant version string into numeric core + prerelease ids. */\nfunction splitVersion(value: string): { core: number[]; pre: string[] } {\n const [coreText = '', preText] = value.trim().replace(/^v/i, '').split('-')\n const core = coreText === ''\n ? [0]\n : coreText.split('.').map((part) => {\n const parsed = Number.parseInt(part, 10)\n return Number.isFinite(parsed) ? parsed : 0\n })\n const pre = preText === undefined ? [] : preText.split('.')\n return { core, pre }\n}\n\n/**\n * Extract the published version from the registry's `/latest` manifest\n * (`{ name, version, … }`). Throws on anything unexpected so callers treat a\n * shape change as a failed attempt, never as bogus data.\n */\nexport function parseLatestVersion(payload: unknown): string {\n if (typeof payload !== 'object' || payload === null) {\n throw new Error('npm latest payload is not an object')\n }\n const version = (payload as { version?: unknown }).version\n if (typeof version !== 'string' || !/^\\d+\\.\\d+\\./.test(version)) {\n throw new Error('npm latest payload has no usable version')\n }\n return version\n}\n\n/** Fetch and parse the published `latest` version. Rejects on any failure. */\nexport async function fetchLatestVersion(\n fetchImpl: typeof fetch = fetch,\n): Promise<string> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n try {\n const response = await fetchImpl(NPM_LATEST_URL, { signal: controller.signal })\n if (!response.ok) {\n throw new Error(`registry responded ${response.status}`)\n }\n return parseLatestVersion(await response.json())\n } finally {\n clearTimeout(timer)\n }\n}\n\n/** What the cache remembers about the last check. */\nexport interface UpdateCheckRecord {\n /** When the last attempt completed (success or failure), epoch ms. */\n at: number\n /** The last successfully learned upstream version, if any. */\n version?: string | undefined\n}\n\n/** Storage seam so tests can stand in for `localStorage`. */\nexport interface UpdateCheckStore {\n read(): UpdateCheckRecord | undefined\n write(record: UpdateCheckRecord): void\n}\n\n/** The `localStorage` key holding {@link UpdateCheckRecord}. */\nexport const UPDATE_CHECK_CACHE_KEY = '@mars-sea/dsh-commandcode-provider/update-check'\n\n/**\n * A {@link UpdateCheckStore} backed by `localStorage`. Tolerates a missing or\n * throwing storage (SSR-ish contexts, private modes): reads yield `undefined`,\n * writes are dropped.\n */\nexport function localStorageUpdateStore(\n storage: Storage | undefined = typeof localStorage === 'undefined' ? undefined : localStorage,\n): UpdateCheckStore {\n return {\n read(): UpdateCheckRecord | undefined {\n if (storage === undefined) return undefined\n try {\n const raw = storage.getItem(UPDATE_CHECK_CACHE_KEY)\n if (raw === null) return undefined\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== 'object' || parsed === null) return undefined\n const at = (parsed as { at?: unknown }).at\n if (typeof at !== 'number' || !Number.isFinite(at)) return undefined\n const version = (parsed as { version?: unknown }).version\n return {\n at,\n version: typeof version === 'string' && version !== '' ? version : undefined,\n }\n } catch {\n return undefined\n }\n },\n write(record: UpdateCheckRecord): void {\n if (storage === undefined) return\n try {\n storage.setItem(UPDATE_CHECK_CACHE_KEY, JSON.stringify(record))\n } catch {\n // Quota/private-mode failures must never break the page.\n }\n },\n }\n}\n\n/**\n * Run one throttled update check. Resolves with the newest published version\n * when it is newer than `currentVersion`, otherwise `undefined`.\n *\n * Within the throttle window (or on failure) the cached version answers, so\n * the hint keeps working offline; past the window the registry is consulted\n * again and the attempt time is refreshed either way.\n */\nexport async function checkForUpdate(options: {\n currentVersion: string\n now: number\n store: UpdateCheckStore\n fetchImpl?: typeof fetch\n}): Promise<string | undefined> {\n const { currentVersion, now, store } = options\n const hintOf = (version: string | undefined): string | undefined =>\n version !== undefined && isNewerVersion(version, currentVersion) ? version : undefined\n\n const cache = store.read()\n if (cache !== undefined && now - cache.at < UPDATE_CHECK_INTERVAL_MS) {\n return hintOf(cache.version)\n }\n\n let learned: string | undefined\n try {\n learned = await fetchLatestVersion(options.fetchImpl)\n } catch {\n // Degrade silently: record the attempt below and fall back to the cache.\n }\n const version = learned ?? cache?.version\n store.write({ at: now, version })\n return hintOf(version)\n}\n","/**\n * React component for the \"Command Code\" settings page (browser half).\n *\n * Renders as a `settings.section` entry — a page at the same settings-nav\n * level as General / Models / Plugins. The shell supplies the nav row and\n * renders this body inside the content column. All copy comes from the\n * `settings.commandcode` locale namespace; all state comes from the\n * `CommandCodeSettingsController` injected by the slot registration.\n *\n * The layout mirrors the harness's settings pages: a max-width content\n * column, labelled fields with hints, a reset affordance, and a\n * save/discard footer. Rarely touched connection facts (API base, working\n * directory, timeouts, plan filter) fold into a collapsed Advanced card\n * (`AdvancedSection`) so the page leads with the key and the usage facts.\n * Styles are injected once by the client entry\n * (see src/client/index.ts) and class-prefixed `cc-` to stay local.\n */\n\nimport { useEffect, useState } from 'react'\nimport { Button, Menu } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { MenuEntry } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { CommandCodeCredits } from '../adapter.ts'\nimport type { CommandCodeAccountUsage, CommandCodeUsageReport } from '../usage-wire.ts'\nimport type { SettingsCommandCodeKey } from './locales.ts'\nimport type { AccountItemState, CatalogModelOption, RuleItemState, SettingsPageState, StagedField } from './settings.ts'\nimport type { CommandCodeLoginFailureReason } from '../login-wire.ts'\nimport type { LoginPageState } from './login.ts'\nimport type { UsagePageState } from './usage.ts'\nimport { formatMoney, formatMoneyExact, formatResetAt, formatTokensCompact, windowRatio } from './usage.ts'\nimport { PLUGIN_RELEASES_URL, PLUGIN_VERSION } from './version.ts'\nimport { checkForUpdate, localStorageUpdateStore } from './update.ts'\n\n/** Props composed by the slot registration: locale seat + injected face. */\nexport interface CommandCodeSettingsProps {\n t: Translate<SettingsCommandCodeKey>\n useCommandCodeSettings<T>(selector: (state: SettingsPageState) => T): T\n useCommandCodeUsage<T>(selector: (state: UsagePageState) => T): T\n useCommandCodeLogin<T>(selector: (state: LoginPageState) => T): T\n edit(field: string, text: string): void\n resetField(field: string): void\n save(): void\n discard(): void\n refreshUsage(): void\n beginLogin(): void\n cancelLogin(): void\n addAccount(): void\n removeAccount(id: string): void\n editAccountLabel(id: string, text: string): void\n editAccountKey(id: string, text: string): void\n toggleKeyClear(id: string): void\n addRule(): void\n removeRule(id: string): void\n editRuleModels(id: string, ids: string[]): void\n editRuleAccount(id: string, text: string): void\n}\n\n/** The section fields folded into the collapsible Advanced card. */\ntype AdvancedField = 'apiBase' | 'workingDir' | 'requestTimeoutMs' | 'streamIdleTimeoutMs' | 'filterModelsByPlan'\nconst ADVANCED_FIELDS: readonly AdvancedField[] = [\n 'apiBase',\n 'workingDir',\n 'requestTimeoutMs',\n 'streamIdleTimeoutMs',\n 'filterModelsByPlan',\n]\n\n/** One labelled field row in the page body. */\nfunction Field({\n id,\n label,\n hint,\n state,\n disabled,\n numeric,\n placeholder,\n onEdit,\n onReset,\n t,\n}: {\n id: string\n label: string\n hint: string\n state: StagedField\n disabled: boolean\n numeric?: boolean\n placeholder?: string | undefined\n onEdit(text: string): void\n onReset(): void\n t: Translate<SettingsCommandCodeKey>\n}) {\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor={id}>{label}</label>\n <span className=\"cc-badges\">\n {state.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null}\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onReset}>{t('reset')}</button>\n </span>\n </div>\n <input\n id={id}\n className={state.invalid ? 'cc-input cc-inputInvalid' : 'cc-input'}\n type=\"text\"\n inputMode={numeric ? 'numeric' : undefined}\n value={state.text}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n <p className={state.invalid ? 'cc-invalid' : 'cc-hint'}>\n {state.invalid ? invalidCopy(state.invalidReason, t) : hint}\n </p>\n </div>\n )\n}\n\n/** The per-field error copy for a staged draft's failure reason. */\nfunction invalidCopy(reason: StagedField['invalidReason'], t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'tooSmall') return t('numberTooSmall')\n if (reason === 'tooLarge') return t('numberTooLarge')\n return t('invalidNumber')\n}\n\n/**\n * The collapsed \"Advanced\" card: API base, working dir, both timeouts, and\n * the plan filter live here so the page leads with the facts a user actually\n * touches. Starts collapsed on every visit; expands on demand. While\n * collapsed, a badge names the customized count so a nonzero override stays\n * visible (a number field's error blocks save and must be reachable).\n */\nfunction AdvancedSection({\n state,\n disabled,\n t,\n onEdit,\n onReset,\n}: {\n state: SettingsPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onEdit(field: string, text: string): void\n onReset(field: string): void\n}) {\n const [expanded, setExpanded] = useState(false)\n const overridden = ADVANCED_FIELDS.filter((field) => state[field].overridden).length\n const invalid = ADVANCED_FIELDS.some((field) => state[field].invalid)\n return (\n <div className=\"cc-card\">\n <button\n type=\"button\"\n className=\"cc-advancedHead\"\n aria-expanded={expanded}\n aria-controls=\"cc-advanced-body\"\n onClick={() => setExpanded((value) => !value)}\n >\n <span className=\"cc-advancedTitle\">{t('advancedSettings')}</span>\n {overridden > 0 ? (\n <span className=\"cc-badge\">\n {overridden === 1 ? t('advancedOverriddenOne') : t('advancedOverriddenMany').replace('{count}', String(overridden))}\n </span>\n ) : null}\n <span className=\"cc-advancedSpacer\" />\n <span className={expanded ? 'cc-chevron cc-chevronUp' : 'cc-chevron'} aria-hidden=\"true\" />\n </button>\n {expanded ? (\n <div id=\"cc-advanced-body\" className=\"cc-advancedBody\">\n <p className=\"cc-hint\">{t('advancedSettingsHint')}</p>\n <Field\n id=\"cc-api-base\"\n label={t('apiBase')}\n hint={t('apiBaseHint')}\n state={state.apiBase}\n disabled={disabled}\n onEdit={(text) => onEdit('apiBase', text)}\n onReset={() => onReset('apiBase')}\n t={t}\n />\n <Field\n id=\"cc-working-dir\"\n label={t('workingDir')}\n hint={t('workingDirHint')}\n state={state.workingDir}\n disabled={disabled}\n placeholder={state.defaultWorkingDir}\n onEdit={(text) => onEdit('workingDir', text)}\n onReset={() => onReset('workingDir')}\n t={t}\n />\n <Field\n id=\"cc-request-timeout\"\n label={t('requestTimeoutMs')}\n hint={t('requestTimeoutMsHint')}\n state={state.requestTimeoutMs}\n disabled={disabled}\n numeric\n onEdit={(text) => onEdit('requestTimeoutMs', text)}\n onReset={() => onReset('requestTimeoutMs')}\n t={t}\n />\n <Field\n id=\"cc-stream-idle-timeout\"\n label={t('streamIdleTimeoutMs')}\n hint={t('streamIdleTimeoutMsHint')}\n state={state.streamIdleTimeoutMs}\n disabled={disabled}\n numeric\n onEdit={(text) => onEdit('streamIdleTimeoutMs', text)}\n onReset={() => onReset('streamIdleTimeoutMs')}\n t={t}\n />\n <ToggleField\n id=\"cc-filter-models-by-plan\"\n label={t('filterModelsByPlan')}\n hint={t('filterModelsByPlanHint')}\n state={state.filterModelsByPlan}\n disabled={disabled}\n defaultChecked\n onEdit={(text) => onEdit('filterModelsByPlan', text)}\n onReset={() => onReset('filterModelsByPlan')}\n t={t}\n />\n </div>\n ) : null}\n {expanded && invalid ? (\n <p className=\"cc-invalid\" role=\"status\">{t('advancedInvalid')}</p>\n ) : null}\n </div>\n )\n}\n\n/**\n * One boolean field row rendered as a toggle. The staged text is `'true'` /\n * `'false'` / `''` (unset → `defaultChecked`); toggling stages the string the\n * boolean field spec parses back into a real boolean on save.\n */\nfunction ToggleField({\n id,\n label,\n hint,\n state,\n disabled,\n defaultChecked,\n onEdit,\n onReset,\n t,\n}: {\n id: string\n label: string\n hint: string\n state: StagedField\n disabled: boolean\n defaultChecked: boolean\n onEdit(text: string): void\n onReset(): void\n t: Translate<SettingsCommandCodeKey>\n}) {\n const checked = state.text === '' ? defaultChecked : state.text === 'true'\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor={id}>{label}</label>\n <span className=\"cc-badges\">\n {state.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null}\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onReset}>{t('reset')}</button>\n </span>\n </div>\n <label className=\"cc-toggleRow\">\n <input\n id={id}\n className=\"cc-toggle\"\n type=\"checkbox\"\n role=\"switch\"\n checked={checked}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.checked ? 'true' : 'false')}\n />\n <span className=\"cc-hint\">{hint}</span>\n </label>\n </div>\n )\n}\n\n/**\n * The API-key control: write-only, reports configured state, never echoes the\n * key. The input is masked by default with a Show/Hide toggle so a pasted key\n * can be spot-checked without leaving the field, and a stored key can be\n * staged for removal (the next save unsets it) when it is bad or unwanted.\n */\nfunction SecretKeyField({\n label,\n hint,\n state,\n disabled,\n configured,\n configuredLabel,\n unconfiguredLabel,\n clearStaged,\n showLabel,\n hideLabel,\n clearLabel,\n clearStagedLabel,\n undoClearLabel,\n onEdit,\n onToggleClear,\n}: {\n label: string\n hint: string\n state: StagedField\n disabled: boolean\n configured: boolean\n configuredLabel: string\n unconfiguredLabel: string\n clearStaged: boolean\n showLabel: string\n hideLabel: string\n clearLabel: string\n clearStagedLabel: string\n undoClearLabel: string\n onEdit(text: string): void\n onToggleClear(): void\n}) {\n const [visible, setVisible] = useState(false)\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor=\"cc-api-key\">{label}</label>\n <span className=\"cc-badges\">\n <span className={configured ? 'cc-badge' : 'cc-badgeMuted'}>\n {configured ? configuredLabel : unconfiguredLabel}\n </span>\n {clearStaged ? <span className=\"cc-badge cc-badgeWarn\">{clearStagedLabel}</span> : null}\n {configured ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onToggleClear}>\n {clearStaged ? undoClearLabel : clearLabel}\n </button>\n ) : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={disabled}\n onClick={() => setVisible((value) => !value)}\n >\n {visible ? hideLabel : showLabel}\n </button>\n </span>\n </div>\n <input\n id=\"cc-api-key\"\n className=\"cc-input\"\n type={visible ? 'text' : 'password'}\n autoComplete=\"off\"\n spellCheck={false}\n value={state.text}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n <p className=\"cc-hint\">{hint}</p>\n </div>\n )\n}\n\n/** The per-reason copy for a failed login attempt. */\nfunction loginFailureCopy(reason: CommandCodeLoginFailureReason | undefined, t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'denied') return t('loginDenied')\n if (reason === 'timeout') return t('loginTimeout')\n if (reason === 'invalid-key') return t('loginInvalidKey')\n if (reason === 'network') return t('loginNetwork')\n if (reason === 'unavailable') return t('loginStoreFailed')\n if (reason === 'cancelled') return t('loginCancelled')\n return t('loginFailedGeneric')\n}\n\n/**\n * The sign-in alternative to pasting a key: one field row that starts the\n * Host-side browser login, links to the Studio authorization page while the\n * attempt is live, and reports the outcome. The key itself never crosses to\n * the browser — only \"who signed in\" does.\n */\nfunction LoginPanel({ state, disabled, t, onBegin, onCancel }: {\n state: LoginPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onBegin(): void\n onCancel(): void\n}) {\n const busy = state.phase === 'starting' || state.phase === 'waiting'\n let hint = t('loginHintIdle')\n let hintTitle: string | undefined\n let hintClass = 'cc-hint'\n if (state.phase === 'starting' || state.phase === 'waiting') hint = t(state.phase === 'starting' ? 'loginStarting' : 'loginWaiting')\n else if (state.phase === 'success') {\n const keyName = state.keyName !== undefined && state.keyName !== '' ? ` · ${state.keyName}` : ''\n hint = `${t('loginSuccess')} ${state.userName ?? ''}${keyName}`.trim()\n hintClass = 'cc-loginDone'\n } else if (state.phase === 'failed') {\n hint = loginFailureCopy(state.reason, t)\n hintClass = 'cc-loginError'\n if (state.message !== undefined) hintTitle = state.message\n } else if (state.phase === 'unavailable') {\n hint = `${t('loginUnavailable')} ${state.message ?? ''}`.trim()\n hintClass = 'cc-loginError'\n }\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\">{t('loginTitle')}</label>\n <span className=\"cc-badges\">\n {busy ? (\n <button type=\"button\" className=\"cc-reset\" onClick={onCancel}>{t('loginCancel')}</button>\n ) : (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onBegin}>{t('loginButton')}</button>\n )}\n </span>\n </div>\n {state.authUrl !== undefined ? (\n <p className=\"cc-hint\">\n <a className=\"cc-loginLink\" href={state.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n </p>\n ) : null}\n <p className={hintClass} title={hintTitle}>{hint}</p>\n </div>\n )\n}\n\n/** One stat tile in the account card's summary grid. */\nfunction UsageStat({ label, value, sub }: { label: string; value: string; sub?: string | undefined }) {\n return (\n <div className=\"cc-usageStat\">\n <span className=\"cc-usageStatLabel\">{label}</span>\n <span className=\"cc-usageStatValue\">{value}</span>\n {sub !== undefined && sub !== '' ? <span className=\"cc-usageStatSub\">{sub}</span> : null}\n </div>\n )\n}\n\n/** One window-limit row: label, used/cap, a fill bar, and the reset time. */\nfunction UsageWindow({\n label,\n limit: { used, cap, exceeded, resetAt },\n t,\n}: {\n label: string\n limit: CommandCodeCredits['fiveHour']\n t: Translate<SettingsCommandCodeKey>\n}) {\n const ratio = windowRatio(used, cap)\n const reset = formatResetAt(resetAt)\n return (\n <div className=\"cc-usageWindow\">\n <div className=\"cc-usageWindowHead\">\n <span className=\"cc-usageWindowLabel\">{label}</span>\n {exceeded ? <span className=\"cc-usageExceeded\">{t('usageExceeded')}</span> : null}\n <span className=\"cc-usageWindowValue\">{cap > 0 ? `${formatMoney(used)} / ${formatMoney(cap)}` : formatMoney(used)}</span>\n </div>\n <div className=\"cc-usageBar\" role=\"progressbar\" aria-valuemin={0} aria-valuemax={100} aria-valuenow={Math.round(ratio * 100)}>\n <div className={exceeded ? 'cc-usageBarFill cc-usageBarFillWarn' : 'cc-usageBarFill'} style={{ width: `${ratio * 100}%` }} />\n </div>\n {reset !== '' ? <p className=\"cc-usageWindowReset\">{t('usageReset')} {reset}</p> : null}\n </div>\n )\n}\n\n/** One account's rotation state as a short badge next to its label. */\nfunction AccountMark({ entry, t }: { entry: CommandCodeAccountUsage; t: Translate<SettingsCommandCodeKey> }) {\n if (entry.active) return <span className=\"cc-usagePlan\">{t('usageActive')}</span>\n if (entry.mark === 'invalid-credential') return <span className=\"cc-usagePlanStatus\">{t('usageInvalidKey')}</span>\n if (entry.cooldownUntil > 0) {\n return <span className=\"cc-usagePlanStatus\">{t('usageCooldown')} {formatResetAt(entry.cooldownUntil)}</span>\n }\n if (entry.mark === 'rate-limit') return <span className=\"cc-usagePlanStatus\">{t('usageCooldown')}</span>\n return null\n}\n\n/**\n * One pool account's facts (identity, totals, credits, window limits)\n * rendered inside the account-usage card.\n */\nfunction AccountReport({ entry, fetchedAt, t, onRemove }: {\n entry: CommandCodeAccountUsage\n /**\n * When the shared usage snapshot was fetched — shares the account's bottom\n * meta row with the billing period end so the two timestamps occupy one\n * line (period/partial facts left, fetch freshness right).\n */\n fetchedAt?: number | undefined\n t: Translate<SettingsCommandCodeKey>\n /** Present only for removable (non-default) accounts on a writable page. */\n onRemove?: (() => void) | undefined\n}) {\n const report = entry.report\n const account = report.account\n const accountName = account === undefined ? '' : account.userName || account.name\n const credits = report.credits\n const plan = report.plan\n const planName = plan?.name ?? ''\n const planStatus = plan !== undefined && plan.status !== '' && plan.status !== 'active' ? plan.status : ''\n const showPeriod = plan !== undefined && plan.currentPeriodEnd > 0\n const showPartial = report.failures.length > 0 && report.blocked === undefined\n\n return (\n <div className=\"cc-accountReport\">\n <div className=\"cc-usageHead\">\n <h4 className=\"cc-usageTitle\">{entry.label}</h4>\n <AccountMark entry={entry} t={t} />\n {accountName !== '' ? <span className=\"cc-usageAccount\">{accountName}</span> : null}\n {planName !== '' ? <span className=\"cc-usagePlan\">{planName}</span> : null}\n {planStatus !== '' ? <span className=\"cc-usagePlanStatus\">{planStatus}</span> : null}\n <span className=\"cc-usageMetaSpacer\" />\n {onRemove !== undefined ? (\n <button type=\"button\" className=\"cc-usageRefresh\" onClick={onRemove}>{t('accountRemove')}</button>\n ) : null}\n </div>\n\n {!entry.configured ? <p className=\"cc-usageHint\">{t('usageUnconfigured')}</p> : null}\n\n {report.blocked !== undefined ? (\n <div className=\"cc-usageBlocked\" role=\"alert\">\n <p className=\"cc-usageBlockedTitle\">{blockedTitle(report.blocked, t)}</p>\n <p className=\"cc-usageBlockedHint\">{blockedHint(report.blocked, t)}</p>\n </div>\n ) : null}\n\n {report.usage !== undefined ? (\n <div className=\"cc-usageStats\">\n <UsageStat\n label={t('usageRequests')}\n value={String(report.usage.completedCount)}\n sub={`${t('usageFailed')} ${report.usage.failedCount}`}\n />\n <UsageStat label={t('usageSuccessRate')} value={`${report.usage.successRate}%`} />\n <UsageStat\n label={t('usageCost')}\n value={formatMoneyExact(report.usage.totalCost)}\n sub={`${formatMoney(report.usage.totalCredits)} credits`}\n />\n <UsageStat\n label={t('usageTokens')}\n value={formatTokensCompact(report.usage.totalTokensIn + report.usage.totalTokensOut)}\n sub={`${formatTokensCompact(report.usage.totalTokensIn)} ${t('usageTokensIn')} / ${formatTokensCompact(report.usage.totalTokensOut)} ${t('usageTokensOut')}`}\n />\n </div>\n ) : null}\n\n {credits !== undefined ? (\n <div className=\"cc-usageStats\">\n <UsageStat label={t('usageMonthly')} value={formatMoney(credits.monthlyCredits)} />\n <UsageStat label={t('usagePurchased')} value={formatMoney(credits.purchasedCredits)} />\n <UsageStat label={t('usageFree')} value={formatMoney(credits.freeCredits)} />\n </div>\n ) : null}\n\n {credits !== undefined ? (\n <div className=\"cc-usageWindows\">\n <UsageWindow label={t('usageFiveHour')} limit={credits.fiveHour} t={t} />\n <UsageWindow label={t('usageWeekly')} limit={credits.weekly} t={t} />\n </div>\n ) : null}\n\n {showPeriod || showPartial || fetchedAt !== undefined ? (\n <div className=\"cc-usageMeta\">\n {showPeriod ? (\n <p className=\"cc-usageUpdated\">{t('usagePeriodEnd')} {new Date(plan.currentPeriodEnd).toLocaleDateString()}</p>\n ) : null}\n {showPartial ? (\n <p className=\"cc-usagePartial\" title={report.failures.join('; ')}>{t('usagePartial')}</p>\n ) : null}\n <span className=\"cc-usageMetaSpacer\" />\n {fetchedAt !== undefined ? (\n <p className=\"cc-usageUpdated\">{t('usageUpdated')} {new Date(fetchedAt).toLocaleTimeString()}</p>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n\n/** The headline copy for a report whose every endpoint failed the same way. */\nfunction blockedTitle(reason: CommandCodeUsageReport['blocked'], t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'invalid-key') return t('usageKeyInvalid')\n if (reason === 'service-unavailable') return t('usageServiceUnavailable')\n return t('usageNetworkError')\n}\n\n/** The actionable hint under a blocked report's headline. */\nfunction blockedHint(reason: CommandCodeUsageReport['blocked'], t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'invalid-key') return t('usageKeyInvalidHint')\n if (reason === 'service-unavailable') return t('usageServiceUnavailableHint')\n return t('usageNetworkHint')\n}\n\n/** The status dot on an account tab: cooling/invalid warn, everything else ok. */\nfunction AccountTabDot({ entry }: { entry: CommandCodeAccountUsage }) {\n const cls = entry.mark === 'invalid-credential'\n ? 'cc-tabDot cc-tabDotError'\n : entry.mark !== '' || entry.cooldownUntil > 0\n ? 'cc-tabDot cc-tabDotWarn'\n : 'cc-tabDot cc-tabDotOk'\n return <span className={cls} />\n}\n\n/**\n * The account-usage card: the `/commandcode` dashboard's facts rendered as\n * a native settings card. With several accounts the card is a carousel — a\n * tab strip (label + status dot) switches between accounts so the page stays\n * short; each account's report carries its own remove affordance (the\n * default account is not removable). Accounts staged for removal in the\n * management card are hidden here immediately. Data arrives through the\n * `commandcode/report` Remote; the API keys never leave the Host.\n */\nfunction UsageCard({ t, usage, apiKeyConfigured, removingIds, removableIds, canManage, onRefresh, onRemoveAccount }: {\n t: Translate<SettingsCommandCodeKey>\n usage: UsagePageState\n apiKeyConfigured: boolean\n /** Ids of accounts staged for removal (hidden from the carousel). */\n removingIds: string[]\n /**\n * Ids of accounts the settings document can actually remove (the stored\n * extra accounts' refs). Composition-only accounts (literal-key slots with\n * positional `account-N` ids) are NOT removable from the page — the\n * settings document cannot name them — so they get no remove button.\n */\n removableIds: string[]\n /** Whether the page accepts writes (the remove affordance follows it). */\n canManage: boolean\n onRefresh(): void\n onRemoveAccount(id: string): void\n}) {\n // First paint with a configured key fetches automatically; later fetches\n // are explicit (refresh button) or follow a landed save.\n useEffect(() => {\n if (apiKeyConfigured && usage.status === 'idle') onRefresh()\n }, [apiKeyConfigured, usage.status, onRefresh])\n\n const loading = usage.status === 'loading'\n const report = usage.report\n // Locally remembered removals: the usage controller keeps the old report\n // until the post-save refresh lands, and removedRefs clears at save-land —\n // without this the just-removed account would pop back in for one refresh\n // round-trip. Cleared when a fresh report arrives (fetchedAt changes).\n const [locallyRemoved, setLocallyRemoved] = useState<readonly string[]>([])\n useEffect(() => {\n setLocallyRemoved([])\n }, [usage.fetchedAt])\n const hidden = new Set([...removingIds, ...locallyRemoved])\n const seenIds = new Set<string>()\n const entries = (report?.accounts ?? []).filter((entry) => {\n if (hidden.has(entry.id)) return false\n // Hand-edited settings can name the same credential ref twice; dedupe so\n // the tab strip never carries duplicate keys/selections.\n if (seenIds.has(entry.id)) return false\n seenIds.add(entry.id)\n return true\n })\n const [selectedId, setSelectedId] = useState<string | undefined>(undefined)\n // The selected tab: the explicit choice while it still exists, else the\n // serving (active) account, else the first entry.\n const selected = entries.find((entry) => entry.id === selectedId)\n ?? entries.find((entry) => entry.active)\n ?? entries[0]\n const removeSelected = canManage && selected !== undefined && removableIds.includes(selected.id)\n ? () => {\n const id = selected.id\n setLocallyRemoved((prev) => [...prev, id])\n onRemoveAccount(id)\n }\n : undefined\n\n return (\n <div className=\"cc-usageCard\" aria-label={t('usageTitle')}>\n <div className=\"cc-usageHead\">\n <h3 className=\"cc-usageTitle\">{t('usageTitle')}</h3>\n <span className=\"cc-usageMetaSpacer\" />\n <button type=\"button\" className=\"cc-usageRefresh\" disabled={loading || !apiKeyConfigured} onClick={onRefresh}>\n {loading ? t('usageRefreshing') : t('usageRefresh')}\n </button>\n </div>\n\n {!apiKeyConfigured ? <p className=\"cc-usageHint\">{t('usageNoKey')}</p> : null}\n {apiKeyConfigured && report === undefined && loading ? <p className=\"cc-usageHint\">{t('usageLoading')}</p> : null}\n {usage.status === 'error' ? (\n <p className=\"cc-usageError\" role=\"status\">\n <span>{t('usageError')}{usage.error !== undefined && usage.error !== '' ? ` — ${usage.error}` : ''}</span>\n </p>\n ) : null}\n\n {entries.length > 1 ? (\n <div className=\"cc-tabs\" role=\"tablist\" aria-label={t('accountsTitle')}>\n {entries.map((entry) => (\n <button\n key={entry.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected?.id === entry.id}\n className={selected?.id === entry.id ? 'cc-tab cc-tabActive' : 'cc-tab'}\n onClick={() => setSelectedId(entry.id)}\n >\n <AccountTabDot entry={entry} />\n {entry.label}\n </button>\n ))}\n </div>\n ) : null}\n\n {selected !== undefined ? (\n <AccountReport\n key={selected.id}\n entry={selected}\n fetchedAt={usage.fetchedAt}\n t={t}\n onRemove={removeSelected}\n />\n ) : null}\n </div>\n )\n}\n\n/**\n * One extra account row: label, key, configured badge. Saved accounts are\n * removed from the usage card above; a NOT-YET-SAVED addition never appears\n * there (the usage report is Host-side), so it keeps its own remove button —\n * otherwise the only way to undo a mistaken Add would be discarding every\n * other staged edit.\n */\nfunction AccountRow({ account, disabled, t, onLabel, onKey, onToggleClear, onRemove }: {\n account: AccountItemState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onLabel(text: string): void\n onKey(text: string): void\n onToggleClear(): void\n onRemove(): void\n}) {\n const locked = !account.writable\n const [keyVisible, setKeyVisible] = useState(false)\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor={`cc-account-label-${account.id}`}>{t('accountLabel')}</label>\n <span className=\"cc-badges\">\n {account.added ? <span className=\"cc-badge\">{t('unsaved')}</span> : null}\n <span className={account.configured ? 'cc-badge' : 'cc-badgeMuted'}>\n {account.configured ? t('apiKeySet') : t('apiKeyUnset')}\n </span>\n {account.clearStaged ? <span className=\"cc-badge cc-badgeWarn\">{t('usageKeyClearStaged')}</span> : null}\n {account.configured && !account.clearStaged ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onToggleClear}>\n {t('usageKeyClear')}\n </button>\n ) : null}\n {account.clearStaged ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onToggleClear}>\n {t('usageUndoKeyClear')}\n </button>\n ) : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={disabled}\n onClick={() => setKeyVisible((value) => !value)}\n >\n {keyVisible ? t('hide') : t('show')}\n </button>\n {account.added ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onRemove}>{t('accountRemove')}</button>\n ) : null}\n </span>\n </div>\n <input\n id={`cc-account-label-${account.id}`}\n className=\"cc-input\"\n type=\"text\"\n value={account.label}\n disabled={disabled}\n onChange={(event) => onLabel(event.target.value)}\n />\n <input\n id={`cc-account-key-${account.id}`}\n className=\"cc-input\"\n type={keyVisible ? 'text' : 'password'}\n autoComplete=\"off\"\n spellCheck={false}\n placeholder={t('accountKey')}\n value={account.keyText}\n disabled={disabled || locked}\n onChange={(event) => onKey(event.target.value)}\n />\n <p className=\"cc-hint\">{locked ? t('apiKeyLocked') : t('accountKeyHint')}</p>\n </div>\n )\n}\n\n/** The multi-account card: the active-account selector + extra accounts in rotation order + add button. */\nfunction AccountsCard({ t, state, disabled, onAdd, onRemove, onLabel, onKey, onToggleClear, onActive, onActiveReset }: {\n t: Translate<SettingsCommandCodeKey>\n state: SettingsPageState\n disabled: boolean\n onAdd(): void\n onRemove(id: string): void\n onLabel(id: string, text: string): void\n onKey(id: string, text: string): void\n onToggleClear(id: string): void\n onActive(text: string): void\n onActiveReset(): void\n}) {\n const active = state.activeAccount\n return (\n <div className=\"cc-card\" aria-label={t('accountsTitle')}>\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\">{t('accountsTitle')}</label>\n <span className=\"cc-badges\">\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onAdd}>{t('accountAdd')}</button>\n </span>\n </div>\n <p className=\"cc-hint\">{t('accountsHint')}</p>\n </div>\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor=\"cc-active-account\">{t('activeAccount')}</label>\n <span className=\"cc-badges\">\n {active.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null}\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onActiveReset}>{t('reset')}</button>\n </span>\n </div>\n <select\n id=\"cc-active-account\"\n className=\"cc-input\"\n value={active.text}\n disabled={disabled}\n onChange={(event) => onActive(event.target.value)}\n >\n <option value=\"\">{t('activeAccountAuto')}</option>\n <option value=\"default\">{t('accountDefault')}</option>\n {state.accounts.filter((account) => !account.added).map((account) => (\n <option key={account.id} value={account.ref}>{account.label}</option>\n ))}\n </select>\n <p className=\"cc-hint\">{t('activeAccountHint')}</p>\n </div>\n {state.accounts.map((account) => (\n <AccountRow\n key={account.id}\n account={account}\n disabled={disabled}\n t={t}\n onLabel={(text) => onLabel(account.id, text)}\n onKey={(text) => onKey(account.id, text)}\n onToggleClear={() => onToggleClear(account.id)}\n onRemove={() => onRemove(account.id)}\n />\n ))}\n </div>\n )\n}\n\n/** One model → account routing rule row. */\nfunction RuleRow({ rule, accounts, catalog, disabled, t, onModels, onAccount, onRemove }: {\n rule: RuleItemState\n accounts: AccountItemState[]\n catalog: CatalogModelOption[]\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onModels(ids: string[]): void\n onAccount(text: string): void\n onRemove(): void\n}) {\n const targets = [\n { value: 'default', label: t('accountDefault') },\n ...accounts.filter((account) => !account.added).map((account) => ({ value: account.ref, label: account.label })),\n ]\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor={`cc-rule-model-${rule.id}`}>{t('ruleModel')}</label>\n <span className=\"cc-badges\">\n {rule.added ? <span className=\"cc-badge\">{t('unsaved')}</span> : null}\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onRemove}>{t('ruleRemove')}</button>\n </span>\n </div>\n <ModelMultiSelect\n id={`cc-rule-model-${rule.id}`}\n selected={rule.models}\n catalog={catalog}\n disabled={disabled}\n t={t}\n onSelect={onModels}\n />\n <select\n id={`cc-rule-account-${rule.id}`}\n className=\"cc-input\"\n value={rule.account}\n disabled={disabled}\n onChange={(event) => onAccount(event.target.value)}\n >\n {targets.map((target) => (\n <option key={target.value} value={target.value}>{target.label}</option>\n ))}\n </select>\n <p className=\"cc-hint\">{t('ruleHint')}</p>\n </div>\n )\n}\n\n/**\n * A checkbox multi-select dropdown for routing-rule models. The trigger shows\n * the selection count; the anchored Menu lists every catalog model with a\n * checkbox, toggled by clicking the row. Selected ids the catalog no longer\n * carries still render so a saved rule never silently loses a selection.\n */\nfunction ModelMultiSelect({ id, selected, catalog, disabled, t, onSelect }: {\n id: string\n selected: string[]\n catalog: CatalogModelOption[]\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onSelect(ids: string[]): void\n}) {\n const [open, setOpen] = useState(false)\n // The catalog is sorted for picking; append any selected ids the catalog no\n // longer carries (removed upstream) so the current rule stays visible.\n const options = [\n ...catalog.map((model) => ({ value: model.id, label: model.name })),\n ...selected\n .filter((id) => !catalog.some((model) => model.id === id))\n .map((id) => ({ value: id, label: id })),\n ]\n const selectedSet = new Set(selected)\n const items: MenuEntry[] = options.map((option) => ({\n id: option.value,\n label: (\n <span className=\"cc-checkRow\">\n <input\n type=\"checkbox\"\n className=\"cc-check\"\n checked={selectedSet.has(option.value)}\n readOnly\n tabIndex={-1}\n />\n <span className=\"cc-checkName\">{option.label}</span>\n </span>\n ),\n }))\n return (\n <Menu\n open={open}\n onClose={() => setOpen(false)}\n onSelect={(modelId) => {\n // Toggle one model in the selection.\n onSelect(selectedSet.has(modelId)\n ? selected.filter((value) => value !== modelId)\n : [...selected, modelId])\n }}\n selectedIds={selected}\n items={items}\n portal\n anchor={\n <button\n id={id}\n type=\"button\"\n className=\"cc-input cc-ruleTrigger\"\n disabled={disabled || catalog.length === 0}\n onClick={() => setOpen((value) => !value)}\n >\n <span className=\"cc-ruleTriggerText\">\n {selected.length === 0 ? t('ruleModelPick') : t('ruleModelCount', { count: selected.length })}\n </span>\n <span className=\"cc-ruleCaret\" aria-hidden=\"true\" />\n </button>\n }\n />\n )\n}\n\n/** The model → account routing card: rules in list order (first match wins). */\nfunction RulesCard({ t, state, disabled, onAdd, onRemove, onModels, onAccount }: {\n t: Translate<SettingsCommandCodeKey>\n state: SettingsPageState\n disabled: boolean\n onAdd(): void\n onRemove(id: string): void\n onModels(id: string, ids: string[]): void\n onAccount(id: string, text: string): void\n}) {\n return (\n <div className=\"cc-card\" aria-label={t('rulesTitle')}>\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\">{t('rulesTitle')}</label>\n <span className=\"cc-badges\">\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onAdd}>{t('ruleAdd')}</button>\n </span>\n </div>\n <p className=\"cc-hint\">{t('rulesHint')}</p>\n {state.catalogFailed ? <p className=\"cc-invalid\">{t('rulesCatalogFailed')}</p> : null}\n </div>\n {state.rules.map((rule) => (\n <RuleRow\n key={rule.id}\n rule={rule}\n accounts={state.accounts}\n catalog={state.catalogModels}\n disabled={disabled}\n t={t}\n onModels={(ids) => onModels(rule.id, ids)}\n onAccount={(text) => onAccount(rule.id, text)}\n onRemove={() => onRemove(rule.id)}\n />\n ))}\n {state.rules.length === 0 ? <p className=\"cc-hint\">{t('rulesEmpty')}</p> : null}\n </div>\n )\n}\n\n/**\n * Show the \"Saved ✓\" affordance for a short window after each accepted save.\n * The controller only counts saves (`savedCount`); the flash timing lives\n * here so the state machine stays timer-free.\n */\nfunction useSavedFlash(tick: number): boolean {\n const [visible, setVisible] = useState(false)\n useEffect(() => {\n if (tick === 0) return\n setVisible(true)\n const timer = setTimeout(() => setVisible(false), 2500)\n return () => clearTimeout(timer)\n }, [tick])\n return visible\n}\n\n/**\n * The update hint: one throttled npm-registry check per page open (the\n * throttle and all failure handling live in ./update.ts). Resolves to the\n * newest published version when it is newer than this build, else undefined —\n * every failure mode degrades to no hint at all.\n */\nfunction usePluginUpdate(): string | undefined {\n const [available, setAvailable] = useState<string | undefined>(undefined)\n useEffect(() => {\n let cancelled = false\n void checkForUpdate({\n currentVersion: PLUGIN_VERSION,\n now: Date.now(),\n store: localStorageUpdateStore(),\n }).then((version) => {\n if (!cancelled) setAvailable(version)\n // A rejected checkForUpdate would be a bug (it catches internally);\n // swallow it regardless — the footer must never break the page.\n }, () => {})\n return () => {\n cancelled = true\n }\n }, [])\n return available\n}\n\n/** The settings page body: connection facts for the Command Code provider. */\nexport function CommandCodeSettingsPage(props: CommandCodeSettingsProps) {\n const { t } = props\n const state = props.useCommandCodeSettings((snapshot) => snapshot)\n const usage = props.useCommandCodeUsage((snapshot) => snapshot)\n const login = props.useCommandCodeLogin((snapshot) => snapshot)\n const disabled = !state.writable\n const keyLocked = !state.apiKeyWritable\n const savedVisible = useSavedFlash(state.savedCount)\n const updateVersion = usePluginUpdate()\n return (\n <section className=\"cc-section\" aria-label={t('title')}>\n <h2 className=\"cc-title\">{t('title')}</h2>\n <p className=\"cc-intro\">{t('intro')}</p>\n {!state.writable ? <p className=\"cc-readOnly\" role=\"status\">{t('readOnly')}</p> : null}\n <UsageCard\n t={t}\n usage={usage}\n apiKeyConfigured={state.anyAccountConfigured}\n removingIds={state.accountsRemoving}\n removableIds={state.accounts.map((account) => account.id)}\n canManage={state.writable}\n onRefresh={props.refreshUsage}\n onRemoveAccount={props.removeAccount}\n />\n <AccountsCard\n t={t}\n state={state}\n disabled={disabled}\n onAdd={props.addAccount}\n onRemove={props.removeAccount}\n onLabel={props.editAccountLabel}\n onKey={props.editAccountKey}\n onToggleClear={(id) => props.toggleKeyClear(id)}\n onActive={(text) => props.edit('activeAccount', text)}\n onActiveReset={() => props.resetField('activeAccount')}\n />\n <RulesCard\n t={t}\n state={state}\n disabled={disabled}\n onAdd={props.addRule}\n onRemove={props.removeRule}\n onModels={props.editRuleModels}\n onAccount={props.editRuleAccount}\n />\n <div className=\"cc-card\">\n <SecretKeyField\n label={t('apiKey')}\n hint={keyLocked ? t('apiKeyLocked') : t('apiKeyHint')}\n state={state.apiKey}\n disabled={disabled || keyLocked}\n configured={state.apiKeyConfigured}\n configuredLabel={t('apiKeySet')}\n unconfiguredLabel={t('apiKeyUnset')}\n clearStaged={state.apiKeyClearStaged}\n showLabel={t('show')}\n hideLabel={t('hide')}\n clearLabel={t('usageKeyClear')}\n clearStagedLabel={t('usageKeyClearStaged')}\n undoClearLabel={t('usageUndoKeyClear')}\n onEdit={(text) => props.edit('apiKey', text)}\n onToggleClear={() => props.toggleKeyClear('default')}\n />\n <LoginPanel\n state={login}\n disabled={disabled || keyLocked}\n t={t}\n onBegin={props.beginLogin}\n onCancel={props.cancelLogin}\n />\n </div>\n <AdvancedSection\n state={state}\n disabled={disabled}\n t={t}\n onEdit={props.edit}\n onReset={props.resetField}\n />\n <div className=\"cc-footer\">\n {state.failed ? <p className=\"cc-failed\" role=\"status\">{t('saveFailed')}</p> : null}\n {savedVisible ? <p className=\"cc-saved\" role=\"status\">{t('saved')}</p> : null}\n <Button variant=\"ghost\" size=\"sm\" disabled={!state.dirty || state.saving} onClick={props.discard}>\n {t('discard')}\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={!state.dirty || state.invalid || state.saving}\n onClick={props.save}\n >\n {t(state.saving ? 'saving' : 'save')}\n </Button>\n </div>\n <p className=\"cc-version\">\n Command Code Provider v{PLUGIN_VERSION}\n {updateVersion !== undefined ? (\n <>\n {' · '}\n <a\n className=\"cc-versionLink\"\n href={PLUGIN_RELEASES_URL}\n target=\"_blank\"\n rel=\"noreferrer\"\n title={t('updateHint')}\n >\n v{updateVersion} {t('updateAvailable')}\n </a>\n </>\n ) : null}\n </p>\n </section>\n )\n}\n","/**\n * The Command Code configuration panel inside the harness Models settings page\n * (browser half). Rendered through the `settings.models.provider-card` keyed\n * slot available in dsh 0.1.2-alpha.2, registered with\n * `entryKey = 'llm-commandcode'` (the plugin's settings namespace, the key the\n * Models page dispatches for every Command Code provider row).\n *\n * The official Models page opens one editor card per provider row through its\n * own 编辑 button. For a namespace the page does not curate a layout for\n * (`llm-commandcode`), that editor is a bare shell — a pointer to\n * `settings.yaml` above a permanently disabled apply button. This panel takes\n * its place: the slot outlet renders right beside the official editor inside\n * the same row card, so the component watches the outlet's siblings and, while\n * the official editor is open, hides the useless shell and shows the real\n * controls in its slot — the credential/route badges, the API-key field,\n * official sign-in, and the discard/save footer. Closed, it renders nothing\n * and the row looks exactly like any other provider row.\n *\n * The slot's owner props (`configured`, `keyConfigured`) mirror what the\n * Models page already knows; the authoritative credential facts still come\n * from this plugin's `CommandCodeSettingsController` shared with the dedicated\n * settings page, so the two surfaces can never disagree about whether a key\n * is stored.\n *\n * A controller-less render (panel mounted before the section registered its\n * inject face — the composition runs one apply) degrades to the stateless\n * registration notice inside the opened panel.\n *\n * Styles ride the page stylesheet the client entry injects once (`cc-`\n * prefixed classes); the card adds no CSS of its own.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsCommandCodeKey } from './locales.ts'\nimport type { SettingsPageState, StagedField } from './settings.ts'\nimport type { LoginPageState } from './login.ts'\nimport type { CommandCodeLoginFailureReason } from '../login-wire.ts'\n\n/**\n * The Models-page extension slots, merged into the SlotMap with the exact\n * declarations dsh 0.1.2-alpha.2's ui-settings-models ships. The merge must\n * stay structurally identical to upstream's (kind/scope/owner), or a future\n * dsh carrying its own declaration would fail the duplicate-merge check at\n * compile time.\n */\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n /** One provider card's adapter extension area, keyed by the row's settingsNs. */\n 'settings.models.provider-card': { kind: 'keyed'; scope: 'root'; owner: ProviderCardExtrasOwnerProps }\n /** Ordered extension area after the provider rows and the add controls. */\n 'settings.models.footer': { kind: 'list'; scope: 'root'; owner: ModelsFooterOwnerProps }\n }\n}\n\n/** The provider directory row as the Models page dispatches it. */\nexport interface ProviderDirectoryRow {\n /** The provider route id (`commandcode` for this plugin). */\n readonly provider: string\n /** The row's display name. */\n readonly displayName: string\n /** The settings namespace the row configures (the slot's dispatch key). */\n readonly settingsNs: string\n /** The settings path the row's profile lives at. */\n readonly settingsPath: readonly string[]\n /** Whether the provider route is live. */\n readonly active: boolean\n /** Whether the adapter declares the route as shipped. */\n readonly declared?: boolean\n}\n\n/** Owner share of one provider-card extension occurrence (upstream's shape). */\nexport interface ProviderCardExtrasOwnerProps {\n /** The card's directory row. */\n readonly provider: ProviderDirectoryRow\n /** Whether any layer configures this provider (its profile resolves). */\n readonly configured: boolean\n /** The row's referenced api-key credential, confirmed configured by the page's join. */\n readonly keyConfigured: boolean\n}\n\n/** Owner share of the footer area (the section supplies nothing). */\nexport interface ModelsFooterOwnerProps {\n /** Marker field: footer owner props are intentionally empty. */\n children?: never\n}\n\n/** Owner props the Models page supplies at its dispatch sites. */\nexport type ProviderCardOwnerProps = ProviderCardExtrasOwnerProps\n\n/**\n * The slot whose outlet anchors this panel inside the Models row — the\n * renderer's own `data-slot` attribute value, stable across builds (unlike\n * CSS-module class hashes).\n */\nexport const CARD_SLOT_KEY = 'settings.models.provider-card'\n\n/** The DOM facts the sibling lookup reads (satisfied by real Elements). */\nexport interface SlotWrapperSiblings {\n previousElementSibling: { className: string } | null\n nextElementSibling: { className: string } | null\n}\n\n/**\n * Find the official editor card among the slot outlet's siblings, or null\n * while it is closed. The Models page renders the editor as an immediate\n * sibling of the outlet wrapper — after it in a provider row (the target of\n * the row's 编辑 toggle), before it in the first-run setup card and the\n * add-provider card, where it is always open. The editor is the only such\n * sibling whose CSS module class carries the `editor` stem\n * (`<hash>_editor`); the row header and the add card's provider select\n * never do, so the lookup needs no hash knowledge.\n */\nexport function adjacentEditorCard(wrapper: SlotWrapperSiblings | null): { className: string } | null {\n if (wrapper === null) return null\n for (const sibling of [wrapper.previousElementSibling, wrapper.nextElementSibling]) {\n if (sibling !== null && typeof sibling.className === 'string' && sibling.className.includes('editor')) {\n return sibling\n }\n }\n return null\n}\n\n/** The closed-panel style: the outlet stays mounted as the detection anchor. */\nconst HIDDEN_STYLE = { display: 'none' } as const\n\n/** Injected face the card's slot registration supplies. */\nexport interface CommandCodeCardProps {\n t: Translate<SettingsCommandCodeKey>\n useCommandCodeSettings<T>(selector: (state: SettingsPageState) => T): T\n useCommandCodeLogin<T>(selector: (state: LoginPageState) => T): T\n edit(field: string, text: string): void\n save(): void\n discard(): void\n beginLogin(): void\n cancelLogin(): void\n}\n\n/** The card's two postures. */\ntype CardMode =\n | { kind: 'registration' }\n | { kind: 'live'; ready: boolean; controllerConfigured: boolean; writable: boolean; apiKeyWritable: boolean }\n\n/** Decide the card's posture from the injected face and the owner facts. */\nexport function cardMode(props: CommandCodeCardProps & ProviderCardOwnerProps): CardMode {\n if (props.useCommandCodeSettings === undefined) return { kind: 'registration' }\n const snapshot = props.useCommandCodeSettings((state) => state)\n return {\n kind: 'live',\n ready: snapshot.available,\n controllerConfigured: snapshot.apiKeyConfigured,\n writable: snapshot.writable,\n apiKeyWritable: snapshot.apiKeyWritable,\n }\n}\n\n/** Status badge for the credential state (green when configured). */\nfunction StatusBadge({ ok, okLabel, pendingLabel }: {\n ok: boolean\n okLabel: string\n pendingLabel: string\n}) {\n return <span className={ok ? 'cc-badge' : 'cc-badgeMuted'}>{ok ? okLabel : pendingLabel}</span>\n}\n\n/**\n * The per-reason copy for a failed login attempt (mirrors the settings\n * page's LoginPanel; the same reasons can surface from this card).\n */\nfunction loginFailureCopy(reason: CommandCodeLoginFailureReason | undefined, t: Translate<SettingsCommandCodeKey>): string {\n if (reason === 'denied') return t('loginDenied')\n if (reason === 'timeout') return t('loginTimeout')\n if (reason === 'invalid-key') return t('loginInvalidKey')\n if (reason === 'network') return t('loginNetwork')\n if (reason === 'unavailable') return t('loginStoreFailed')\n if (reason === 'cancelled') return t('loginCancelled')\n return t('loginFailedGeneric')\n}\n\n/** The sign-in affordance row for the not-configured card (see LoginPanel). */\nfunction CardLoginRow({ state, disabled, t, onBegin, onCancel }: {\n state: LoginPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onBegin(): void\n onCancel(): void\n}) {\n const busy = state.phase === 'starting' || state.phase === 'waiting'\n let hint = t('loginHintIdle')\n let hintClass = 'cc-hint'\n if (state.phase === 'starting' || state.phase === 'waiting') hint = t(state.phase === 'starting' ? 'loginStarting' : 'loginWaiting')\n else if (state.phase === 'success') {\n const keyName = state.keyName !== undefined && state.keyName !== '' ? ` · ${state.keyName}` : ''\n hint = `${t('loginSuccess')} ${state.userName ?? ''}${keyName}`.trim()\n hintClass = 'cc-loginDone'\n } else if (state.phase === 'failed') {\n hint = loginFailureCopy(state.reason, t)\n hintClass = 'cc-loginError'\n } else if (state.phase === 'unavailable') {\n hint = `${t('loginUnavailable')} ${state.message ?? ''}`.trim()\n hintClass = 'cc-loginError'\n }\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <span className=\"cc-label\">{t('loginTitle')}</span>\n <span className=\"cc-badges\">\n {busy ? (\n <button type=\"button\" className=\"cc-reset\" onClick={onCancel}>{t('loginCancel')}</button>\n ) : (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={onBegin}>{t('loginButton')}</button>\n )}\n </span>\n </div>\n {state.authUrl !== undefined ? (\n <p className=\"cc-hint\">\n <a className=\"cc-loginLink\" href={state.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n </p>\n ) : null}\n <p className={hintClass}>{hint}</p>\n </div>\n )\n}\n\n/** Compact key field for the not-configured card. */\nfunction CardKeyField({ state, disabled, t, onEdit }: {\n state: StagedField\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onEdit(text: string): void\n}) {\n const [visible, setVisible] = useState(false)\n return (\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <label className=\"cc-label\" htmlFor=\"cc-card-api-key\">{t('apiKey')}</label>\n <span className=\"cc-badges\">\n <button type=\"button\" className=\"cc-reset\" disabled={disabled} onClick={() => setVisible((value) => !value)}>\n {visible ? t('hide') : t('show')}\n </button>\n </span>\n </div>\n <input\n id=\"cc-card-api-key\"\n className=\"cc-input\"\n type={visible ? 'text' : 'password'}\n autoComplete=\"off\"\n spellCheck={false}\n value={state.text}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n <p className=\"cc-hint\">{t('apiKeyHint')}</p>\n </div>\n )\n}\n\n/**\n * The slot component body. Dispatched on every Command Code provider card of\n * the Models page (saved row, first-run setup posture, and add-provider\n * draft).\n *\n * Closed (the official 编辑 toggle off) the panel renders nothing: the row\n * head the Models page owns already names the provider and shows the\n * credential dot, so a page full of providers stays compact. Opening the\n * official editor mounts the editor shell as the outlet's sibling; the panel\n * watches for it, hides the shell (it carries only the settings.yaml hint and\n * a disabled apply for this namespace), and shows the real controls — badges,\n * API-key field, sign-in, discard/save.\n */\nexport function CommandCodeProviderCard(props: CommandCodeCardProps & ProviderCardOwnerProps) {\n const { t } = props\n const mode = cardMode(props)\n const state = props.useCommandCodeSettings !== undefined\n ? props.useCommandCodeSettings((snapshot) => snapshot)\n : undefined\n const login = props.useCommandCodeLogin !== undefined\n ? props.useCommandCodeLogin((snapshot) => snapshot)\n : undefined\n const dirty = state?.dirty ?? false\n const saving = state?.saving ?? false\n const invalid = state?.invalid ?? false\n const failed = state?.failed ?? false\n const savingBlocked = !dirty || invalid\n const configured = mode.kind === 'live' && mode.ready ? mode.controllerConfigured : props.keyConfigured\n const disabled = mode.kind === 'live' && (!mode.writable || (state !== undefined && !mode.apiKeyWritable))\n const showBody = mode.kind === 'live' && mode.ready && state !== undefined\n // The official editor's open state lives in the Models page's own component\n // state and never reaches this slot's props; the outlet wrapper is the\n // stable neighbor, so watch its siblings for the editor's mount/unmount.\n // The outlet stays mounted either way — it is the observation anchor — so\n // the closed panel hides its own root instead of unmounting.\n const rootRef = useRef<HTMLDivElement | null>(null)\n const [editorOpen, setEditorOpen] = useState(false)\n useEffect(() => {\n const root = rootRef.current\n if (root === null || typeof MutationObserver === 'undefined') return\n const wrapper = root.closest(`[data-slot=\"${CARD_SLOT_KEY}\"]`) ?? root.parentElement\n if (wrapper === null) return\n const row = wrapper.parentElement\n if (row === null) return\n let hiddenEditor: HTMLElement | null = null\n const sync = () => {\n const editor = adjacentEditorCard(wrapper) as HTMLElement | null\n setEditorOpen(editor !== null)\n if (editor !== null) {\n // React pins no inline style on the editor shell, so this survives\n // the shell's own re-renders; a shell that unmounts and remounts is\n // re-hidden by the next observation.\n editor.style.display = 'none'\n hiddenEditor = editor\n }\n }\n sync()\n const observer = new MutationObserver(sync)\n observer.observe(row, { childList: true })\n return () => {\n observer.disconnect()\n // If the shell outlives the panel (plugin reload), give it back: the\n // settings.yaml hint is the honest fallback face again.\n if (hiddenEditor !== null) hiddenEditor.style.display = ''\n }\n }, [])\n return (\n <div\n ref={rootRef}\n className=\"cc-providerCard\"\n data-cc-models-card=\"true\"\n style={editorOpen ? undefined : HIDDEN_STYLE}\n >\n {editorOpen && mode.kind === 'registration' ? <p className=\"cc-hint\">{t('cardRegistrationHint')}</p> : null}\n {editorOpen && mode.kind === 'live' && !mode.ready ? <p className=\"cc-hint\">{t('cardLoadingHint')}</p> : null}\n {editorOpen && showBody ? (\n <>\n <div className=\"cc-field\">\n <div className=\"cc-fieldHead\">\n <span className=\"cc-label\">{t('cardTitle')}</span>\n <span className=\"cc-badges\">\n <StatusBadge ok={configured} okLabel={t('apiKeySet')} pendingLabel={t('apiKeyUnset')} />\n {props.provider.active ? <span className=\"cc-badge\">{t('cardRouteActive')}</span> : null}\n </span>\n </div>\n </div>\n <CardKeyField\n state={state.apiKey}\n disabled={disabled}\n t={t}\n onEdit={(text) => props.edit('apiKey', text)}\n />\n {login !== undefined ? (\n <CardLoginRow\n state={login}\n disabled={disabled}\n t={t}\n onBegin={props.beginLogin}\n onCancel={props.cancelLogin}\n />\n ) : null}\n <div className=\"cc-footer\">\n {failed ? <p className=\"cc-failed\" role=\"status\">{t('saveFailed')}</p> : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={!dirty || saving}\n onClick={props.discard}\n >\n {t('discard')}\n </button>\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={savingBlocked || saving}\n onClick={props.save}\n >\n {t(saving ? 'saving' : 'save')}\n </button>\n </div>\n </>\n ) : null}\n </div>\n )\n}\n","/**\n * Locale copy for the \"Command Code\" settings page, and the declaration that\n * merges the page's namespace into the framework's `LocaleNamespaceMap` so\n * `ctx.locale.register` / `ctx.slots.register(..., { locale })` are typed.\n *\n * zh is the source of truth for the key set (repo convention); en must carry\n * the exact same keys — a mismatch is a compile error at the register site.\n */\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Copy of the Command Code settings page. */\n 'settings.commandcode': SettingsCommandCodeKey\n }\n}\n\n/** Dictionary keys of the Command Code settings page. */\nexport type SettingsCommandCodeKey =\n | 'nav'\n | 'title'\n | 'intro'\n | 'apiKey'\n | 'apiKeyHint'\n | 'apiKeySet'\n | 'apiKeyUnset'\n | 'apiKeyLocked'\n | 'apiBase'\n | 'apiBaseHint'\n | 'workingDir'\n | 'workingDirHint'\n | 'requestTimeoutMs'\n | 'requestTimeoutMsHint'\n | 'streamIdleTimeoutMs'\n | 'streamIdleTimeoutMsHint'\n | 'advancedSettings'\n | 'advancedSettingsHint'\n | 'advancedOverriddenOne'\n | 'advancedOverriddenMany'\n | 'advancedInvalid'\n | 'filterModelsByPlan'\n | 'filterModelsByPlanHint'\n | 'accountsTitle'\n | 'accountsHint'\n | 'accountAdd'\n | 'accountRemove'\n | 'accountLabel'\n | 'accountKey'\n | 'accountKeyHint'\n | 'accountDefault'\n | 'activeAccount'\n | 'activeAccountAuto'\n | 'activeAccountHint'\n | 'rulesTitle'\n | 'rulesHint'\n | 'rulesEmpty'\n | 'rulesCatalogFailed'\n | 'ruleAdd'\n | 'ruleRemove'\n | 'ruleModel'\n | 'ruleModelPick'\n | 'ruleModelCount'\n | 'ruleAccount'\n | 'ruleHint'\n | 'overridden'\n | 'reset'\n | 'invalidNumber'\n | 'numberTooSmall'\n | 'numberTooLarge'\n | 'readOnly'\n | 'unsaved'\n | 'save'\n | 'saving'\n | 'saved'\n | 'saveFailed'\n | 'discard'\n | 'cancel'\n | 'show'\n | 'hide'\n | 'usageTitle'\n | 'usageRefresh'\n | 'usageRefreshing'\n | 'usageLoading'\n | 'usageNoKey'\n | 'usageError'\n | 'usageRequests'\n | 'usageFailed'\n | 'usageSuccessRate'\n | 'usageCost'\n | 'usageTokens'\n | 'usageTokensIn'\n | 'usageTokensOut'\n | 'usageMonthly'\n | 'usagePurchased'\n | 'usageFree'\n | 'usageFiveHour'\n | 'usageWeekly'\n | 'usageExceeded'\n | 'usageReset'\n | 'usagePartial'\n | 'usageKeyClear'\n | 'usageKeyClearStaged'\n | 'usageUndoKeyClear'\n | 'usageKeyInvalid'\n | 'usageKeyInvalidHint'\n | 'usageServiceUnavailable'\n | 'usageServiceUnavailableHint'\n | 'usageNetworkError'\n | 'usageNetworkHint'\n | 'usageUpdated'\n | 'usagePeriodEnd'\n | 'usageActive'\n | 'usageCooldown'\n | 'usageInvalidKey'\n | 'usageUnconfigured'\n | 'updateAvailable'\n | 'updateHint'\n | 'loginTitle'\n | 'loginHintIdle'\n | 'loginButton'\n | 'loginStarting'\n | 'loginWaiting'\n | 'loginOpenLink'\n | 'loginCancel'\n | 'loginSuccess'\n | 'loginUnavailable'\n | 'loginDenied'\n | 'loginTimeout'\n | 'loginInvalidKey'\n | 'loginNetwork'\n | 'loginStoreFailed'\n | 'loginCancelled'\n | 'loginFailedGeneric'\n | 'cardTitle'\n | 'cardRouteActive'\n | 'cardLoadingHint'\n | 'cardRegistrationHint'\n\nexport const zh: Record<SettingsCommandCodeKey, string> = {\n nav: 'Command Code',\n title: 'Command Code',\n intro:\n '配置 Command Code Provider 连接。API 密钥仅保存在本机凭据服务中,不会回显;'\n + '其他字段写入用户设置,下次请求即生效。',\n apiKey: 'API 密钥',\n apiKeyHint: '在 commandcode.ai 控制台创建。留空保存不会覆盖已存储的密钥。',\n apiKeySet: '已配置',\n apiKeyUnset: '未配置',\n apiKeyLocked: '密钥由只读来源提供',\n apiBase: 'API 地址',\n apiBaseHint: '默认 https://api.commandcode.ai,一般无需修改。',\n workingDir: '工作目录',\n workingDirHint: '可选。留空时使用占位符显示的进程工作目录;仅在需要固定路径时填写。',\n requestTimeoutMs: '请求超时(毫秒)',\n requestTimeoutMsHint: '等待响应首个字节的超时;默认 60000。',\n streamIdleTimeoutMs: '流空闲超时(毫秒)',\n streamIdleTimeoutMsHint: '生成流停滞多久视为断连;默认 300000(长思考模型可静默数分钟,默认值刻意放宽)。',\n advancedSettings: '高级设置',\n advancedSettingsHint: 'API 地址、工作目录、超时与模型过滤等不常修改的选项。',\n advancedOverriddenOne: '已自定义 1 项',\n advancedOverriddenMany: '已自定义 {count} 项',\n advancedInvalid: '高级设置中有未填好的数字,请展开修正后再保存。',\n filterModelsByPlan: '隐藏套餐外模型',\n filterModelsByPlanHint: '开启后,模型选择器只列出当前套餐可用的模型;账户持有按需余额时会显示全部。',\n accountsTitle: '多账户轮换',\n accountsHint: '当前账户达到用量限额(429)或密钥失效(401)时,请求自动切换到下一个账户;全部耗尽时会提示最早的重置时间。',\n accountAdd: '添加账户',\n accountRemove: '移除',\n accountLabel: '账户备注名',\n accountKey: 'API 密钥',\n accountKeyHint: '该账户的 API 密钥。留空保存不会覆盖已存储的密钥。',\n accountDefault: '默认账户',\n activeAccount: '当前使用账户',\n activeAccountAuto: '自动(第一个可用账户)',\n activeAccountHint: '手动指定优先使用的账户,保存后下次请求即生效;所选账户耗尽时仍会自动切换到其他可用账户。',\n rulesTitle: '按模型切换账户',\n rulesHint: '选择模型并路由到某个账户(可多选)。命中规则的模型且该账户可用时优先使用;账户耗尽或密钥失效时仍自动回落到其他账户。规则按列表顺序匹配,第一条命中生效。',\n rulesEmpty: '尚未配置规则。',\n rulesCatalogFailed: '模型目录获取失败,暂时无法选择模型;已保存的规则仍会生效。',\n ruleAdd: '添加规则',\n ruleRemove: '移除',\n ruleModel: '模型',\n ruleModelPick: '选择模型…',\n ruleModelCount: '已选 {count} 个模型',\n ruleAccount: '目标账户',\n ruleHint: '从下拉列表勾选要路由的模型(可多选),再选择目标账户。',\n overridden: '已覆盖',\n reset: '重置',\n invalidNumber: '无效数字',\n numberTooSmall: '不能小于 1(毫秒)',\n numberTooLarge: '超出允许上限(2147483647 毫秒)',\n readOnly: '当前配置为只读。',\n unsaved: '未保存',\n save: '保存',\n saving: '保存中',\n saved: '已保存 ✓',\n saveFailed: '保存失败,请重试。',\n discard: '放弃',\n cancel: '取消',\n show: '显示',\n hide: '隐藏',\n usageTitle: '账户用量',\n usageRefresh: '刷新',\n usageRefreshing: '刷新中…',\n usageLoading: '正在获取账户用量…',\n usageNoKey: '配置 API 密钥后,这里会显示账户的用量与额度状态。',\n usageError: '用量获取失败',\n usageRequests: '请求',\n usageFailed: '失败',\n usageSuccessRate: '成功率',\n usageCost: '花费',\n usageTokens: 'Token',\n usageTokensIn: '入',\n usageTokensOut: '出',\n usageMonthly: '月额度',\n usagePurchased: '已购',\n usageFree: '赠送',\n usageFiveHour: '5 小时窗口',\n usageWeekly: '每周窗口',\n usageExceeded: '已超限',\n usageReset: '重置于',\n usagePartial: '部分端点数据不可用',\n usageKeyClear: '清除已存密钥',\n usageKeyClearStaged: '将清除(保存后生效)',\n usageUndoKeyClear: '撤销清除',\n usageKeyInvalid: 'API 密钥无效或已过期',\n usageKeyInvalidHint: '服务端拒绝了全部请求(401)。请检查该账户配置的密钥,或到 commandcode.ai 控制台重新生成。',\n usageServiceUnavailable: 'Command Code 服务暂时不可用',\n usageServiceUnavailableHint: '服务端返回了错误(5xx),稍后点击刷新重试。',\n usageNetworkError: '无法连接 Command Code 服务',\n usageNetworkHint: '所有请求都没有到达服务端。请检查网络连接或 API 地址设置。',\n usageUpdated: '更新于',\n usagePeriodEnd: '账期截止',\n usageActive: '当前使用',\n usageCooldown: '限额冷却中',\n usageInvalidKey: '密钥无效',\n usageUnconfigured: '该账户尚未配置 API 密钥。',\n updateAvailable: '可更新',\n updateHint: '已发布新版本,点击查看发布说明;更新插件后刷新本页,提示会自动消失。',\n loginTitle: '通过官方登录获取密钥',\n loginHintIdle: '不想手动创建密钥?点击登录后浏览器会打开 commandcode.ai 授权页,完成后密钥自动写入本机凭据服务,下次请求即生效。',\n loginButton: '登录 Command Code',\n loginStarting: '正在启动本地回调服务…',\n loginWaiting: '等待在浏览器中完成授权…',\n loginOpenLink: '打开授权页面 ↗',\n loginCancel: '取消登录',\n loginSuccess: '已登录为',\n loginUnavailable: '此环境暂不支持登录流程,请手动粘贴密钥。',\n loginDenied: '授权被拒绝。可重试,或手动粘贴密钥。',\n loginTimeout: '等待超时:未在窗口期内收到授权回调,请重试。',\n loginInvalidKey: '获取到的密钥未通过校验(401),请重试或手动粘贴。',\n loginNetwork: '无法连接 Command Code 服务校验密钥,请检查网络后重试。',\n loginStoreFailed: '密钥无法写入本机凭据服务,请手动粘贴。',\n loginCancelled: '登录已取消。',\n loginFailedGeneric: '登录失败,请重试或手动粘贴密钥。',\n cardTitle: 'Command Code',\n cardRouteActive: '已启用',\n cardLoadingHint: '正在读取 Command Code 配置…',\n cardRegistrationHint: '此卡片随 Command Code 插件注册,需要较新版本的 DeepSeek Harness 才会显示完整内容。',\n}\n\nexport const en: Record<SettingsCommandCodeKey, string> = {\n nav: 'Command Code',\n title: 'Command Code',\n intro:\n 'Configure the Command Code Provider connection. The API key is stored only'\n + ' in the local credential service and never echoed; other fields are written'\n + ' to user settings and take effect on the next request.',\n apiKey: 'API key',\n apiKeyHint: 'Create one in the commandcode.ai console. Saving with this field'\n + ' blank keeps the stored key.',\n apiKeySet: 'Configured',\n apiKeyUnset: 'Not configured',\n apiKeyLocked: 'Key provided by a read-only source',\n apiBase: 'API base URL',\n apiBaseHint: 'Defaults to https://api.commandcode.ai; usually leave as-is.',\n workingDir: 'Working directory',\n workingDirHint: 'Optional. Leave blank to use the process cwd shown as the'\n + ' placeholder; fill in only to pin a specific path.',\n requestTimeoutMs: 'Request timeout (ms)',\n requestTimeoutMsHint: 'Time to wait for the first response byte; default 60000.',\n streamIdleTimeoutMs: 'Stream idle timeout (ms)',\n streamIdleTimeoutMsHint: 'How long a stalled stream is treated as dead; default 300000'\n + ' (deliberately generous — long-thinking models can stay silent for minutes).',\n advancedSettings: 'Advanced',\n advancedSettingsHint: 'Rarely touched options: API base URL, working directory, timeouts, and model filtering.',\n advancedOverriddenOne: '1 customized',\n advancedOverriddenMany: '{count} customized',\n advancedInvalid: 'A number in Advanced settings is not ready to save; expand to fix it.',\n filterModelsByPlan: 'Hide out-of-plan models',\n filterModelsByPlanHint: 'When on, the model picker lists only models your subscription'\n + ' includes; any on-demand credit balance shows the full catalog.',\n accountsTitle: 'Account rotation',\n accountsHint: 'When the active account hits its usage limit (429) or its key'\n + ' fails (401), requests switch to the next account; when every account is'\n + ' exhausted the error names the earliest window reset.',\n accountAdd: 'Add account',\n accountRemove: 'Remove',\n accountLabel: 'Account label',\n accountKey: 'API key',\n accountKeyHint: 'This account’s API key. Saving with the field blank keeps the stored key.',\n accountDefault: 'Default account',\n activeAccount: 'Active account',\n activeAccountAuto: 'Auto (first usable account)',\n activeAccountHint: 'Pin the preferred account; applies to the next request after saving.'\n + ' If the selected account is exhausted, requests still rotate to another usable account.',\n rulesTitle: 'Route models to accounts',\n rulesHint: 'Pick models (multi-select) and route them to an account. When the'\n + ' request’s model is in a rule and that account is usable, it serves;'\n + ' an exhausted or invalid routed account falls back to the normal rotation.'\n + ' Rules match in list order — the first hit wins.',\n rulesEmpty: 'No rules yet.',\n rulesCatalogFailed: 'Could not load the model catalog — selecting models is unavailable; saved rules still apply.',\n ruleAdd: 'Add rule',\n ruleRemove: 'Remove',\n ruleModel: 'Models',\n ruleModelPick: 'Select models…',\n ruleModelCount: '{count} model(s) selected',\n ruleAccount: 'Target account',\n ruleHint: 'Check the models to route from the dropdown (multi-select), then pick the target account.',\n overridden: 'Overridden',\n reset: 'Reset',\n invalidNumber: 'Invalid number',\n numberTooSmall: 'Must be at least 1 (ms)',\n numberTooLarge: 'Above the allowed maximum (2147483647 ms)',\n readOnly: 'Settings are read-only.',\n unsaved: 'Unsaved',\n save: 'Save',\n saving: 'Saving',\n saved: 'Saved ✓',\n saveFailed: 'Save failed, please retry.',\n discard: 'Discard',\n cancel: 'Cancel',\n show: 'Show',\n hide: 'Hide',\n usageTitle: 'Account usage',\n usageRefresh: 'Refresh',\n usageRefreshing: 'Refreshing…',\n usageLoading: 'Fetching account usage…',\n usageNoKey: 'Configure an API key to see this account’s usage and credit state here.',\n usageError: 'Could not fetch usage',\n usageRequests: 'Requests',\n usageFailed: 'failed',\n usageSuccessRate: 'Success rate',\n usageCost: 'Spend',\n usageTokens: 'Tokens',\n usageTokensIn: 'in',\n usageTokensOut: 'out',\n usageMonthly: 'Monthly',\n usagePurchased: 'Purchased',\n usageFree: 'Free',\n usageFiveHour: '5-hour window',\n usageWeekly: 'Weekly window',\n usageExceeded: 'Exceeded',\n usageReset: 'Resets',\n usagePartial: 'Some endpoint data unavailable',\n usageKeyClear: 'Clear stored key',\n usageKeyClearStaged: 'Will be cleared on save',\n usageUndoKeyClear: 'Undo clear',\n usageKeyInvalid: 'API key invalid or expired',\n usageKeyInvalidHint: 'The server rejects every request (401). Check the key configured for this account, or generate a new one in the commandcode.ai console.',\n usageServiceUnavailable: 'The Command Code service is temporarily unavailable',\n usageServiceUnavailableHint: 'The server returned errors (5xx); try Refresh again later.',\n usageNetworkError: 'Could not reach the Command Code service',\n usageNetworkHint: 'No request reached the server. Check your network connection or the API base setting.',\n usageUpdated: 'Updated',\n usagePeriodEnd: 'Period ends',\n usageActive: 'Active',\n usageCooldown: 'Cooling down',\n usageInvalidKey: 'Invalid key',\n usageUnconfigured: 'No API key configured for this account yet.',\n updateAvailable: 'update available',\n updateHint: 'A newer version has been published; click for release notes. The notice disappears once the plugin is updated.',\n loginTitle: 'Sign in to fetch a key',\n loginHintIdle: 'Rather not create a key by hand? Sign in and your browser opens the commandcode.ai authorization page; the approved key is stored in the local credential service and applies to the next request.',\n loginButton: 'Sign in to Command Code',\n loginStarting: 'Starting the local callback server…',\n loginWaiting: 'Waiting for authorization in your browser…',\n loginOpenLink: 'Open the authorization page ↗',\n loginCancel: 'Cancel sign-in',\n loginSuccess: 'Signed in as',\n loginUnavailable: 'Sign-in is unavailable in this environment; paste the API key instead.',\n loginDenied: 'Authorization was denied. Try again or paste the key manually.',\n loginTimeout: 'Timed out waiting for the authorization callback; try again.',\n loginInvalidKey: 'The delivered key failed validation (401). Try again or paste it manually.',\n loginNetwork: 'Could not reach the Command Code service to validate the key; check your network and retry.',\n loginStoreFailed: 'The key could not be stored in the local credential service; paste it manually.',\n loginCancelled: 'Sign-in cancelled.',\n loginFailedGeneric: 'Sign-in failed; try again or paste the key manually.',\n cardTitle: 'Command Code',\n cardRouteActive: 'Active',\n cardLoadingHint: 'Loading the Command Code configuration…',\n cardRegistrationHint: 'This card is contributed by the Command Code plugin; a newer DeepSeek Harness is needed to show the full controls.',\n}\n","/**\n * Browser half of the dsh-commandcode-provider bundle.\n *\n * Two responsibilities:\n *\n * 1. A \"Command Code\" settings page (a `settings.section` entry at the same\n * nav level as General / Models / Plugins). The Models page renders an\n * unknown-adapter-family card for the `commandcode` provider and disables\n * its submit, so the API key cannot be configured there; this page is the\n * dedicated surface. It writes the API key through the credentials domain\n * (the `COMMANDCODE_API_KEY` reference the plugin resolves via\n * `ctx.remote.credentials`) and the connection facts through the\n * `llm-commandcode` settings namespace, so a saved key or endpoint reaches\n * the very next request.\n *\n * 2. The Models-page provider card (settings.models.provider-card) and the\n * friendly image-gate error wrapper — see `./card.tsx` / `./sessions.ts`.\n * The wrapper is deliberately narrow: only the `model-unavailable` code is\n * rewritten, only when the message matches the image-session gate, and only\n * the message text changes.\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { createSnapshotStore } from './snapshot-store.ts'\n// Type-only imports that pull in the client-service augmentations\n// (`slots`/`remote`/`locale` on Context) and the `settings.section` SlotMap\n// entry (`settingsScope` arrives through dsh-client-ui-settings).\nimport type {} from '@deepseek-ai/dsh-api-remotes/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { installFriendlyImageError } from './sessions.ts'\nimport type { ConnectionLike } from './sessions.ts'\nimport { CommandCodeSettingsController, COMMANDCODE_NS, type SettingsPageState } from './settings.ts'\nimport type { HostDescriptionSource, SettingsPageApi } from './settings.ts'\nimport { adaptLegacyCredentials, type LegacyCredentialsApi } from './legacy-credentials.ts'\nimport { CommandCodeUsageController, type UsagePageState, type UsageRemote } from './usage.ts'\nimport { CommandCodeLoginController, type LoginPageState, type LoginRemote } from './login.ts'\nimport { USAGE_REMOTE_CONTRIBUTION, MODELS_REMOTE_CONTRIBUTION } from '../usage-wire.ts'\nimport { LOGIN_REMOTE_CONTRIBUTION } from '../login-wire.ts'\nimport type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { CommandCodeSettingsPage } from './section.tsx'\nimport { CommandCodeProviderCard } from './card.tsx'\nimport { zh, en } from './locales.ts'\n\nexport { isImageSessionRejection, withFriendlyImageError } from './sessions.ts'\n\n/** CSS for the settings page, injected once (harness bundle convention). */\nconst PAGE_CSS = `\n.cc-section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}\n.cc-title{margin:0;font-size:18px;font-weight:600}\n.cc-intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px;line-height:1.5}\n.cc-readOnly{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.cc-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px}\n.cc-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}\n.cc-field+.cc-field{border-top:1px solid var(--dsw-alias-border-l2)}\n.cc-fieldHead{align-items:center;gap:8px;display:flex}\n.cc-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}\n.cc-badges{align-items:center;gap:8px;display:inline-flex}\n.cc-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}\n.cc-badgeMuted{white-space:nowrap;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-size:11px;line-height:17px}\n.cc-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}\n.cc-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.cc-reset:disabled{cursor:default;opacity:.5}\n.cc-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}\n.cc-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}\n.cc-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}\n/* The routing-rule model multi-select: a button trigger that opens an\n * anchored Menu of checkbox rows. The trigger mirrors .cc-input sizing so it\n * sits flush with the sibling account select. */\n.cc-ruleTrigger{align-items:center;gap:8px;display:flex;width:100%;text-align:left;cursor:pointer}\n.cc-ruleTrigger:disabled{cursor:default}\n.cc-ruleTriggerText{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.cc-ruleCaret{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:6px;height:6px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg)}\n.cc-checkRow{align-items:center;gap:8px;display:inline-flex;min-width:0}\n.cc-checkRow:hover{cursor:pointer}\n.cc-check{appearance:none;flex-shrink:0;width:15px;height:15px;margin:0;border:1px solid var(--dsw-alias-border-l2);border-radius:4px;background:var(--dsw-alias-bg-layer-1);position:relative}\n.cc-check:checked{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}\n.cc-check:checked::after{content:'';position:absolute;top:2px;left:5px;width:3px;height:7px;border:solid #fff;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}\n.cc-checkName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n/* Selects need their own treatment to sit flush with the text inputs:\n * the UA stylesheet renders <select> border-box (34px total vs the inputs'\n * 36px) and forces its own menulist text metrics, so drop the native\n * chrome entirely (appearance:none), restore content-box so the outer box\n * matches the inputs again, and draw the chevron ourselves. Longhand\n * background-* only — the shorthand would reset .cc-input's background. */\nselect.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box-sizing:content-box;padding-right:32px;background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23888f98' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 11px center}\n.cc-inputInvalid{border-color:var(--dsw-alias-label-error)}\n.cc-invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}\n/* The Advanced card: its header row is one full-width toggle button; the\n * chevron is two borders on a rotated square (no icon dependency). */\n.cc-advancedHead{align-items:center;gap:8px;display:flex;width:100%;padding:12px 0;background:0 0;border:none;cursor:pointer;font:inherit;text-align:left}\n.cc-advancedHead:hover .cc-advancedTitle{color:var(--dsw-alias-label-primary)}\n.cc-advancedTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}\n.cc-advancedSpacer{flex:1}\n.cc-chevron{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:8px;height:8px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg);transition:transform .15s ease}\n.cc-chevronUp{transform:rotate(-135deg);margin-bottom:-3px}\n.cc-advancedBody{flex-direction:column;display:flex}\n.cc-advancedBody>.cc-field:first-of-type{border-top:1px solid var(--dsw-alias-border-l2)}\n.cc-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.cc-footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}\n.cc-toggleRow{align-items:center;gap:8px;cursor:pointer;display:flex}\n.cc-toggleRow:has(.cc-toggle:disabled){cursor:default}\n.cc-toggle{appearance:none;flex-shrink:0;background:var(--dsw-alias-border-l2);border-radius:999px;width:30px;height:18px;margin:0;cursor:pointer;position:relative;transition:background .15s ease}\n.cc-toggle:checked{background:var(--dsw-alias-brand-primary)}\n.cc-toggle::after{content:'';background:#fff;border-radius:50%;width:14px;height:14px;position:absolute;top:2px;left:2px;transition:left .15s ease}\n.cc-toggle:checked::after{left:14px}\n.cc-toggle:disabled{cursor:default;opacity:.5}\n.cc-failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}\n.cc-usageCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:14px 16px;flex-direction:column;gap:12px;display:flex}\n.cc-usageHead{align-items:center;gap:8px;display:flex}\n.cc-usageTitle{color:var(--dsw-alias-label-primary);flex:1;margin:0;font-size:13px;font-weight:600;line-height:1.5}\n.cc-usageAccount{max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}\n.cc-usagePlan{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:600;line-height:17px}\n.cc-usagePlanStatus{white-space:nowrap;color:var(--dsw-alias-label-error);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}\n.cc-usageRefresh{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}\n.cc-usageRefresh:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.cc-usageRefresh:disabled{cursor:default;opacity:.5}\n.cc-usageHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.cc-usageError{align-items:center;gap:8px;color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5;display:flex}\n.cc-usageStats{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;display:grid}\n.cc-usageStat{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:8px;padding:8px 10px;flex-direction:column;gap:2px;display:flex}\n.cc-usageStatLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}\n.cc-usageStatValue{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}\n.cc-usageStatSub{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}\n.cc-usageWindows{flex-direction:column;gap:16px;display:flex}\n.cc-usageWindow{flex-direction:column;gap:6px;display:flex}\n.cc-usageWindowHead{align-items:baseline;gap:8px;display:flex}\n.cc-usageWindowLabel{color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;font-weight:500;line-height:1.5}\n.cc-usageWindowValue{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500;line-height:1.5}\n.cc-usageExceeded{color:var(--dsw-alias-label-error);font-size:11px;font-weight:500;line-height:1.5}\n.cc-usageBar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:6px}\n.cc-usageBarFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}\n.cc-usageBarFillWarn{background:var(--dsw-alias-label-error)}\n.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}\n.cc-usageMeta{align-items:center;gap:8px;display:flex}\n.cc-accountReport{flex-direction:column;gap:12px;display:flex}\n.cc-tabs{flex-wrap:wrap;gap:6px;display:flex}\n.cc-tab{align-items:center;font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:2px 10px;font-size:12px;line-height:18px;display:inline-flex;gap:6px}\n.cc-tab:hover:not(.cc-tabActive){color:var(--dsw-alias-label-primary)}\n.cc-tabActive{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}\n.cc-tabDotOk{background:var(--dsw-alias-brand-primary);border-radius:50%;width:6px;height:6px}\n.cc-tabDotWarn{background:#d97706;border-radius:50%;width:6px;height:6px}\n.cc-tabDotError{background:var(--dsw-alias-label-error);border-radius:50%;width:6px;height:6px}\n.cc-usageMetaSpacer{flex:1}\n.cc-usageUpdated{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}\n.cc-usagePartial{color:var(--dsw-alias-label-error);margin:0;font-size:11px;line-height:1.5}\n.cc-usageBlocked{border:1px solid var(--dsw-alias-label-error);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:4px}\n.cc-usageBlockedTitle{color:var(--dsw-alias-label-error);margin:0;font-size:13px;font-weight:600;line-height:1.5}\n.cc-usageBlockedHint{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:1.5}\n.cc-version{margin:4px 0 0;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n/* The update hint rides the footer version line: warning-tinted (with a\n * muted fallback for themes without the alias), quiet until hovered. */\n.cc-versionLink{color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary));text-decoration:none}\n.cc-versionLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-position:under}\n/* The login panel rides the connection card as one more field row; the\n * authorization link is the only branded element on it. */\n.cc-loginLink{color:var(--dsw-alias-brand-primary);text-decoration:none;font-size:12px;line-height:1.5}\n.cc-loginLink:hover{text-decoration:underline;text-underline-position:under}\n.cc-loginBusy{color:var(--dsw-alias-label-tertiary)}\n.cc-loginDone{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary))}\n.cc-loginError{color:var(--dsw-alias-label-error)}\n.cc-saved{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary));margin:0;font-size:12px;font-weight:500;line-height:1.5}\n.cc-badgeWarn{background:var(--dsw-alias-state-warning-secondary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary))}\n`\n\n/** Inject the page stylesheet once (idempotent per tag). */\nfunction injectPageCss(): void {\n if (typeof document === 'undefined') return\n const id = '@mars-sea/dsh-commandcode-provider/CommandCodeSettingsPage.module.css'\n if (document.querySelector(`style[data-plugin-css=\"${id}\"]`) !== null) return\n const tag = document.createElement('style')\n tag.dataset.plugin = '@mars-sea/dsh-commandcode-provider'\n tag.dataset.pluginCss = id\n tag.textContent = PAGE_CSS\n document.head.appendChild(tag)\n}\n\n/** Connection fields retained by pre-0.1.2 clients and absent from the current transport handle. */\ninterface LegacyConnectionLike extends ConnectionLike {\n api?: ConnectionLike['api'] & { credentials?: LegacyCredentialsApi }\n hostDescription?: HostDescriptionSource\n}\n\n/**\n * Client plugin body. Gates on the services shared by both client generations\n * (`slots`, `locale`, `connection`, `remote`, `settingsScope`). Current clients\n * mount the page after `remote.credentials` appears; legacy clients mount it\n * from the connection ApiProxy credential face.\n */\nexport function apply(ctx: Context): void {\n injectPageCss()\n\n const connection = ctx.get('connection') as LegacyConnectionLike | undefined\n if (connection !== undefined) {\n // The wrapper is reached from a non-React path that has no `t` in scope;\n // it reads the active client locale at call time, so a language switch\n // immediately applies to the next selectModel failure. On legacy builds\n // it wraps `connection.api.sessions`; 0.1.2 replaced that façade with\n // `remote.session`, so the helper safely skips this UX-only rewrite there\n // instead of preventing the whole plugin from activating.\n installFriendlyImageError(connection, () => ctx.locale.getLocale().active === 'zh' ? 'zh' : 'en')\n }\n\n // The \"Command Code\" settings page: register the section once the\n // `settings.section` declaration is on the ledger (ui-settings-general\n // owns the shell; registration order relative to it is not constrained —\n // `slots.inject` waits for the declaration).\n ctx.effect(() => ctx.locale.register('settings.commandcode', { zh, en }), 'dsh-commandcode-provider: page copy')\n\n const legacyApi = adaptLegacyCredentials(connection?.api?.credentials)\n if (legacyApi !== undefined) {\n applyClientSurfaces(ctx, legacyApi, connection?.hostDescription)\n return\n }\n\n // DSH 0.1.2 exposes credentials through a Typert Remote namespace. Keep it\n // optional at the root so a legacy client without `remote.credentials` can\n // still activate through the ApiProxy branch above.\n ctx.inject(['remote.credentials'], (remoteCtx) => {\n const credentials = (remoteCtx.remote as unknown as {\n credentials: SettingsPageApi['credentials']\n }).credentials\n applyClientSurfaces(remoteCtx, { credentials })\n })\n}\n\n/** Mount the one shared UI implementation over either credential transport. */\nfunction applyClientSurfaces(\n ctx: Context,\n api: SettingsPageApi,\n hostDescription?: HostDescriptionSource,\n): void {\n const scope = ctx.settingsScope.bind<Record<string, unknown>>({ namespace: COMMANDCODE_NS })\n // The model catalog for the routing-rule editor is served by the\n // `commandcode/models` Remote below; the controller reads it through this\n // mutable seam so the Remote mount (which happens after the controller is\n // constructed) still reaches the catalog fetch. Unset until the mount\n // lands — the controller degrades to the empty-catalog state meanwhile.\n let modelsRemote: NonNullable<SettingsPageApi['models']> | undefined\n const controller = new CommandCodeSettingsController(\n scope,\n { ...api, models: () => modelsRemote?.() ?? Promise.resolve({ ok: false, error: { message: 'commandcode/models remote is not mounted' } }) },\n hostDescription,\n )\n ctx.effect(() => () => controller.dispose(), 'dsh-commandcode-provider: settings controller')\n const store = createSnapshotStore<SettingsPageState>(controller.state())\n controller.subscribe(() => store.set(controller.state()))\n ctx.effect(\n () => (ctx.remote as unknown as {\n $on(event: 'credentials/reference-updated', listener: (ref: string) => void): () => void\n }).$on('credentials/reference-updated', () => { controller.refreshCredentials() }),\n 'dsh-commandcode-provider: credential invalidations',\n )\n\n // The account-usage card + login panel: mount the shared Remote contribution\n // (one mount carries every endpoint this plugin serves — report and login —\n // so the Client's bookkeeping stays 1:1 with the Host's single registry\n // registration), then resolve the `remote.commandcode` namespace through a\n // scoped inject. Cordis only serves services a fiber declares in `inject`,\n // and the namespace service exists only after the mount — a static inject\n // would deadlock the plugin (the mounter would wait for its own mount), so\n // the inject is registered dynamically once the mount lands. A Host half\n // that predates the Remote fails the calls instead, and the surfaces render\n // their error branches.\n let usageNamespace: (typeof ctx.remote)['commandcode'] | undefined\n let usageMountError: string | undefined\n const contribution: TypertRemoteContribution = {\n package: USAGE_REMOTE_CONTRIBUTION.package,\n descriptors: [\n ...USAGE_REMOTE_CONTRIBUTION.descriptors,\n ...MODELS_REMOTE_CONTRIBUTION.descriptors,\n ...LOGIN_REMOTE_CONTRIBUTION.descriptors,\n ],\n }\n ctx.effect(() => {\n let cancelled = false\n let unmount: (() => Promise<void>) | undefined\n void ctx.remote.$mount(contribution).then((dispose: () => Promise<void>) => {\n if (cancelled) {\n void dispose()\n return\n }\n unmount = dispose\n ctx.inject(['remote.commandcode'], (namespaceCtx) => {\n usageNamespace = namespaceCtx.remote.commandcode\n // The catalog Remote is live now; (re)fetch it for the rule editor.\n controller.refreshCatalog()\n namespaceCtx.effect(() => () => {\n usageNamespace = undefined\n }, 'dsh-commandcode-provider: usage namespace')\n })\n }, (error: unknown) => {\n // A mount failure (e.g. a harness without the Remote mount) leaves the\n // namespace unset; keep the reason so the card can surface it.\n usageMountError = error instanceof Error ? error.message : String(error)\n })\n return () => {\n cancelled = true\n usageNamespace = undefined\n if (unmount !== undefined) void unmount()\n }\n }, 'dsh-commandcode-provider: usage remote')\n const usageRemote: UsageRemote = {\n report: async () => {\n const namespace = usageNamespace\n if (namespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode/report remote is not mounted' } }\n }\n return namespace.report()\n },\n models: async () => {\n const namespace = usageNamespace\n if (namespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode/models remote is not mounted' } }\n }\n return namespace.models()\n },\n }\n // Wire the catalog Remote into the settings controller's models seam so the\n // routing-rule editor can fetch the catalog once the mount lands.\n modelsRemote = () => usageRemote.models()\n const usageController = new CommandCodeUsageController(usageRemote)\n ctx.effect(() => () => usageController.dispose(), 'dsh-commandcode-provider: usage controller')\n const usageStore = createSnapshotStore<UsagePageState>(usageController.state())\n usageController.subscribe(() => usageStore.set(usageController.state()))\n\n // The login panel: same namespace, three endpoints; the key never crosses\n // to the browser — the Host validates and stores it through the credentials\n // seam, and a landed login re-reads the credential badges + usage card.\n const loginRemote: LoginRemote = {\n loginBegin: async () => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginBegin()\n },\n loginStatus: async () => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginStatus()\n },\n loginCancel: async () => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginCancel()\n },\n }\n const loginController = new CommandCodeLoginController(() => loginRemote)\n ctx.effect(() => () => loginController.dispose(), 'dsh-commandcode-provider: login controller')\n const loginStore = createSnapshotStore<LoginPageState>(loginController.state())\n let lastLoginPhase = loginController.state().phase\n loginController.subscribe(() => {\n const phase = loginController.state().phase\n // A landed login stored the key Host-side behind the page's back; the\n // badges must follow and the account card can finally fetch.\n if (phase === 'success' && lastLoginPhase !== 'success') {\n controller.refreshCredentials()\n void usageController.refresh()\n }\n lastLoginPhase = phase\n loginStore.set(loginController.state())\n })\n\n const injected = () => ({\n hooks: { commandCodeSettings: store, commandCodeUsage: usageStore, commandCodeLogin: loginStore },\n edit: (field: string, text: string) => controller.edit(field, text),\n resetField: (field: string) => controller.resetField(field),\n // A landed save can change the key or endpoint the usage endpoints read,\n // so the account card refetches; a failed save keeps the old data.\n save: () => void controller.save().then(() => {\n const settled = controller.state()\n if (!settled.failed && settled.anyAccountConfigured) void usageController.refresh()\n }),\n discard: () => controller.discard(),\n refreshUsage: () => void usageController.refresh(),\n beginLogin: () => void loginController.begin(),\n cancelLogin: () => void loginController.cancel(),\n addAccount: () => controller.addAccount(),\n removeAccount: (id: string) => controller.removeAccount(id),\n editAccountLabel: (id: string, text: string) => controller.editAccountLabel(id, text),\n editAccountKey: (id: string, text: string) => controller.editAccountKey(id, text),\n toggleKeyClear: (id: string) => controller.toggleKeyClear(id),\n addRule: () => controller.addRule(),\n removeRule: (id: string) => controller.removeRule(id),\n editRuleModels: (id: string, ids: string[]) => controller.editRuleModels(id, ids),\n editRuleAccount: (id: string, text: string) => controller.editRuleAccount(id, text),\n })\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'commandcode',\n order: 12,\n label: () => ctx.locale.bind('settings.commandcode')('nav'),\n locale: 'settings.commandcode',\n inject: injected,\n }, CommandCodeSettingsPage))\n\n // The Models-page provider panel (dsh 0.1.2-alpha.2): a keyed slot the\n // Models section dispatches with `entryKey = settingsNs` on every provider\n // card of an adapter family. Registering under `llm-commandcode` mounts the\n // panel beside the official editor on every Command Code row — including\n // the first-run setup posture, exactly where a user without a key lands.\n // While the official 编辑 toggle is open, the panel hides the official\n // editor shell (for this namespace it holds only the settings.yaml hint\n // over a disabled apply) and shows the real controls; see card.tsx.\n // The registration carries its own inject face (store hooks + actions)\n // because the declaring entry is ui-settings-models', not ours; the `t`\n // seat comes from the registration's own `locale` namespace.\n //\n // On dsh builds without this slot the declaration never exists and\n // `slots.inject` never fires its callback — the registration silently\n // does not happen, and nothing else about the plugin changes.\n ctx.slots.inject('settings.models.provider-card', () => ctx.slots.register({\n name: 'settings.models.provider-card',\n key: 'llm-commandcode',\n locale: 'settings.commandcode',\n inject: () => ({\n hooks: { commandCodeSettings: store, commandCodeLogin: loginStore },\n edit: (field: string, text: string) => controller.edit(field, text),\n save: () => void controller.save().then(() => {\n const settled = controller.state()\n if (!settled.failed && settled.anyAccountConfigured) void usageController.refresh()\n }),\n discard: () => controller.discard(),\n beginLogin: () => void loginController.begin(),\n cancelLogin: () => void loginController.cancel(),\n }),\n }, CommandCodeProviderCard))\n}\n\nexport const inject: readonly string[] = [\n 'slots',\n 'locale',\n 'connection',\n 'remote',\n 'settingsScope',\n]\n"],"mappings":"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"}
|