@mars-sea/dsh-commandcode-provider 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["record","numberField","booleanField","IDLE","record","stringField","reject","pkg.version","(pkg as { repository?: unknown }).repository","useState","useMemo","Menu","Button","useSyncExternalStore","useCallback","useRef","HIDDEN_STYLE","useState","useRef","money","count","useState","useId","useState","Button","useRef"],"sources":["../src/client/snapshot-store.ts","../src/client/error-text.ts","../src/client/settings-scope.ts","../src/timeout-limits.ts","../src/model-visibility.ts","../src/client/settings-write.ts","../src/client/settings.ts","../src/display-format.ts","../src/client/usage.ts","../src/client/prices.ts","../src/client/login-page.ts","../src/client/login.ts","../src/wire-shared.ts","../src/usage-wire.ts","../src/login-wire.ts","../src/enrollment-wire.ts","../src/client/enrollment.ts","../src/client/locales.ts","../src/plan-tiers.ts","../src/client/model-select.ts","../package.json","../src/client/version.ts","../src/client/update.ts","../src/client/section.tsx","../src/client/login-row.tsx","../src/client/card.tsx","../src/client/analytics-copy.ts","../src/client/panel-copy.ts","../src/client/panel.ts","../src/analytics-wire.ts","../src/client/analytics-view.tsx","../src/client/panel-view.tsx","../src/cost-facts.ts","../src/client/session-cost.ts","../src/client/session-cost-display.ts","../src/client/session-cost-view.tsx","../src/client/page-styles.ts","../src/client/panel-styles.ts","../src/client/analytics.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, and small enough to stay that way: the harness's\n * `@deepseek-ai/dsh-client-store` is a seeded platform module, but pulling it in\n * would add a fourth `require()` target (and a client-only peer) to the bundle\n * for the ~30 lines used here, and its `set()` carries engine semantics\n * (dev-mode deep freeze, forced replacement) these callers do not want.\n */\n\n/** 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 * Turn a caught value into readable text for the settings page's error UI.\n *\n * @module dsh-commandcode-provider/client/error-text\n */\n\n/**\n * `error instanceof Error ? error.message : String(error)` degrades to the\n * literal string `[object Object]` for a plain object with no `Error`\n * prototype — which is exactly what a Remote call across the webview/host\n * boundary can hand back: `dsh-typert-protocol` serializes a rejection for\n * the wire, and a structurally-cloned value loses its prototype chain even\n * when the host threw a real `Error` (issue #74). Reading a `message` string\n * off the plain object first recovers the original text in that case; only a\n * value with neither an `Error` prototype nor a usable `message` field falls\n * through to a JSON dump.\n */\nexport function readableErrorText(error: unknown): string {\n if (error instanceof Error) return error.message\n if (typeof error === 'string') return error\n if (error !== null && typeof error === 'object') {\n const message = (error as { message?: unknown }).message\n if (typeof message === 'string' && message !== '') return message\n try {\n return JSON.stringify(error)\n } catch {\n return Object.prototype.toString.call(error)\n }\n }\n return String(error)\n}\n","/**\n * Browser settings scope over the `remote.settings` Typert namespace.\n *\n * The harness's own `settingsScope` client wrapper was REMOVED by the 0.1.7\n * settings rewrite and has no replacement, so this module IS the client half:\n * it speaks the `describe()` / `mutate(namespace, ops, revision)` wire directly\n * and implements the `SettingsScope<T>` face the settings-page controller\n * consumes. `view.writable` is the Host's own authorization fact — the client\n * never infers write permission from localhost, URL shape or origin.\n *\n * **Capture the namespace from an inject-scoped context, never read it off\n * `ctx.remote`.** React-free so `tests/settings-scope.test.ts` can drive the\n * lifecycle over a fake remote.\n *\n * @module dsh-commandcode-provider/client/settings-scope\n */\n\nimport type { SettingsScope, SettingsScopeSnapshot } from './settings.ts'\nimport { createSnapshotStore, type SnapshotStore } from './snapshot-store.ts'\nimport { readableErrorText } from './error-text.ts'\n\n/** Result envelope of one current Typert Remote call. */\ntype Envelope<T> = { ok: true; value: T } | { ok: false; error?: { message?: string } | undefined }\n\n/** One path-addressed form edit — the `SettingsPathOp` wire shape. */\nexport interface SettingsPathOp {\n op: 'set' | 'unset'\n path: readonly string[]\n value?: unknown\n}\n\n/** 本地确认结果,不改宿主远端载体;恢复快照不能冒充本次写入成功。 */\nexport type SettingsMutationResult = 'accepted' | 'conflict' | 'failed' | 'cancelled'\n\n/** One entry's row inside a `settings.describe()` view — `SettingsNamespaceView`. */\ninterface SettingsNamespaceRow {\n ns?: unknown\n value?: unknown\n base?: unknown\n user?: unknown\n revision?: unknown\n}\n\n/** The `settings.describe()` view: the directory plus the Host's write posture. */\ninterface SettingsView {\n namespaces?: SettingsNamespaceRow[] | undefined\n writable?: boolean | undefined\n}\n\n/** The `remote.settings` namespace this scope calls. Structural: never imported. */\nexport interface SettingsRemoteNamespace {\n describe(): Promise<Envelope<SettingsView>>\n /** A write answers with the fresh ROW for its namespace, not the directory. */\n mutate(\n namespace: string,\n ops: readonly SettingsPathOp[],\n revision?: number,\n ): Promise<Envelope<SettingsNamespaceRow>>\n}\n\n/**\n * Reads the `remote.settings` namespace object, or `undefined` while it is not\n * mounted.\n *\n * This is a SEAM rather than a property on {@link SettingsScopeContext}\n * because the namespace has to be captured inside a context that declares it\n * (`ctx.inject(['remote.settings'], (settingsCtx) => …)`). Reading it off our\n * own `ctx.remote` throws `cannot get property \"remote.settings\" without\n * inject` inside this module's `try`/`catch` — silently, with no describe ever\n * sent and the scope stuck on its initial `writable: false` snapshot. Do not\n * \"simplify\" this seam away (AGENTS.md has the full incident).\n */\nexport type SettingsRemoteResolver = () => SettingsRemoteNamespace | undefined\n\n/**\n * The client `Context` slice this module consumes, typed structurally so the\n * browser bundle never imports a version-specific module value and node tests\n * can hand in a plain object. Only `remote` itself (a declared service) is read\n * here — never `remote.<namespace>`, which requires its own inject.\n */\nexport interface SettingsScopeContext {\n remote: {\n $on?: ((event: string, listener: () => void) => (() => void) | undefined) | undefined\n }\n /** Connection lifecycle; older clients and tests may omit it. */\n on?: ((event: string, listener: () => void) => unknown) | undefined\n}\n\n/** Mirror snapshot: one in-flight-or-idle describe read and its held view. */\ninterface MirrorState {\n status: 'idle' | 'loading' | 'ready'\n view: SettingsView | null\n error: string | null\n}\n\n/**\n * Backoff before re-reading a directory whose FIRST read failed, in millis.\n *\n * Only a failure with NOTHING held retries. With no view the scope keeps its\n * initial `{ status: 'loading', writable: false }` snapshot and the settings\n * page renders fully disabled, while the forwarded invalidation signals need a\n * live Host to fire and the namespace only re-mounts on a reload. A failure\n * with a held view retries nothing — the page already shows the last good\n * document (`tests/settings-scope.test.ts` pins both).\n */\nexport const SETTINGS_DESCRIBE_RETRY_MS: readonly number[] = [1000, 2000, 4000]\n\n/** Timer seam for the bounded describe retry; tests drive it without waiting. */\nexport interface SettingsRetryTimer {\n set(callback: () => void, ms: number): unknown\n clear(handle: unknown): void\n}\n\n/** The production timer: a browser/node timeout, no polling. */\nconst REAL_SETTINGS_TIMER: SettingsRetryTimer = {\n set(callback, ms) {\n const handle = setTimeout(callback, ms)\n ;(handle as { unref?: () => void }).unref?.()\n return handle\n },\n clear(handle) { clearTimeout(handle as ReturnType<typeof setTimeout>) },\n}\n\n/** Shallow equality over the snapshot fields, so an unchanged derive never churns subscribers. */\nfunction sameSnapshot(a: SettingsScopeSnapshot<never>, b: SettingsScopeSnapshot<never>): boolean {\n return a.status === b.status\n && Object.is(a.value, b.value)\n && Object.is(a.base, b.base)\n && Object.is(a.user, b.user)\n && Object.is(a.revision, b.revision)\n && a.writable === b.writable\n && a.mode === b.mode\n}\n\n/** Accept a decoded row value only when it is the object a settings section is. */\nfunction decodeRow(value: unknown): Record<string, unknown> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n return value as Record<string, unknown>\n}\n\n/**\n * One shared mirror of the Host `settings.describe()` view.\n *\n * The run loop is the harness's own: serialize behind `inFlight`, fold a\n * concurrent invalidation into exactly one rerun, and hold the previous view\n * across a failed read (status stays `ready` with an `error`, or returns to\n * `idle` when nothing was ever held).\n */\nclass SettingsDescribeMirror {\n private readonly store: SnapshotStore<MirrorState>\n private inFlight: Promise<void> | undefined\n private rerun = false\n private generation = 0\n /** Pending retry handle and how many of {@link SETTINGS_DESCRIBE_RETRY_MS} are spent. */\n private retryHandle: unknown\n private retries = 0\n private disposed = false\n\n constructor(\n private readonly resolveRemote: SettingsRemoteResolver,\n private readonly timer: SettingsRetryTimer = REAL_SETTINGS_TIMER,\n ) {\n this.store = createSnapshotStore<MirrorState>({\n status: 'idle',\n view: null,\n error: null,\n })\n }\n\n getSnapshot(): MirrorState {\n return this.store.getSnapshot()\n }\n\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** The cheap idempotent entry: kick a first read. */\n ensure(): void {\n void this.load()\n }\n\n /**\n * Refresh from the Host. A call during an in-flight read marks one rerun\n * after it settles instead of racing a second wire read.\n * @returns settlement after this call's freshness is reflected.\n */\n load(): Promise<void> {\n if (this.disposed) return Promise.resolve()\n // A live read supersedes a scheduled retry: the retry exists only to\n // revive a mirror that nothing else would ever re-read.\n this.clearRetry()\n if (this.inFlight !== undefined) {\n this.rerun = true\n return this.inFlight\n }\n const run = Promise.resolve().then(() => this.run())\n this.inFlight = run\n return run\n }\n\n /**\n * Fold one write answer's namespace ROW into the held view without a wire\n * read, and invalidate any read still in flight: a read begun before the\n * write committed must not publish the pre-write document over it. With no\n * held document the answer is not published as a partial document — the\n * next read (or the failed-write recovery) picks it up.\n * @param row - The namespace view a settings write answered with.\n */\n acceptView(row: SettingsNamespaceRow): void {\n const before = this.store.getSnapshot()\n this.generation += 1\n if (this.inFlight !== undefined) this.rerun = true\n if (before.view === null) return\n const held = before.view\n const namespaces = held.namespaces?.some((candidate) => candidate.ns === row.ns)\n ? held.namespaces.map((candidate) => (candidate.ns === row.ns ? row : candidate))\n : [...(held.namespaces ?? []), row]\n this.store.set({ ...before, view: { ...held, namespaces } })\n }\n\n private async run(): Promise<void> {\n try {\n for (;;) {\n const before = this.store.getSnapshot()\n if (before.status === 'idle') this.store.set({ ...before, status: 'loading' })\n this.rerun = false\n const generation = ++this.generation\n let outcome: { view: SettingsView } | { failure: string }\n try {\n const namespace = this.resolveRemote()\n if (namespace === undefined) throw new Error('the settings remote namespace is not mounted')\n const response = await namespace.describe()\n if (response.ok) {\n const value: unknown = response.value\n // The mirror holds a VIEW or nothing: an empty/malformed answer\n // must not be published as `ready` with an undefined view, or the\n // derive below would read through it. (Upstream guards the same way\n // by testing the held view for `undefined`.)\n outcome = typeof value === 'object' && value !== null\n ? { view: value as SettingsView }\n : { failure: 'settings describe answered no view' }\n } else {\n outcome = { failure: response.error?.message ?? 'settings describe failed' }\n }\n } catch (error: unknown) {\n outcome = { failure: readableErrorText(error) }\n }\n if (generation !== this.generation) continue\n if ('view' in outcome) {\n this.retries = 0\n this.store.set({ status: 'ready', view: outcome.view, error: null })\n } else {\n const held = this.store.getSnapshot()\n this.store.set({\n status: held.view === null ? 'idle' : 'ready',\n view: held.view,\n error: outcome.failure,\n })\n // Nothing held → nothing can heal this but a retry (see\n // SETTINGS_DESCRIBE_RETRY_MS); a held view needs none.\n if (held.view === null) this.scheduleRetry()\n }\n if (!this.rerun) break\n }\n } finally {\n this.inFlight = undefined\n }\n }\n\n /**\n * Schedule the next retry of a failed FIRST read ({@link SETTINGS_DESCRIBE_RETRY_MS}).\n * Bounded: once the ladder is spent the scope keeps its degraded snapshot,\n * exactly as before, until an invalidation or a namespace re-mount arrives.\n */\n private scheduleRetry(): void {\n if (this.disposed || this.retries >= SETTINGS_DESCRIBE_RETRY_MS.length) return\n const delay = SETTINGS_DESCRIBE_RETRY_MS[this.retries]!\n this.retries += 1\n this.retryHandle = this.timer.set(() => {\n this.retryHandle = undefined\n void this.load()\n }, delay)\n }\n\n /** Cancel a pending retry (a live read is starting, or the scope is going away). */\n private clearRetry(): void {\n if (this.retryHandle !== undefined) this.timer.clear(this.retryHandle)\n this.retryHandle = undefined\n }\n\n /** Stop the mirror: no further reads, and no retry may fire after disposal. */\n dispose(): void {\n this.disposed = true\n this.clearRetry()\n }\n}\n\n/**\n * One namespace's derived scope over the shared mirror, plus its serialized\n * Host writes — the face `CommandCodeSettingsController` consumes\n * (`getSnapshot` / `subscribe` / `set` / `unset`).\n */\nclass RemoteSettingsScope<T> implements SettingsScope<T> {\n private readonly resolveRemote: SettingsRemoteResolver\n private readonly store: SnapshotStore<SettingsScopeSnapshot<T>>\n private readonly mirror: SettingsDescribeMirror\n private readonly namespace: string\n private tail: Promise<void> = Promise.resolve()\n private writeGeneration = 0\n private disposed = false\n private unsubscribe: (() => void) | undefined\n /** Revision answered by a superseded write still ahead of the mirror. */\n private pendingRevision: number | undefined\n\n constructor(\n resolveRemote: SettingsRemoteResolver,\n mirror: SettingsDescribeMirror,\n namespace: string,\n ) {\n this.resolveRemote = resolveRemote\n this.mirror = mirror\n this.namespace = namespace\n this.store = createSnapshotStore<SettingsScopeSnapshot<T>>({\n status: 'loading',\n value: undefined,\n base: undefined,\n user: undefined,\n revision: undefined,\n writable: false,\n mode: 'host',\n })\n this.unsubscribe = mirror.subscribe(() => { this.derive() })\n this.derive()\n }\n\n getSnapshot(): SettingsScopeSnapshot<T> {\n return this.store.getSnapshot()\n }\n\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** Queue one field write (the single-path `set` op form). */\n async set(field: string, value: unknown): Promise<void> {\n await this.mutate([{ op: 'set', path: [field], value }])\n }\n\n /** Queue one field clear (the single-path `unset` op form). */\n async unset(field: string): Promise<void> {\n await this.mutate([{ op: 'unset', path: [field] }])\n }\n\n /**\n * Queue one atomic namespace mutation behind the single-flight fence.\n * A rejected write (e.g. `SETTINGS_CONFLICT`) re-reads the Host so the\n * snapshot reports what actually landed; an accepted one folds its answer\n * in directly — unless a newer write already superseded it, in which case\n * that answer's revision becomes the next write's fence.\n */\n mutate(ops: readonly SettingsPathOp[], expectedRevision?: number): Promise<SettingsMutationResult> {\n const ownedOps = structuredClone(ops)\n const generation = ++this.writeGeneration\n return this.enqueue(async () => {\n const revision = expectedRevision ?? this.pendingRevision ?? this.getSnapshot().revision\n const response = await this.mutateRemote(ownedOps, revision)\n if (!response.ok) {\n await this.recover(generation)\n return response.error?.message?.includes('SETTINGS_CONFLICT') ? 'conflict' : 'failed'\n }\n const row = response.value\n if (row?.ns !== this.namespace || decodeRow(row.value) === undefined || typeof row.revision !== 'number') {\n await this.recover(generation)\n return 'failed'\n }\n if (this.disposed) return 'accepted'\n if (generation === this.writeGeneration) {\n this.pendingRevision = undefined\n this.mirror.acceptView(row)\n } else {\n this.pendingRevision = typeof row.revision === 'number' ? row.revision : undefined\n }\n return 'accepted'\n })\n }\n\n private async mutateRemote(\n ops: readonly SettingsPathOp[],\n revision: number | undefined,\n ): Promise<Envelope<SettingsNamespaceRow>> {\n try {\n const namespace = this.resolveRemote()\n if (namespace === undefined) {\n return { ok: false, error: { message: 'the settings remote namespace is not mounted' } }\n }\n return await namespace.mutate(this.namespace, ops, revision)\n } catch (error: unknown) {\n return { ok: false, error: { message: readableErrorText(error) } }\n }\n }\n\n /** Reload Host state for the latest failed write; superseded failures leave recovery to it. */\n private async recover(generation: number): Promise<void> {\n if (this.disposed || generation !== this.writeGeneration) return\n this.pendingRevision = undefined\n await this.mirror.load()\n }\n\n /** Derive this namespace's snapshot from the mirror's held view. */\n private derive(): void {\n if (this.disposed) return\n const mirrored = this.mirror.getSnapshot()\n // `undefined` as well as `null`: the held view is only ever the wire's\n // answer, and a malformed one never reaches the store (see `run`).\n if (mirrored.view === null || mirrored.view === undefined) return\n const writable = mirrored.view.writable === true\n const row = mirrored.view.namespaces?.find((candidate) => candidate.ns === this.namespace)\n if (row === undefined) {\n this.publish({ status: 'unavailable', writable })\n return\n }\n const decoded = decodeRow(row.value)\n if (decoded === undefined) return\n this.publish({\n status: 'ready',\n writable,\n value: decoded as T,\n base: row.base,\n user: row.user,\n revision: typeof row.revision === 'number' ? row.revision : undefined,\n })\n }\n\n /** Publish `next` over the current snapshot, skipping the write when nothing changed. */\n private publish(next: {\n status: SettingsScopeSnapshot<T>['status']\n writable: boolean\n value?: T\n base?: unknown\n user?: unknown\n revision?: number | undefined\n }): void {\n const current = this.store.getSnapshot()\n const candidate: SettingsScopeSnapshot<T> = {\n status: next.status,\n value: 'value' in next ? next.value : current.value,\n base: 'base' in next ? next.base : current.base,\n user: 'user' in next ? next.user : current.user,\n revision: 'revision' in next ? next.revision : current.revision,\n writable: next.writable,\n mode: current.mode,\n }\n if (sameSnapshot(candidate as SettingsScopeSnapshot<never>, current as SettingsScopeSnapshot<never>)) return\n this.store.set(candidate)\n }\n\n /** Queue operations one at a time; disposal makes the queue inert. */\n private enqueue(operation: () => Promise<SettingsMutationResult>): Promise<SettingsMutationResult> {\n if (this.disposed) return Promise.resolve('cancelled')\n const task = this.tail.then(async () => {\n if (this.disposed) return 'cancelled' as const\n return operation()\n })\n this.tail = task.then(() => {}, () => {})\n return task\n }\n\n /** Stop queued operations, stop deriving, and wait for the current wire call to settle. */\n async dispose(): Promise<void> {\n this.disposed = true\n this.writeGeneration += 1\n this.unsubscribe?.()\n await this.tail\n }\n}\n\n/** The scope plus the handles the plugin entry wires into its fiber lifecycle. */\nexport interface ManagedSettingsScope<T> extends SettingsScope<T> {\n mutate(ops: readonly SettingsPathOp[], expectedRevision?: number): Promise<SettingsMutationResult>\n /** Re-read the Host — used when the `remote.settings` namespace mounts after boot. */\n refresh(): void\n /** Stop deriving, drop the forwarded-event subscriptions, and settle in-flight work. */\n dispose(): Promise<void>\n}\n\n/**\n * Build the plugin's settings scope for one namespace.\n *\n * Subscribes the two signals that can move the Host view — the forwarded\n * `settings/document-updated` invalidation and (when the client exposes it)\n * `connection/reset` — kicks the first describe read, and derives the namespace\n * row on every mirror change.\n *\n * `resolveRemote` must be the INJECT-CAPTURED namespace (see\n * {@link SettingsRemoteResolver}), and the caller that owns that inject calls\n * {@link ManagedSettingsScope.refresh} once the namespace lands — that is what\n * turns the first, namespace-less read into a served one. A profile that never\n * mounts the namespace leaves the page in its degraded (`unavailable`,\n * read-only) state instead of throwing.\n *\n * @param namespace - Settings namespace (profile entry id) this scope binds.\n */\nexport function createSettingsScope<T>(\n context: SettingsScopeContext,\n namespace: string,\n resolveRemote: SettingsRemoteResolver,\n timer: SettingsRetryTimer = REAL_SETTINGS_TIMER,\n): ManagedSettingsScope<T> {\n const mirror = new SettingsDescribeMirror(resolveRemote, timer)\n const scope = new RemoteSettingsScope<T>(resolveRemote, mirror, namespace)\n const disposers: Array<() => void> = []\n if (typeof context.remote.$on === 'function') {\n const off = context.remote.$on('settings/document-updated', () => { mirror.ensure() })\n if (typeof off === 'function') disposers.push(off)\n }\n if (typeof context.on === 'function') {\n const off = context.on('connection/reset', () => { void mirror.load() })\n if (typeof off === 'function') disposers.push(off as () => void)\n }\n mirror.ensure()\n return {\n getSnapshot: () => scope.getSnapshot(),\n subscribe: (listener) => scope.subscribe(listener),\n set: (field, value) => scope.set(field, value),\n unset: (field) => scope.unset(field),\n mutate: (ops, revision) => scope.mutate(ops, revision),\n refresh: () => { void mirror.load() },\n dispose: async () => {\n for (const dispose of disposers.splice(0)) dispose()\n // Before the scope: a pending describe retry would otherwise re-read a\n // directory nobody is rendering any more.\n mirror.dispose()\n await scope.dispose()\n },\n }\n}\n","/** 两端共用可编辑超时范围,存储仍是整数毫秒;提示不能借用重试退避上限。 */\nexport const MIN_TIMEOUT_SECONDS = 0.001\nexport const MAX_TIMEOUT_SECONDS = 3600\n","/** 网页、终端与模型目录共用的选择规则;显式开关优先于白名单。 */\nexport function modelIsVisible(id: string, allowlist: readonly string[], overrides: unknown): boolean {\n const flag = overrides !== null && typeof overrides === 'object' && !Array.isArray(overrides)\n ? (overrides as Record<string, unknown>)[id] : undefined\n return typeof flag === 'boolean' ? flag : allowlist.length === 0 || allowlist.includes(id)\n}\n\n/** 只接收布尔事实,手工配置中的其他值不能成为可见性开关。 */\nexport function readVisibility(raw: unknown): Record<string, boolean> {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) return {}\n return Object.fromEntries(Object.entries(raw).filter(([id, value]) => id !== '' && typeof value === 'boolean'))\n}\n","/** 设置写入过程:同一控制器的意图按顺序执行,配置确认与凭据确认分别保留。\n * 生产使用现有远端设置/凭据,测试替换这些依赖;不提供跨服务事务。 */\nimport { readVisibility } from '../model-visibility.ts'\nimport type { SettingsPageApi, SettingsScope, SettingsScopeSnapshot } from './settings.ts'\nimport type { SettingsMutationResult, SettingsPathOp } from './settings-scope.ts'\n\nexport const DEFAULT_API_KEY_REF = 'COMMANDCODE_API_KEY'\nexport interface StoredRule { models: string[]; account: string }\n\n/** 与宿主路由的第一条匹配规则一致,重复模型只归属于先出现的账号。 */\nexport function accountModelMap(rules: readonly StoredRule[]): Map<string, string[]> {\n const claimed = new Set<string>()\n const map = new Map<string, string[]>()\n for (const rule of rules) {\n const list = map.get(rule.account) ?? []\n for (const model of rule.models) {\n if (claimed.has(model)) continue\n claimed.add(model)\n list.push(model)\n }\n map.set(rule.account, list)\n }\n return map\n}\n\nexport interface SettingsWriteResult {\n config: 'none' | 'confirmed' | 'conflict' | 'unconfirmed'\n credential: 'none' | 'not-issued' | 'confirmed' | 'unconfirmed'\n issue: 'target-changed' | 'closed' | 'cleanup-pending' | undefined\n refreshFailed: boolean\n /** 实际发出调用的原引用,仅用于核对;从不包含密钥内容。 */\n credentialRef: string | undefined\n}\n\nexport type SettingsWriteIntent =\n | { kind: 'save'; ops: readonly SettingsPathOp[]; visibleModels?: readonly string[]; key?: string }\n | { kind: 'rename'; ref: string; label: string }\n | { kind: 'remove' | 'cleanup'; ref: string }\n | { kind: 'key'; target: string; value?: string }\n | { kind: 'active'; id: string }\n | { kind: 'models'; target: string; models: readonly string[] }\n\ntype Snapshot = SettingsScopeSnapshot<Record<string, unknown>>\ntype CredentialInfo = { configured: boolean; writable: boolean }\ntype FieldBaseline = { value: unknown; base: unknown; user: unknown; overridden: boolean }\ninterface Command {\n intent: SettingsWriteIntent\n ops: readonly SettingsPathOp[]\n baseline: Map<string, FieldBaseline>\n defaultRef: string | undefined\n}\ninterface QueuedWrite { command: Command; resolve(result: SettingsWriteResult): void }\n\nconst record = (value: unknown): Record<string, unknown> => value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\nconst result = (): SettingsWriteResult => ({ config: 'none', credential: 'none', issue: undefined, refreshFailed: false, credentialRef: undefined })\nconst closedResult = (): SettingsWriteResult => ({ ...result(), issue: 'closed' })\nconst fieldBaseline = (snapshot: Snapshot, field: string): FieldBaseline => ({\n value: snapshot.value?.[field], base: record(snapshot.base)[field], user: record(snapshot.user)[field],\n overridden: Object.hasOwn(record(snapshot.user), field),\n})\n\n/** 不用显示文本比较配置;数组顺序与显式覆盖/继承也是写入事实。 */\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((value, i) => sameValue(value, b[i]))\n if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false\n const left = record(a), right = record(b)\n const keys = Object.keys(left)\n return keys.length === Object.keys(right).length && keys.every(key => Object.hasOwn(right, key) && sameValue(left[key], right[key]))\n}\n\nexport function writeCompleted(outcome: SettingsWriteResult): boolean {\n return outcome.issue === undefined && outcome.config !== 'conflict' && outcome.config !== 'unconfirmed'\n && outcome.credential !== 'not-issued' && outcome.credential !== 'unconfirmed'\n}\n\nexport class SettingsWriter {\n private readonly pending: QueuedWrite[] = []\n private running = false\n private closed = false\n private readonly facts = new Map<string, CredentialInfo>()\n /** 每个引用独立的读写世代,防止旧描述覆盖随后确认的凭据修改。 */\n private readonly factVersions = new Map<string, number>()\n private refreshGeneration = 0\n private refreshFailed = false\n\n constructor(\n private readonly scope: SettingsScope<Record<string, unknown>>,\n private readonly credentials: SettingsPageApi['credentials'],\n private readonly onFactsChanged: () => void,\n ) {}\n\n credential(ref: string): CredentialInfo | undefined { return this.facts.get(ref) }\n factsRefreshFailed(): boolean { return this.refreshFailed }\n\n /** 在入队时捕获意图与目标;执行者不能重新读取页面草稿。 */\n submit(intent: SettingsWriteIntent): Promise<SettingsWriteResult> {\n if (this.closed) return Promise.resolve(closedResult())\n const owned = structuredClone(intent)\n const snapshot = this.scope.getSnapshot()\n const ops = owned.kind === 'save' ? [...owned.ops] : []\n if (owned.kind === 'save' && owned.visibleModels !== undefined) {\n const list = [...owned.visibleModels]\n const keys = new Set<string>()\n for (const layer of [snapshot.base, snapshot.user, snapshot.value]) {\n for (const id of Object.keys(readVisibility(record(layer).modelVisibility))) keys.add(id)\n }\n ops.push({ op: 'set', path: ['visibleModels'], value: list },\n { op: 'set', path: ['modelVisibility'], value: Object.fromEntries([...keys].map(id => [id, list.length === 0 || list.includes(id)])) })\n }\n const baseline = new Map(ops.map(op => [op.path[0]!, structuredClone(fieldBaseline(snapshot, op.path[0]!))]))\n const defaultRef = (owned.kind === 'save' && owned.key !== undefined) || (owned.kind === 'key' && owned.target === 'default')\n ? this.defaultRef() : undefined\n return new Promise(resolve => {\n this.pending.push({ command: { intent: owned, ops, baseline, defaultRef }, resolve })\n if (!this.running) void this.drain()\n })\n }\n\n /** 销毁不等待远端;未发出的任务立即结束,已发调用只能自然收束。 */\n dispose(): void {\n this.closed = true\n for (const task of this.pending.splice(0)) task.resolve(closedResult())\n this.facts.clear()\n this.factVersions.clear()\n }\n\n private async drain(): Promise<void> {\n this.running = true\n try {\n for (;;) {\n const task = this.pending.shift()\n if (task === undefined) break\n let outcome: SettingsWriteResult\n try { outcome = this.closed ? closedResult() : await this.execute(task.command) }\n catch { outcome = { ...result(), config: 'unconfirmed' } }\n task.resolve(outcome)\n }\n } finally { this.running = false }\n }\n\n private defaultRef(): string {\n const ref = this.scope.getSnapshot().value?.apiKeyEnv\n return typeof ref === 'string' && ref !== '' ? ref : DEFAULT_API_KEY_REF\n }\n private value(field: string): unknown { return this.scope.getSnapshot().value?.[field] }\n private accounts(): Record<string, unknown>[] {\n const raw = this.value('accounts')\n return Array.isArray(raw) ? raw.filter(item => item !== null && typeof item === 'object' && !Array.isArray(item)) as Record<string, unknown>[] : []\n }\n private rules(): StoredRule[] {\n const raw = this.value('modelAccountRules')\n if (!Array.isArray(raw)) return []\n return raw.flatMap(item => {\n const rule = record(item)\n const models = Array.isArray(rule.models) ? rule.models.filter((id): id is string => typeof id === 'string' && id !== '') : []\n return models.length ? [{ models, account: typeof rule.account === 'string' && rule.account !== '' ? rule.account : 'default' }] : []\n })\n }\n private cleanupRefs(): string[] {\n const raw = this.value('credentialCleanupRefs')\n return Array.isArray(raw) ? [...new Set(raw.filter((ref): ref is string => typeof ref === 'string' && ref !== ''))] : []\n }\n private bump(ref: string): number {\n const next = (this.factVersions.get(ref) ?? 0) + 1\n this.factVersions.set(ref, next)\n return next\n }\n\n /** 只刷新事实;此入口永远不重放凭据修改。缺少条目不能解释为不存在。 */\n async refreshCredentials(extra: readonly string[] = []): Promise<boolean> {\n if (this.closed) return false\n const refs = [...new Set([this.defaultRef(), ...this.accounts().flatMap(account => typeof account.apiKeyEnv === 'string' ? [account.apiKeyEnv] : []), ...extra])]\n const generation = ++this.refreshGeneration\n const versions = new Map(refs.map(ref => [ref, this.bump(ref)]))\n let success = false\n try {\n const response = await this.credentials.describe(refs)\n if (this.closed) return false\n success = response.ok && refs.every(ref => typeof response.value?.[ref]?.configured === 'boolean')\n success = success && refs.every(ref => this.factVersions.get(ref) === versions.get(ref))\n if (success) for (const ref of refs) {\n if (this.factVersions.get(ref) !== versions.get(ref)) continue\n const view = response.value![ref]!\n this.facts.set(ref, { configured: view.configured, writable: view.writable ?? true })\n }\n } catch { /* 未读到新事实时保留最后已确认结果,不猜测不存在。 */ }\n if (!this.closed && generation === this.refreshGeneration) {\n this.refreshFailed = !success\n this.onFactsChanged()\n }\n return success\n }\n\n private async commit(ops: readonly SettingsPathOp[], baseline?: ReadonlyMap<string, FieldBaseline>): Promise<SettingsMutationResult> {\n if (this.closed) return 'cancelled'\n const snapshot = this.scope.getSnapshot()\n if (!snapshot.writable || this.scope.mutate === undefined) return 'failed'\n if (baseline && [...baseline].some(([field, before]) => !sameValue(before, fieldBaseline(snapshot, field)))) return 'conflict'\n try { return await this.scope.mutate(ops, snapshot.revision) }\n catch { return 'failed' }\n }\n\n private async configure(outcome: SettingsWriteResult, ops: readonly SettingsPathOp[], baseline?: ReadonlyMap<string, FieldBaseline>): Promise<boolean> {\n if (ops.length === 0) return true\n const confirmation = await this.commit(ops, baseline)\n outcome.config = confirmation === 'accepted' ? 'confirmed' : confirmation === 'conflict' ? 'conflict' : 'unconfirmed'\n if (confirmation === 'cancelled' || this.closed) outcome.issue = 'closed'\n return confirmation === 'accepted' && !this.closed\n }\n\n private async changeCredential(outcome: SettingsWriteResult, ref: string, value: string | undefined, defaultRef?: string): Promise<void> {\n outcome.credential = 'not-issued'\n if (this.closed) { outcome.issue = 'closed'; return }\n if (defaultRef !== undefined && this.defaultRef() !== defaultRef) { outcome.issue = 'target-changed'; return }\n outcome.credentialRef = ref\n this.bump(ref)\n try {\n const response = value === undefined ? await this.credentials.unset(ref) : await this.credentials.set(ref, value)\n outcome.credential = response.ok ? 'confirmed' : 'unconfirmed'\n } catch { outcome.credential = 'unconfirmed' }\n if (this.closed) { outcome.issue = 'closed'; return }\n this.bump(ref)\n // 远端写入确认说明引用已修改;后续读回不提供密钥内容校验。\n if (outcome.credential === 'confirmed') {\n this.facts.set(ref, { configured: value !== undefined, writable: this.facts.get(ref)?.writable ?? true })\n this.onFactsChanged()\n }\n if (defaultRef !== undefined && this.defaultRef() !== defaultRef) outcome.issue = 'target-changed'\n outcome.refreshFailed = !(await this.refreshCredentials([ref]))\n if (defaultRef !== undefined && this.defaultRef() !== defaultRef) outcome.issue = 'target-changed'\n if (this.closed) outcome.issue = 'closed'\n }\n\n private async execute(command: Command): Promise<SettingsWriteResult> {\n const outcome = result()\n const intent = command.intent\n if (!this.scope.getSnapshot().writable) return {\n ...outcome,\n config: intent.kind === 'key' || (intent.kind === 'save' && command.ops.length === 0) ? 'none' : 'unconfirmed',\n credential: intent.kind === 'key' || (intent.kind === 'save' && intent.key !== undefined) ? 'not-issued' : 'none',\n }\n if (intent.kind === 'save') {\n if (intent.key !== undefined) outcome.credential = 'not-issued'\n if (!(await this.configure(outcome, command.ops, command.baseline))) return outcome\n if (intent.key !== undefined) await this.changeCredential(outcome, command.defaultRef!, intent.key, command.defaultRef)\n } else if (intent.kind === 'key') {\n if (intent.value !== undefined && intent.value.trim() === '') return { ...outcome, credential: 'not-issued' }\n await this.changeCredential(outcome, command.defaultRef ?? intent.target, intent.value, command.defaultRef)\n } else if (intent.kind === 'rename') {\n if (intent.label === '') return { ...outcome, config: 'unconfirmed' }\n await this.configure(outcome, [{ op: 'set', path: ['accounts'], value: this.accounts().map(account => account.apiKeyEnv === intent.ref ? { ...account, label: intent.label } : { ...account }) }])\n } else if (intent.kind === 'active') {\n // 恢复自动轮换与恢复继承不同;基础层有固定账号时必须显式覆盖为空。\n const base = record(this.scope.getSnapshot().base).activeAccount\n const op: SettingsPathOp = intent.id !== '' || (typeof base === 'string' && base !== '')\n ? { op: 'set', path: ['activeAccount'], value: intent.id } : { op: 'unset', path: ['activeAccount'] }\n await this.configure(outcome, [op])\n } else if (intent.kind === 'models') {\n const chosen = [...new Set(intent.models.filter(id => id !== ''))]\n const taken = new Set(chosen)\n const map = accountModelMap(this.rules())\n for (const [account, models] of map) if (account !== intent.target) map.set(account, models.filter(id => !taken.has(id)))\n map.set(intent.target, chosen)\n const rules = [...map].flatMap(([account, models]) => models.length ? [{ account, models }] : [])\n await this.configure(outcome, [{ op: 'set', path: ['modelAccountRules'], value: rules }])\n } else {\n if (intent.kind === 'remove') {\n if (!this.accounts().some(account => account.apiKeyEnv === intent.ref) && !this.cleanupRefs().includes(intent.ref)) return { ...outcome, config: 'unconfirmed' }\n const snapshot = this.scope.getSnapshot()\n const ops: SettingsPathOp[] = [\n { op: 'set', path: ['accounts'], value: this.accounts().filter(account => account.apiKeyEnv !== intent.ref).map(account => ({ ...account })) },\n { op: 'set', path: ['modelAccountRules'], value: this.rules().filter(rule => rule.account !== intent.ref) },\n { op: 'set', path: ['credentialCleanupRefs'], value: [...new Set([...this.cleanupRefs(), intent.ref])] },\n ]\n if (this.value('activeAccount') === intent.ref) ops.push(record(snapshot.base).activeAccount === intent.ref\n ? { op: 'set', path: ['activeAccount'], value: '' } : { op: 'unset', path: ['activeAccount'] })\n if (!(await this.configure(outcome, ops))) return outcome\n }\n await this.cleanRemoved(outcome, intent.ref)\n }\n return outcome\n }\n\n private async cleanRemoved(outcome: SettingsWriteResult, ref: string): Promise<void> {\n if (!this.cleanupRefs().includes(ref)) {\n if (outcome.config !== 'confirmed') outcome.config = 'unconfirmed'\n outcome.issue = 'cleanup-pending'\n return\n }\n if (this.closed) { outcome.issue = 'closed'; return }\n if (!(await this.refreshCredentials([ref]))) { outcome.credential = 'not-issued'; outcome.refreshFailed = true; return }\n if (this.closed) { outcome.issue = 'closed'; return }\n const inherited = record(this.scope.getSnapshot().base).accounts\n const referenced = ref === this.defaultRef() || this.accounts().some(account => account.apiKeyEnv === ref)\n || (Array.isArray(inherited) && inherited.some(account => record(account).apiKeyEnv === ref))\n || this.rules().some(rule => rule.account === ref) || this.value('activeAccount') === ref\n if (!referenced && this.facts.get(ref)?.configured === true) {\n await this.changeCredential(outcome, ref, undefined)\n if (!writeCompleted(outcome) || outcome.refreshFailed) {\n if (outcome.issue === undefined && outcome.credential === 'confirmed') outcome.issue = 'cleanup-pending'\n return\n }\n }\n if (this.closed) { outcome.issue = 'closed'; return }\n // 最后一步失败不能抹掉前面已经确认的账号移除/凭据清理事实。\n const cleanup = result()\n if (!(await this.configure(cleanup, [{ op: 'set', path: ['credentialCleanupRefs'], value: this.cleanupRefs().filter(entry => entry !== ref) }]))) {\n if (outcome.config === 'none') outcome.config = cleanup.config\n outcome.issue = cleanup.issue ?? 'cleanup-pending'\n } else if (outcome.config === 'none') outcome.config = cleanup.config\n }\n}\n","/** 设置页面控制器只负责输入校验、草稿版本与页面投影。\n * 保存及即时账号操作由同一个设置写入过程持有;设置与凭据分别确认。 */\n\nimport { MIN_TIMEOUT_SECONDS, MAX_TIMEOUT_SECONDS } from '../timeout-limits.ts'\nimport { modelIsVisible, readVisibility } from '../model-visibility.ts'\nimport type { SettingsMutationResult, SettingsPathOp } from './settings-scope.ts'\nimport { SettingsWriter, DEFAULT_API_KEY_REF, accountModelMap, writeCompleted, type StoredRule, type SettingsWriteIntent, type SettingsWriteResult } from './settings-write.ts'\nexport { DEFAULT_API_KEY_REF, accountModelMap } from './settings-write.ts'\n\n/** The settings namespace the plugin registers (host half, src/index.ts). */\nexport const COMMANDCODE_NS = 'llm-commandcode'\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'\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 mutate?(ops: readonly SettingsPathOp[], expectedRevision?: number): Promise<SettingsMutationResult>\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 model editors (Host-side). Optional: a transport\n * without the Remote mount leaves the editors on the empty-catalog state.\n */\n models?(): Promise<RemoteResult<{ models: CatalogModelOption[] }>>\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 /** `format`, `tooSmall`/`tooLarge`; undefined when valid. */\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/**\n * One extra account row. Account management commits immediately (no page\n * save), so a row carries only Host facts — never a staged draft.\n */\nexport interface AccountItemState {\n /** Stable id — the account's credential reference (also its slot id). */\n id: string\n ref: string\n /** Stored label (falls back to the reference). */\n label: string\n configured: boolean\n credentialKnown: boolean\n writable: boolean\n}\n\n/** The immediate account operations, named for the failure copy. */\nexport type AccountOperation = 'rename' | 'remove' | 'key' | 'active' | 'models'\n\n/** One selectable catalog model in the settings page's model editors. */\nexport interface CatalogModelOption {\n id: string\n name: string\n /**\n * Minimum plan-tier key (a Host `KNOWN_PLANS` value), or undefined for\n * models outside the snapshot / older Hosts. Drives the tier headings in\n * the editor dropdowns; absent tiers render unheaded.\n */\n tier?: string\n /**\n * Per-model MONTHLY allowance in USD, already resolved Host-side against the\n * account pool's highest plan (Go, GOAT and Pro publish one). Undefined for\n * plans without an allowance, for models the page has no row for, and for\n * older Hosts — the row then shows no allowance instead of a guess.\n */\n allowance?: number\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 /** 没有描述或写入确认时状态未知,不能显示为未配置。 */\n apiKeyKnown: 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 /**\n * The default API key draft (write-only; starts blank, never echoes the\n * stored key). Only the Models-page card stages it for its own save; the\n * settings page writes keys immediately through `setAccountKey()`.\n */\n apiKey: StagedField\n apiBase: StagedField\n requestTimeoutMs: StagedField\n streamIdleTimeoutMs: StagedField\n /**\n * transportMaxRetries draft: how many transport failures one request absorbs\n * before the failure surfaces (issue #39's second report — the retry policy's\n * 1000-attempt, 15-minute cadence turned a 10-second TCP connect timeout into\n * an ~8-minute stall). Unset means the Host default, so it stages like the\n * timeout fields above rather than as a toggle with an implicit default.\n */\n transportMaxRetries: StagedField\n /** Opt-in durable offload of images after this model has answered. */\n offloadSeenImagesForCache: StagedField\n /** filterModelsByPlan draft; `''` = \"inherit the default\" (on). */\n filterModelsByPlan: StagedField\n /** webSearch draft; `''` = \"inherit the default\" (on — this route serves dsh's web_search). */\n webSearch: StagedField\n /** showSidebarQuota draft; `''` = \"inherit the default\" (off — the card is opt-in). */\n showSidebarQuota: StagedField\n /** zdr draft; `''` = \"inherit the default\" (off — ZDR is opt-in). */\n zdr: StagedField\n /**\n * Whether the STORED document turns the sidebar quota card on\n * (`showSidebarQuota === true`). Deliberately NOT the staged draft above: the\n * page has an explicit Save, and a card that appeared from an unsaved draft\n * would outlive a discarded edit (staging lives as long as the client does)\n * until the next page load.\n */\n sidebarQuota: boolean\n /** The stored pinned account: a slot id; `''` = \"auto — first usable account\". */\n activeAccount: string\n /** Extra accounts (multi-account rotation), in rotation order. */\n accounts: AccountItemState[]\n /**\n * Each account's dedicated models, keyed by slot id, derived from the stored\n * `modelAccountRules` with the runtime's first-match-wins semantics, so a\n * model sits under exactly the one account that would serve it.\n */\n accountModels: Record<string, string[]>\n /** Whether an immediate account operation is in flight. */\n accountBusy: boolean\n /** The last immediate account operation that failed (cleared by the next one). */\n accountFailed: AccountOperation | undefined\n /** 已移除账户的待清理凭据引用,来自持久化配置,刷新后仍能重试。 */\n pendingCredentialCleanup: string[]\n /** 宿主开通尚未完成的引用,不展示可操作的账号行。 */\n accountEnrollmentRefs: string[]\n /** Effective visible-model allowlist: staged draft or stored value. Empty = show all. */\n visibleModels: string[]\n /** 区分不受限制与终端显式隐藏全部;不能用空数组推断显示全部。 */\n visibleModelsAll: boolean\n /** The catalog the model editors offer (Host-side, empty until loaded). */\n catalogModels: CatalogModelOption[]\n /** Whether the catalog fetch failed (editors fall 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 /** Monotonic counter bumped once per accepted save (the component flashes on it). */\n savedCount: number\n /** 本次写入各阶段的确认事实,不用整体失败推断回滚。 */\n saveResult: SettingsWriteResult | undefined\n accountResult: SettingsWriteResult | undefined\n credentialRefreshFailed: boolean\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, like the Host schema's `z.number()`.\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 * The second-based bounds the timeout fields are EDITED in.\n *\n * The stored unit stays milliseconds — that is the Host schema\n * (`z.number().min(1).max(MAX_TIMER_DELAY_MS)` in src/index.ts, dsh-timeout's\n * 2^31-1 timer ceiling), and switching it would break every existing profile —\n * so this is presentation only: the field formats ms ÷ 1000 on the way in and\n * multiplies by 1000 on the way out. 3600 rather than the Host's ceiling (~24.8\n * days), because a header wait longer than an hour is a hung process, not a\n * budget, and the input is the place to refuse it. A hand-written profile can\n * still carry a larger value; `secondsField` displays that true number rather\n * than silently clamping, it just cannot be re-typed here.\n */\nexport { MIN_TIMEOUT_SECONDS, MAX_TIMEOUT_SECONDS } from '../timeout-limits.ts'\n\n/**\n * 秒制输入保留毫秒精度,兼容已有 1500ms、1ms 等配置。\n *\n * Milliseconds are the wrong unit to show: the defaults are 300000 and the\n * ceiling is 2147483647, so the page asked users to do arithmetic to answer\n * \"how long is a reasonable wait\". `format` divides, `parse` multiplies, and\n * the stored value never leaves milliseconds.\n *\n * 最多三位小数;不接受更多位数后悄悄取整,避免页面与存储不一致。\n */\nfunction secondsField(field: string, bounds: { min: number; max: number }): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'number' ? String(value / 1000) : ''),\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return { kind: 'clear' }\n const parsed = Number(trimmed)\n if (!Number.isFinite(parsed) || !/^-?(?:\\d+(?:\\.\\d{1,3})?|\\.\\d{1,3})$/.test(trimmed)) return { kind: 'invalid', reason: 'format' }\n if (parsed < bounds.min) return { kind: 'invalid', reason: 'tooSmall' }\n if (parsed > bounds.max) return { kind: 'invalid', reason: 'tooLarge' }\n return { kind: 'set', value: Math.round(parsed * 1000) }\n },\n }\n}\n\n/** The fields this page edits inside the `llm-commandcode` namespace. */\nconst SECTION_FIELDS: FieldSpec[] = [\n textField('apiBase'),\n secondsField('requestTimeoutMs', { min: MIN_TIMEOUT_SECONDS, max: MAX_TIMEOUT_SECONDS }),\n secondsField('streamIdleTimeoutMs', { min: MIN_TIMEOUT_SECONDS, max: MAX_TIMEOUT_SECONDS }),\n // A COUNT of retries, not a millisecond wait: it shares the Host schema's\n // 0..50 bounds (`MAX_TRANSPORT_MAX_RETRIES` in src/transport-retry.ts, applied\n // to `transportMaxRetries` in src/index.ts) rather than the timer ceiling\n // above, so a draft can never be saved in a shape the Host rejects. The Host\n // stays the final gate, and the client bundle cannot import that node-side\n // module — `tests/transport-retry.test.ts` pins the schema's bound against\n // the constant so this mirrored literal cannot drift unnoticed.\n numberField('transportMaxRetries', { min: 0, max: 50 }),\n booleanField('offloadSeenImagesForCache'),\n booleanField('filterModelsByPlan'),\n booleanField('webSearch'),\n booleanField('showSidebarQuota'),\n booleanField('zdr'),\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/** 共享控制器跨普通切页保存草稿,插件销毁才关闭写入过程。 */\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 credentialRef = DEFAULT_API_KEY_REF\n private readonly writer: SettingsWriter\n private saveResult: SettingsWriteResult | undefined\n private accountResult: SettingsWriteResult | undefined\n /** Staged visible-model allowlist (undefined = no draft). */\n private visibleModelsDraft: string[] | undefined = undefined\n private catalogModels: CatalogModelOption[] = []\n private catalogFailed = false\n private saving = false\n private failed = false\n private savedCount = 0\n private accountPending = 0\n private accountFailed: AccountOperation | undefined = undefined\n\n constructor(\n scope: SettingsScope<Record<string, unknown>>,\n api: SettingsPageApi,\n ) {\n this.scope = scope\n this.api = api\n this.writer = new SettingsWriter(scope, api.credentials, () => this.publish())\n this.disposers.push(scope.subscribe(() => {\n this.recomputeCredentialRef()\n void this.writer.refreshCredentials()\n this.publish()\n }))\n this.recomputeCredentialRef()\n void this.writer.refreshCredentials()\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 this.writer.dispose()\n this.staged.clear()\n this.visibleModelsDraft = undefined\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 the profile Config gets a page that\n * addresses the renamed ref instead of silently writing the default —\n * 与模型卡共享同一设置引用。\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 }\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.writer.credential(this.credentialRef)\n const accounts = this.effectiveAccounts()\n const active = this.sectionValue('activeAccount')\n return {\n available: snapshot.status === 'ready',\n writable: snapshot.writable,\n apiKeyConfigured: credential?.configured ?? false,\n apiKeyKnown: credential !== undefined,\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 apiBase: this.field('apiBase'),\n requestTimeoutMs: this.field('requestTimeoutMs'),\n streamIdleTimeoutMs: this.field('streamIdleTimeoutMs'),\n transportMaxRetries: this.field('transportMaxRetries'),\n offloadSeenImagesForCache: this.field('offloadSeenImagesForCache'),\n filterModelsByPlan: this.field('filterModelsByPlan'),\n webSearch: this.field('webSearch'),\n showSidebarQuota: this.field('showSidebarQuota'),\n zdr: this.field('zdr'),\n sidebarQuota: this.sectionValue('showSidebarQuota') === true,\n activeAccount: typeof active === 'string' ? active : '',\n accounts,\n accountModels: Object.fromEntries(accountModelMap(this.storedRules())),\n accountBusy: this.accountPending > 0,\n accountFailed: this.accountFailed,\n pendingCredentialCleanup: this.cleanupRefs().filter((ref) => !this.enrollmentRefs(true).includes(ref)),\n accountEnrollmentRefs: this.enrollmentRefs(false),\n visibleModels: this.effectiveVisibleModels(),\n visibleModelsAll: this.visibleModelsDraft === undefined ? this.storedShowsAll() : this.visibleModelsDraft.length === 0,\n catalogModels: this.catalogModels,\n catalogFailed: this.catalogFailed,\n dirty: plan.length > 0 || this.visibleModelsDirty(),\n invalid: plan.some((item) => item.change === undefined),\n saving: this.saving,\n failed: this.failed,\n savedCount: this.savedCount,\n saveResult: this.saveResult,\n accountResult: this.accountResult,\n credentialRefreshFailed: this.writer.factsRefreshFailed(),\n }\n }\n\n // --- Staged form ---\n\n private enrollmentRefs(includeNamed: boolean): string[] {\n const records = this.sectionValue('accountEnrollmentTasks')\n if (!Array.isArray(records)) return []\n return records.flatMap((item: unknown) => {\n if (typeof item !== 'object' || item === null) return []\n const record = item as Record<string, unknown>\n return typeof record.ref === 'string' && (includeNamed || record.phase !== 'naming') ? [record.ref] : []\n })\n }\n\n /** Stage one field's draft text. */\n edit(field: string, text: string): void {\n if (field !== 'apiKey') this.spec(field)\n this.staged.set(field, { text, clear: false })\n this.failed = false\n this.saveResult = undefined\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.saveResult = undefined\n this.publish()\n }\n\n /** Discard every staged edit. */\n discard(): void {\n if (this.staged.size === 0 && this.visibleModelsDraft === undefined && !this.failed) return\n this.staged.clear()\n this.visibleModelsDraft = undefined\n this.failed = false\n this.saveResult = undefined\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 async refreshCredentials(): Promise<void> {\n if (!(await this.writer.refreshCredentials()) || this.disposed) return\n if (this.saveResult) this.saveResult = { ...this.saveResult, refreshFailed: false }\n if (this.accountResult) this.accountResult = { ...this.accountResult, refreshFailed: false }\n this.publish()\n }\n\n /** 冻结点击时的草稿;只清理本次已确认且期间未被替换的对象。 */\n async save(): Promise<SettingsWriteResult | undefined> {\n if (this.disposed || this.saving) return\n const submitted = new Map(this.staged)\n const submittedVisible = this.visibleModelsDraft\n const plan = this.plan()\n const visibleDirty = this.visibleModelsDirty()\n if ((plan.length === 0 && !visibleDirty) || plan.some(item => item.change === undefined)) return\n const ops = plan.flatMap(item => typeof item.change === 'object' ? [item.change] : [])\n const key = plan.find(item => item.field === 'apiKey')?.change\n this.saving = true\n this.failed = false\n this.saveResult = undefined\n // 入队先于通知订阅者,避免通知回调发起的后续操作插队。\n const completion = this.writer.submit({ kind: 'save', ops,\n ...(visibleDirty ? { visibleModels: submittedVisible ?? [] } : {}),\n ...(typeof key === 'string' ? { key } : {}),\n })\n this.publish()\n const outcome = await completion\n if (this.disposed) return outcome\n this.saving = false\n this.saveResult = outcome\n this.failed = !writeCompleted(outcome)\n if (!this.failed) this.savedCount += 1\n for (const [field, draft] of submitted) {\n const confirmed = field === 'apiKey'\n ? outcome.credential === 'confirmed' && outcome.issue === undefined\n : outcome.config === 'confirmed' || writeCompleted(outcome)\n if (confirmed && this.staged.get(field) === draft) this.staged.delete(field)\n }\n if ((outcome.config === 'confirmed' || writeCompleted(outcome)) && this.visibleModelsDraft === submittedVisible) this.visibleModelsDraft = undefined\n this.publish()\n return outcome\n }\n\n /** Stage the visible-model allowlist (multi-select). */\n editVisibleModels(models: string[]): void {\n this.visibleModelsDraft = [...models]\n this.failed = false\n this.saveResult = undefined\n this.publish()\n }\n\n /** Stage \"show all models\" (clears the allowlist). */\n clearVisibleModels(): void {\n this.visibleModelsDraft = []\n this.failed = false\n this.saveResult = undefined\n this.publish()\n }\n\n // --- Immediate account management ---\n\n renameAccount(ref: string, label: string): Promise<boolean> {\n return this.runAccountOp('rename', { kind: 'rename', ref, label: label.trim() })\n }\n\n /** 配置移除确认后才清理凭据,失败记录留在宿主清理队列。 */\n removeAccount(ref: string): Promise<boolean> {\n return this.runAccountOp('remove', { kind: 'remove', ref })\n }\n\n retryCredentialCleanup(ref: string): Promise<boolean> {\n return this.runAccountOp('remove', { kind: 'cleanup', ref })\n }\n\n private cleanupRefs(): string[] {\n const raw = this.sectionValue('credentialCleanupRefs')\n return Array.isArray(raw) ? [...new Set(raw.filter((ref): ref is string => typeof ref === 'string' && ref !== ''))] : []\n }\n\n setAccountKey(target: string, key: string): Promise<boolean> {\n return this.runAccountOp('key', { kind: 'key', target, value: key.trim() })\n }\n\n clearAccountKey(target: string): Promise<boolean> {\n return this.runAccountOp('key', { kind: 'key', target })\n }\n\n setActiveAccount(id: string): Promise<boolean> {\n return this.runAccountOp('active', { kind: 'active', id })\n }\n\n setAccountModels(target: string, models: readonly string[]): Promise<boolean> {\n return this.runAccountOp('models', { kind: 'models', target, models })\n }\n\n /** 即时入口与保存共享写入过程,只在这里维护页面忙碌投影。 */\n private async runAccountOp(op: AccountOperation, intent: SettingsWriteIntent): Promise<boolean> {\n this.accountPending += 1\n this.accountFailed = undefined\n this.accountResult = undefined\n const completion = this.writer.submit(intent)\n this.publish()\n const outcome = await completion\n this.accountPending -= 1\n if (this.disposed) return false\n const ok = writeCompleted(outcome)\n this.accountResult = outcome\n this.accountFailed = ok ? undefined : op\n this.publish()\n return ok\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 private plan(): Array<{ field: string; change: SettingsPathOp | string | undefined }> {\n const plan: Array<{ field: string; change: SettingsPathOp | string | undefined }> = []\n for (const [field, staged] of this.staged) {\n if (field === 'apiKey') {\n const value = staged.text.trim()\n if (value !== '') plan.push({ field, change: value })\n continue\n }\n const spec = this.spec(field)\n if (staged.clear) {\n if (this.stored(field)) plan.push({ field, change: { op: 'unset', path: [field] } })\n continue\n }\n if (staged.text === spec.format(this.sectionValue(field))) continue\n const parsed = spec.parse(staged.text)\n const change: SettingsPathOp | undefined = parsed.kind === 'invalid' ? undefined\n : parsed.kind === 'clear' ? { op: 'unset', path: [field] } : { op: 'set', path: [field], value: parsed.value }\n plan.push({ field, change })\n }\n return plan\n }\n\n /**\n * Fetch the model catalog through the Host Remote. Runs once at construction;\n * call again (e.g. from the client entry once the Remote mount lands) to\n * (re)try — a later success clears a prior failure flag, so the editors\n * recover 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 // Defensive per-entry shaping: the Remote result is untrusted at the\n // boundary, and an older Host predates the tier field.\n const shaped: CatalogModelOption[] = []\n for (const model of response.value.models) {\n if (typeof model !== 'object' || model === null) continue\n const entry = model as unknown as Record<string, unknown>\n if (typeof entry.id !== 'string' || typeof entry.name !== 'string') continue\n shaped.push({\n id: entry.id,\n name: entry.name,\n ...(typeof entry.tier === 'string' ? { tier: entry.tier } : {}),\n ...(typeof entry.allowance === 'number' && Number.isFinite(entry.allowance)\n ? { allowance: entry.allowance }\n : {}),\n })\n }\n this.catalogModels = shaped\n this.catalogFailed = false\n } else {\n this.catalogFailed = true\n }\n }, () => {\n this.catalogFailed = true\n }).then(() => this.publish())\n }\n\n // --- Stored accounts and rules ---\n\n /** The raw `accounts` array of the stored section, verbatim. */\n private rawStoredAccounts(): Array<Record<string, unknown>> {\n const raw = this.scope.getSnapshot().value?.accounts\n if (!Array.isArray(raw)) return []\n return raw.filter(\n (entry): entry is Record<string, unknown> =>\n typeof entry === 'object' && entry !== null && !Array.isArray(entry),\n )\n }\n\n /**\n * The stored extra accounts this page can address: the rows carrying a\n * credential reference. Entries it cannot name (a composition entry with a\n * literal `apiKey`, or an unknown shape) are never dropped — every list\n * write starts from {@link rawStoredAccounts} and copies them verbatim,\n * because the settings layer replaces the whole array.\n */\n private storedExtras(): Array<{ label: string; ref: string }> {\n const out: Array<{ label: string; ref: string }> = []\n const seen = new Set<string>()\n for (const record of this.rawStoredAccounts()) {\n const ref = record.apiKeyEnv\n if (typeof ref !== 'string' || ref === '' || seen.has(ref)) continue\n seen.add(ref)\n const label = record.label\n out.push({ label: typeof label === 'string' && label !== '' ? label : ref, ref })\n }\n return out\n }\n\n private effectiveAccounts(): AccountItemState[] {\n return this.storedExtras().map((extra) => ({\n id: extra.ref,\n ref: extra.ref,\n label: extra.label,\n configured: this.writer.credential(extra.ref)?.configured ?? false,\n credentialKnown: this.writer.credential(extra.ref) !== undefined,\n writable: this.writer.credential(extra.ref)?.writable ?? true,\n }))\n }\n\n /** The stored routing rules from the settings section (`modelAccountRules`). */\n private storedRules(): StoredRule[] {\n const raw = this.scope.getSnapshot().value?.modelAccountRules\n if (!Array.isArray(raw)) return []\n const out: StoredRule[] = []\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 models = Array.isArray(record.models)\n ? record.models.filter((m): m is string => typeof m === 'string' && m !== '')\n : []\n if (models.length === 0) continue\n out.push({\n models,\n account: typeof record.account === 'string' && record.account !== '' ? record.account : 'default',\n })\n }\n return out\n }\n\n /** 原始白名单;空列表延续现有的显示全部语义。 */\n private storedAllowlist(): string[] {\n const raw = this.scope.getSnapshot().value?.visibleModels\n if (!Array.isArray(raw)) return []\n return raw.filter((m): m is string => typeof m === 'string' && m !== '')\n }\n\n private storedShowsAll(): boolean {\n return this.storedAllowlist().length === 0\n && !Object.values(readVisibility(this.scope.getSnapshot().value?.modelVisibility)).includes(false)\n }\n\n /** 目录、白名单与显式显示的旧模型一起投影,目录失败不删除旧选择。 */\n private storedVisibleModels(): string[] {\n const list = this.storedAllowlist()\n const flags = readVisibility(this.scope.getSnapshot().value?.modelVisibility)\n const ids = [...new Set([...list, ...this.catalogModels.map((model) => model.id), ...Object.keys(flags)])]\n return ids.filter((id) => modelIsVisible(id, list, flags))\n }\n\n private effectiveVisibleModels(): string[] {\n if (this.visibleModelsDraft === undefined) return this.storedVisibleModels()\n return this.visibleModelsDraft.length === 0\n ? this.catalogModels.map((model) => model.id)\n : this.visibleModelsDraft\n }\n\n private visibleModelsDirty(): boolean {\n if (this.visibleModelsDraft === undefined) return false\n if (this.visibleModelsDraft.length === 0) return !this.storedShowsAll()\n return this.storedShowsAll() || !sameModels(this.visibleModelsDraft, this.storedVisibleModels())\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of this.listeners) listener()\n }\n}\n","/** Shared, dependency-free formatting for Host commands and browser surfaces. */\n\nexport function formatMoney(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\nexport function formatMoneyExact(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\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/** The input is already in percent units; callers add the percent sign. */\nexport function formatSuccessRate(value: number): string {\n return String(Number(value.toFixed(2)))\n}\n\n/** One window's fill ratio in [0, 1]; zero 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/** Local date-time, with the empty state chosen by the caller. */\nexport function formatResetAt(ms: number): string {\n return ms <= 0 ? '' : new Date(ms).toLocaleString()\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 * @module dsh-commandcode-provider/client/usage\n */\n\nimport type { CommandCodeAccountsReport, CommandCodeCatalog, CommandCodePriceTable } from '../usage-wire.ts'\nimport type { CommandCodeLoginStatus } from '../login-wire.ts'\nimport type { EnrollmentRemote } from './enrollment.ts'\nimport type { AnalyticsRemote } from './analytics.ts'\nimport type { AnalyticsQuery, AnalyticsReport } from '../analytics-wire.ts'\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nimport { readableErrorText } from './error-text.ts'\nexport { formatMoney, formatMoneyExact, formatTokensCompact, formatSuccessRate, windowRatio, formatResetAt } from '../display-format.ts'\n\n/**\n * Merge the plugin's Remote endpoints into the harness's typed client Remote\n * surface, so `ctx.remote.commandcode.*()` is typed once each contribution is\n * mounted. The `commandcode` namespace member is declared exactly once here\n * (interface merging forbids duplicate members) and therefore carries the usage\n * report, the model catalog, the price table AND the login endpoints.\n */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/report': () => Promise<RemoteResult<CommandCodeAccountsReport>>\n 'commandcode/models': () => Promise<RemoteResult<CommandCodeCatalog>>\n 'commandcode/prices': () => Promise<RemoteResult<CommandCodePriceTable>>\n 'commandcode/analytics': (query: AnalyticsQuery) => Promise<RemoteResult<AnalyticsReport>>\n }\n interface TypertRemoteNamespaceMap {\n commandcode: Partial<EnrollmentRemote> & AnalyticsRemote & {\n report: () => Promise<RemoteResult<CommandCodeAccountsReport>>\n models: () => Promise<RemoteResult<CommandCodeCatalog>>\n /**\n * Optional because the Host half and this browser bundle can be a\n * cross-version pair: a Host older than the price table mounts no\n * `commandcode/prices` descriptor, so the member is genuinely absent at\n * runtime. The price controller reads a missing method as \"no table\"\n * (see `./prices.ts`) instead of throwing.\n */\n prices?: () => Promise<RemoteResult<CommandCodePriceTable>>\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 * Optional for the same cross-version reason as the namespace member above;\n * `CommandCodePricesController` reads the absence as a permanent \"no prices\"\n * state.\n */\n prices?(): Promise<\n | { ok: true; value: CommandCodePriceTable }\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: readableErrorText(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/** Host facts drive the usage card, including keys invisible to browser credentials. */\nexport function usageCardState(usage: UsagePageState) {\n const accounts = usage.report?.accounts ?? []\n return {\n loading: usage.status === 'loading',\n shouldRefresh: usage.status === 'idle',\n noKey: accounts.length > 0 && !accounts.some(account => account.configured),\n }\n}\n","/**\n * Browser controller for the model price table the composer's session-cost\n * figure depends on.\n *\n * The rates are vendored Host-side (`src/model-prices.ts`) and cross the\n * `commandcode/prices` Remote, so the browser never carries its own copy that\n * could drift from the snapshot, and a price update reaches an open page\n * without rebuilding the client bundle.\n *\n * @module dsh-commandcode-provider/client/prices\n */\n\nimport type { CommandCodePriceTable } from '../usage-wire.ts'\nimport { readableErrorText } from './error-text.ts'\n\n/** The narrow slice of the mounted Remote this controller calls. */\nexport interface PricesRemote {\n /**\n * Optional because the Host and the browser bundle can be a cross-version\n * pair: a Host half older than this feature serves no `commandcode/prices`\n * endpoint, and the controller must read that as \"no price table\" instead of\n * calling an undefined method.\n */\n prices?(): Promise<\n | { ok: true; value: CommandCodePriceTable }\n | { ok: false; error: { message: string; permanent?: boolean } }\n >\n}\n\n/** The price table's fetch lifecycle. */\nexport type PricesStatus =\n /** Never requested. */\n | 'idle'\n /** A fetch is in flight. */\n | 'loading'\n /** The table is loaded and cached for the page's lifetime. */\n | 'ready'\n /** The last fetch failed; `ensure()` may try again. */\n | 'error'\n\n/** The readout's price-table state face. */\nexport interface SessionCostPricesState {\n status: PricesStatus\n /** The cached table (only ever set once). */\n table: CommandCodePriceTable | undefined\n /** The last failure's message. */\n error: string | undefined\n}\n\nconst IDLE: SessionCostPricesState = { status: 'idle', table: undefined, error: undefined }\n\n/**\n * Timer seam for the bounded retry backoff, so a node test can drive the\n * schedule without waiting on it.\n */\nexport interface PriceRetryTimer {\n set(callback: () => void, ms: number): unknown\n clear(handle: unknown): void\n}\nconst RETRY_TIMER: PriceRetryTimer = {\n set(callback, ms) { const handle = setTimeout(callback, ms); handle.unref?.(); return handle },\n clear(handle) { clearTimeout(handle as ReturnType<typeof setTimeout>) },\n}\n\n/**\n * Cache over the `commandcode/prices` Remote, with a bounded transient-retry\n * budget (three retries at 1/2/4 s — bounded, not a poll). Public API mirrors\n * {@link CommandCodeUsageController}: `state()`, `subscribe` and `ensure()`;\n * `reload()` additionally drops the cache and restarts the budget when the\n * Host namespace rebinds. A MANUAL `ensure()` still fetches after the budget\n * is spent, and a PERMANENT failure — the Host serving no such endpoint — is\n * terminal for the binding until `reload()`.\n */\nexport class CommandCodePricesController {\n private readonly remote: PricesRemote\n private readonly listeners = new Set<() => void>()\n private current: SessionCostPricesState = IDLE\n private generation = 0\n private inFlight = false\n private disposed = false\n\n private retryHandle: unknown\n private attempts = 0\n private permanent = false\n private readonly timer: PriceRetryTimer\n\n constructor(remote: PricesRemote, timer: PriceRetryTimer = RETRY_TIMER) {\n this.timer = timer\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.clearRetry()\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 state face. */\n state(): SessionCostPricesState {\n return this.current\n }\n\n /**\n * Fetch the table unless it is already loaded, permanent, or in flight — and\n * unless a bounded retry already owns the next attempt. Only the client\n * entry calls this (on rebind and on a manual refresh), so a mounted readout\n * renders the current state instead of triggering a fetch of its own.\n */\n ensure(): void {\n if (this.disposed || this.permanent || this.inFlight || this.current.status === 'ready') return\n this.clearRetry()\n const call = this.remote.prices\n // An older Host half serves no price endpoint. That is a permanent\n // condition for this page, so it lands in the error state (the readout\n // stays hidden) rather than retrying on every mount.\n if (typeof call !== 'function') {\n this.permanent = true\n this.publish({ status: 'error', table: undefined, error: 'the Host serves no commandcode/prices endpoint' })\n return\n }\n const generation = this.generation\n this.inFlight = true\n this.attempts += 1\n this.publish({ status: 'loading', table: this.current.table, error: undefined })\n let request: ReturnType<NonNullable<PricesRemote['prices']>>\n try { request = call.call(this.remote) } catch (error) { request = Promise.reject(error) }\n void request.then((result) => {\n if (this.disposed || generation !== this.generation) return\n this.inFlight = false\n if (result.ok) {\n this.publish({ status: 'ready', table: result.value, error: undefined })\n return\n }\n this.permanent = result.error.permanent === true\n this.publish({ status: 'error', table: undefined, error: result.error.message })\n this.scheduleRetry()\n }, (error: unknown) => {\n if (this.disposed || generation !== this.generation) return\n this.inFlight = false\n this.publish({\n status: 'error',\n table: undefined,\n error: readableErrorText(error),\n })\n this.scheduleRetry()\n })\n }\n\n /** Rebinding a Host invalidates cached prices and restarts the bounded retry budget. */\n reload(): void {\n if (this.disposed) return\n this.generation += 1\n this.inFlight = false\n this.clearRetry()\n this.permanent = false\n this.attempts = 0\n this.current = IDLE\n this.ensure()\n }\n\n private clearRetry(): void {\n if (this.retryHandle !== undefined) this.timer.clear(this.retryHandle)\n this.retryHandle = undefined\n }\n\n private scheduleRetry(): void {\n if (this.disposed || this.permanent || this.attempts >= 4) return\n this.retryHandle = this.timer.set(() => { this.retryHandle = undefined; this.ensure() }, 1000 * 2 ** (this.attempts - 1))\n }\n\n private publish(next: SessionCostPricesState): void {\n this.current = next\n for (const listener of this.listeners) listener()\n }\n}\n","/** 收到宿主授权地址后才打开页面;浏览器拦截不应中断登录,界面始终保留手动链接。 */\nexport function openLoginPage(authUrl: string): void {\n if (typeof window === 'undefined') return\n try {\n // 授权页不持有设置页引用,也不接收设置页来源地址。\n // 使用 noopener 时成功打开也可能返回 null,因此不据此判断弹窗是否被拦截。\n window.open(authUrl, '_blank', 'noopener,noreferrer')\n } catch { /* 自动打开失败时仍可通过手动链接完成授权。 */ }\n}\n","/**\n * Browser controller for the settings page's login panel: `begin` asks the\n * Host to bind the callback server and returns the Studio URL, the controller\n * polls `loginStatus` while the attempt is live, and `cancel` tears it down.\n * The key itself never crosses to the browser — the Host validates and stores\n * it through the credentials seam.\n *\n * Transport-level failures (no mounted Remote, an older Host without the login\n * endpoints) land in the dedicated `unavailable` phase so the page can point\n * back at manual paste. Deliberately JSX-free, mirroring `./settings.ts` and\n * `./usage.ts`.\n *\n * @module dsh-commandcode-provider/client/login\n */\n\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nimport { readableErrorText } from './error-text.ts'\nimport { openLoginPage } from './login-page.ts'\nimport type { CommandCodeLoginFailureReason, CommandCodeLoginStatus } from '../login-wire.ts'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsCommandCodeKey } from './locales.ts'\n\n/** The endpoint-level Remote surface this controller calls. */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/loginBegin': (targetRef?: string) => 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(targetRef?: string): 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 saved extra account receiving this attempt, or undefined for default. */\n targetRef?: string\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/** Keep one account's login status out of every other account's row. */\nexport function loginStateForTarget(\n state: LoginPageState,\n targetRef: string | undefined,\n): { visible: LoginPageState; busyElsewhere: boolean } {\n if (state.targetRef === targetRef) return { visible: state, busyElsewhere: false }\n return {\n visible: { ...state, phase: 'idle', authUrl: undefined },\n busyElsewhere: state.phase === 'starting' || state.phase === 'waiting',\n }\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 targetRef: string | undefined\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 private openedPage = false\n\n constructor(remote: () => LoginRemote | undefined, pollMs = POLL_INTERVAL_MS, private readonly openPage = openLoginPage) {\n this.remote = remote\n this.pollMs = pollMs\n }\n\n /** Subscribe to state projections. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n state(): LoginPageState {\n return {\n phase: this.phase,\n ...(this.targetRef === undefined ? {} : { targetRef: this.targetRef }),\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(targetRef?: string): Promise<void> {\n if (this.disposed || this.phase === 'starting' || this.phase === 'waiting') return\n const generation = ++this.generation\n this.openedPage = false\n this.targetRef = targetRef\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(targetRef)\n } catch (error: unknown) {\n // A transport throw (gateway hiccup) reads the same as a rejected call.\n result = { ok: false, error: { message: readableErrorText(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 /** Poll until the attempt leaves `waiting` or a newer loop supersedes us. */\n private async poll(generation: number): Promise<void> {\n // `currentPhase` is a getter, read (not the field) so control-flow\n // narrowing across `await` 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 // 在宿主返回地址后打开,每次尝试仅执行一次,状态轮询不重复开页。\n if (status.authUrl && !this.openedPage) {\n this.openedPage = true\n this.openPage(status.authUrl)\n }\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// Hint copy for the login panel / card row, JSX-free so node tests drive it.\n\n/**\n * The per-reason copy for a failed attempt. Shared by the settings page's login\n * panel and the Models-page card's login row — the same reason can surface from\n * either.\n */\nexport function loginFailureCopy(\n reason: CommandCodeLoginFailureReason | undefined,\n t: Translate<SettingsCommandCodeKey>,\n): 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/** One login panel row's computed hint: text, class stem, and optional title. */\nexport interface LoginHint {\n text: string\n className: string\n /** Tooltip shown when the row carries secondary failure detail. */\n title: string | undefined\n}\n\n/**\n * The hint text + class for one login panel state, shared by the settings\n * page's login panel and the Models-page card's login row so both surfaces\n * can never drift apart. Pure: no timers, no state.\n */\nexport function loginHint(\n state: LoginPageState,\n t: Translate<SettingsCommandCodeKey>,\n): LoginHint {\n if (state.phase === 'starting' || state.phase === 'waiting') {\n return {\n text: t(state.phase === 'starting' ? 'loginStarting' : 'loginWaiting'),\n className: 'cc-hint',\n title: undefined,\n }\n }\n if (state.phase === 'success') {\n const keyName = state.keyName !== undefined && state.keyName !== '' ? ` · ${state.keyName}` : ''\n return {\n text: `${t('loginSuccess')} ${state.userName ?? ''}${keyName}`.trim(),\n className: 'cc-loginDone',\n title: undefined,\n }\n }\n if (state.phase === 'failed') {\n return {\n text: loginFailureCopy(state.reason, t),\n className: 'cc-loginError',\n title: state.message,\n }\n }\n if (state.phase === 'unavailable') {\n return {\n text: `${t('loginUnavailable')} ${state.message ?? ''}`.trim(),\n className: 'cc-loginError',\n title: undefined,\n }\n }\n return { text: t('loginHintIdle'), className: 'cc-hint', title: undefined }\n}\n","/**\n * Shared boundary-validation and Remote-descriptor plumbing for the plugin's\n * hand-rolled Typert wire contracts (`commandcode/report`, `commandcode/models`,\n * `commandcode/prices`, `commandcode/login*`).\n *\n * Every Remote this plugin serves crosses the Typert Gateway with a strict\n * result schema: the Host half registers a descriptor against a Cordis service\n * (`src/usage-remote.ts`) and the browser half mounts the matching contribution\n * on `ctx.remote` (`src/client/index.ts`). This module is dependency-free so\n * the client bundle can inline it, and it holds the schema helpers and\n * descriptor boilerplate the wire files used to duplicate.\n *\n * @module dsh-commandcode-provider/wire-shared\n */\nimport type { InvocationDescriptor, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\n\n/** The npm package identity every contribution and descriptor claims. */\nexport const REMOTE_PACKAGE = '@mars-sea/dsh-commandcode-provider'\n\n/** The Cordis service key the Gateway resolves every Command Code Remote from. */\nexport const REMOTE_SERVICE = 'commandcodeUsage'\n\n/** The wire namespace all Command Code endpoints share. */\nexport const REMOTE_NAMESPACE = 'commandcode'\n\n/** The read/validate helpers one boundary codec needs. */\nexport interface BoundaryValidator {\n /** Reject one boundary value with a field-naming error. */\n reject(field: string): never\n /** Narrow an unknown value to a plain record, or reject. */\n record(value: unknown, field: string): Record<string, unknown>\n /** Read one required string field (`field` is the dotted error label). */\n stringField(source: Record<string, unknown>, key: string, field: string): string\n /** Read one required finite number field (`field` is the dotted error label). */\n numberField(source: Record<string, unknown>, key: string, field: string): number\n /** Read one required boolean field (`field` is the dotted error label). */\n booleanField(source: Record<string, unknown>, key: string, field: string): boolean\n}\n\n/**\n * Build the validator helpers one endpoint uses. `prefix` names the endpoint\n * in the rejection message (e.g. `commandcode/report result:`), so each wire\n * file keeps its own diagnostic phrasing while sharing the helper bodies.\n *\n * The helpers return the reject call directly in the failure branch: since\n * `reject` is typed `never`, the ternary's union collapses to the success type\n * without relying on TypeScript's control-flow analysis of a never-returning\n * call (which only recognizes function declarations, not the destructured\n * arrow `reject` callers receive from this factory). Callers that need the\n * narrowing in an `if` must therefore assign inside the positive branch.\n */\nexport function makeBoundaryValidator(prefix: string): BoundaryValidator {\n const reject = (field: string): never => {\n throw new TypeError(`${prefix} invalid ${field}`)\n }\n const record = (value: unknown, field: string): Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : reject(field)\n const stringField = (source: Record<string, unknown>, key: string, field: string): string =>\n typeof source[key] === 'string' ? source[key] as string : reject(field)\n const numberField = (source: Record<string, unknown>, key: string, field: string): number =>\n typeof source[key] === 'number' && Number.isFinite(source[key] as number)\n ? source[key] as number\n : reject(field)\n const booleanField = (source: Record<string, unknown>, key: string, field: string): boolean =>\n typeof source[key] === 'boolean' ? source[key] as boolean : reject(field)\n return { reject, record, stringField, numberField, booleanField }\n}\n\n/**\n * One strict result codec: `mode: 'strict'` carries the LAZY schema factory\n * (`create()`) the registry requires and the Gateway validates with\n * (`codec.create().parse`). There is NO `schema` member — issue #49.\n */\ninterface StrictCodec<Output> {\n readonly mode: 'strict'\n readonly typeSymbol: string\n readonly create: () => TypertSchema<Output>\n}\n\n/** Use the same strict-codec shape for invocation parameters and results. */\nexport function makeStrictCodec<Output>(typeSymbol: string, schema: TypertSchema<Output>): StrictCodec<Output> {\n return { mode: 'strict', typeSymbol, create: () => schema }\n}\n\n/**\n * Build one strict invocation descriptor. Every Command Code Remote shares the\n * `commandcode` namespace, the `commandcodeUsage` service, and a strict result\n * — only the endpoint, method, result type symbol, and schema differ.\n */\nexport function makeRemoteDescriptor<Output>(\n endpoint: string,\n method: string,\n typeSymbol: string,\n schema: TypertSchema<Output>,\n): InvocationDescriptor {\n return {\n id: `${REMOTE_PACKAGE}#${endpoint}`,\n service: REMOTE_SERVICE,\n namespace: REMOTE_NAMESPACE,\n method,\n invocation: { kind: 'direct' },\n parameters: [],\n result: makeStrictCodec(typeSymbol, schema),\n }\n}\n","/**\n * Wire contracts for the Command Code Remotes the browser half mounts: the\n * account-usage report (`commandcode/report`), the model catalog\n * (`commandcode/models`) and the price table (`commandcode/prices`).\n *\n * The browser never holds the API key, so every one of these is produced\n * Host-side: the Host half registers a strict invocation descriptor against a\n * Cordis service (`src/usage-remote.ts`) and the browser half mounts the\n * matching contribution on `ctx.remote` (`src/client/index.ts`). This module\n * is the single source both halves share — the hand-rolled result validators\n * and the exact descriptor objects, so neither half can drift. It is\n * dependency-free because the client bundle inlines it.\n *\n * @module dsh-commandcode-provider/usage-wire\n */\n\nimport type { CommandCodeCredits, CommandCodeUsageReport, UsageBlockReason } from './adapter.ts'\n\nexport type { CommandCodeUsageReport, UsageBlockReason }\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\nimport {\n makeBoundaryValidator,\n makeRemoteDescriptor,\n REMOTE_PACKAGE,\n} from './wire-shared.ts'\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 = REMOTE_PACKAGE\n\n/** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */\nexport const USAGE_REPORT_ENDPOINT = 'commandcode/report'\n\n/**\n * The shared read/validate helpers for the usage report endpoint, prefixed\n * so rejection messages name the offending boundary.\n */\nconst { reject, record, stringField, numberField, booleanField } =\n makeBoundaryValidator('commandcode/report result:')\n\n/**\n * Parse one quota window, or undefined when the frame carries no such window.\n *\n * The distinction is load-bearing at this boundary: an ABSENT window means the\n * billing endpoint reported none (an unlimited plan), while a present block with\n * `cap: 0` means uncapped spend that was really reported. Collapsing the two\n * would draw a zeroed quota row for an account that has no such limit.\n */\nfunction windowLimit(\n value: unknown,\n field: string,\n): { used: number; cap: number; exceeded: boolean; resetAt: number } | undefined {\n if (value === undefined) return undefined\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 === 'invalid-response' || blocked === 'network') {\n report.blocked = blocked\n } else {\n reject('blocked')\n }\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 const parsed: CommandCodeCredits = {\n monthlyCredits: numberField(credits, 'monthlyCredits', 'credits.monthlyCredits'),\n purchasedCredits: numberField(credits, 'purchasedCredits', 'credits.purchasedCredits'),\n freeCredits: numberField(credits, 'freeCredits', 'credits.freeCredits'),\n }\n // OPTIONAL on the wire: an explicit `false` means the endpoint omitted the\n // balance, which cannot be told from a real zero — the panel keeps the\n // figure off the dashboard rather than drawing a consumed quota. An absent\n // flag (an older Host) stays unset and reads as \"assume reported\", so a\n // real balance is not lost cross-version. A PRESENT value must still be a\n // boolean, so a malformed frame is rejected here rather than coerced.\n if (credits.monthlyReported !== undefined) {\n parsed.monthlyReported = booleanField(credits, 'monthlyReported', 'credits.monthlyReported')\n }\n for (const flag of ['purchasedReported', 'freeReported'] as const) {\n if (credits[flag] !== undefined) parsed[flag] = booleanField(credits, flag, `credits.${flag}`)\n }\n // Absent means the endpoint reported no such window: the parsers return\n // undefined for an absent block, and an optional member is only set when\n // it was really there.\n const fiveHour = windowLimit(credits.fiveHour, 'credits.fiveHour')\n const weekly = windowLimit(credits.weekly, 'credits.weekly')\n if (fiveHour !== undefined) parsed.fiveHour = fiveHour\n if (weekly !== undefined) parsed.weekly = weekly\n report.credits = parsed\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)) {\n return { accounts: accounts.map(parseAccountUsage) }\n }\n return reject('accounts')\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 makeRemoteDescriptor<CommandCodeAccountsReport>(\n USAGE_REPORT_ENDPOINT,\n 'report',\n `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`,\n usageReportSchema,\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 // Every Host contribution must carry its reflection model. This hand-written\n // Remote deliberately has no generated reflection exports, so use the\n // official empty-model form rather than a cast that would leave registry\n // 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 model editors offer. */\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 * Minimum plan-tier key for this model (a `KNOWN_PLANS` value: `go`,\n * `goat`, `pro`, `provider`, `max`), or undefined for models outside the\n * snapshot. The settings page groups the model-editor dropdowns under\n * tier headings from this — the browser cannot import the Host's\n * capability snapshot, so the Host stamps it per entry.\n */\n tier?: string\n /**\n * Per-model MONTHLY allowance in USD: how much of the plan's monthly credit\n * pool this one model may draw, already resolved by the Host against the\n * account pool's highest plan (the pricing page publishes an allowance for\n * Go, GOAT and Pro). Undefined when that plan has no published allowance\n * (Go, Provider, Max, Ultra) or when billing could not be read — the browser\n * shows nothing rather than guessing a neighbouring tier's figure.\n *\n * Deliberately a plain number and not the `{ go, goat, pro }` map: the bracket is\n * a Host decision that already depends on facts the browser does not hold, and\n * shipping both figures would invite a second, divergent rule here. Note this\n * is dollars per MONTH, unlike every rate in `CommandCodePriceTable`.\n */\n allowance?: number\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/**\n * The shared read/validate helpers for the model-catalog endpoint — a\n * separate instance so catalog boundary errors name `commandcode/models`,\n * not the report endpoint.\n */\nconst {\n record: catalogRecord,\n stringField: catalogString,\n numberField: catalogNumber,\n} = makeBoundaryValidator('commandcode/models result:')\n\n/** Parse one untrusted boundary value into a {@link CommandCodeCatalogModel}. */\nfunction parseCatalogModel(value: unknown): CommandCodeCatalogModel {\n const source = catalogRecord(value, 'model')\n const model: CommandCodeCatalogModel = {\n id: catalogString(source, 'id', 'model.id'),\n name: catalogString(source, 'name', 'model.name'),\n }\n // Tier is optional on the wire (older Hosts predate it); a present\n // non-string is a contract violation, not a silent drop.\n if (source.tier !== undefined) {\n model.tier = catalogString(source, 'tier', 'model.tier')\n }\n // Same rule for the allowance: an older Host simply omits it, but a Host that\n // sends a non-number has broken the contract.\n if (source.allowance !== undefined) {\n model.allowance = catalogNumber(source, 'allowance', 'model.allowance')\n }\n return model\n}\n\n/** Parse the wire result into a {@link CommandCodeCatalog}. */\nfunction parseCatalog(value: unknown): CommandCodeCatalog {\n const source = catalogRecord(value, 'result')\n const models = source.models\n if (Array.isArray(models)) {\n return { models: models.map(parseCatalogModel) }\n }\n throw new TypeError('commandcode/models result: invalid models')\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 makeRemoteDescriptor<CommandCodeCatalog>(\n MODELS_ENDPOINT,\n 'models',\n `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`,\n modelsSchema,\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// ---------------------------------------------------------------------------\n// Model price table Remote (`commandcode/prices`)\n// ---------------------------------------------------------------------------\n\n/**\n * One model's per-token rates, in USD per 1,000,000 tokens — the unit the\n * official pricing page publishes in.\n */\nexport interface CommandCodeModelRates {\n /** Uncached (billed) input tokens. */\n inputCost: number\n /** Completion tokens. */\n outputCost: number\n /** Input tokens served from the provider's cache. */\n cacheReadCost: number\n /**\n * Input tokens written into the provider's cache. Present for a minority of\n * models — the page publishes no cache-write rate for the rest, whose\n * cache-write tokens are therefore UNPRICED. Do not substitute a multiple of\n * the input rate for a missing value.\n */\n cacheWriteCost?: number\n}\n\n/** One whole-request context band; maxContext is inclusive, absent on the last band. */\nexport interface CommandCodeContextTier extends CommandCodeModelRates {\n maxContext?: number\n}\n\n/** One model's rates plus the peak-hour override for time-of-day models. */\nexport interface CommandCodeModelPrice extends CommandCodeModelRates {\n /**\n * Lookup key: the catalog model id when a catalog model maps to this row,\n * otherwise the pricing page's own slug. A session reports catalog ids, so\n * this is the primary key the browser looks up by.\n */\n id: string\n /** The pricing page's slug for this row — the secondary lookup key. */\n slug: string\n /**\n * Rates charged inside the peak windows. The row's own top-level rates are\n * the off-peak rates, so a row WITH this block is time-of-day priced and a\n * row without it is flat-priced.\n */\n peak?: CommandCodeModelRates\n contextTiers?: CommandCodeContextTier[]\n /**\n * Whether the model costs nothing on every plan right now (a free deal or a\n * `:free` catalog variant). Served explicitly at zero rates so a surface can\n * say \"free\" rather than showing nothing.\n */\n free?: boolean\n}\n\n/** The price-table Remote result: every known model's rates. */\nexport interface CommandCodePriceTable {\n /**\n * Every priced model, keyed by {@link CommandCodeModelPrice.id} (catalog id\n * first, pricing slug as the fallback) and carrying its slug as a second\n * lookup key. A model absent from this list has no known price and must\n * render no cost at all rather than a guess.\n */\n models: CommandCodeModelPrice[]\n /**\n * Peak-pricing windows as `[startHour, endHour)` in UTC, end-exclusive,\n * applying Monday–Friday only. Shipped with the table so the browser prices\n * against the Host snapshot's schedule instead of restating it.\n */\n peakHours: Array<[number, number]>\n}\n\n/** Canonical `<namespace>/<method>` endpoint of the price-table Remote. */\nexport const PRICES_ENDPOINT = 'commandcode/prices'\n\n/**\n * The shared read/validate helpers for the price-table endpoint — its own\n * instance so price boundary errors name `commandcode/prices`.\n */\nconst {\n reject: priceReject,\n record: priceRecord,\n stringField: priceString,\n numberField: priceNumber,\n booleanField: priceBoolean,\n} = makeBoundaryValidator('commandcode/prices result:')\n\n/** Parse one rate block (`rates`, or a model's `peak` override). */\nfunction parseRates(source: Record<string, unknown>, field: string): CommandCodeModelRates {\n const rates: CommandCodeModelRates = {\n inputCost: priceNumber(source, 'inputCost', `${field}.inputCost`),\n outputCost: priceNumber(source, 'outputCost', `${field}.outputCost`),\n cacheReadCost: priceNumber(source, 'cacheReadCost', `${field}.cacheReadCost`),\n }\n // Optional on the wire: a present non-number is a contract violation rather\n // than a silent zero (only a minority of models publish a cache-write rate).\n if (source.cacheWriteCost !== undefined) {\n rates.cacheWriteCost = priceNumber(source, 'cacheWriteCost', `${field}.cacheWriteCost`)\n }\n return rates\n}\n\n/** Parse one untrusted boundary value into a {@link CommandCodeModelPrice}. */\nfunction parseModelPrice(value: unknown): CommandCodeModelPrice {\n const source = priceRecord(value, 'model')\n const price: CommandCodeModelPrice = {\n id: priceString(source, 'id', 'model.id'),\n slug: priceString(source, 'slug', 'model.slug'),\n ...parseRates(source, 'model'),\n }\n if (source.peak !== undefined) price.peak = parseRates(priceRecord(source.peak, 'model.peak'), 'model.peak')\n if (source.contextTiers !== undefined) {\n if (!Array.isArray(source.contextTiers) || source.contextTiers.length === 0) priceReject('contextTiers')\n let previous = 0\n price.contextTiers = (source.contextTiers as unknown[]).map((value, index, tiers) => {\n const tier = priceRecord(value, 'contextTier')\n const out: CommandCodeContextTier = parseRates(tier, 'contextTier')\n if (tier.maxContext !== undefined) {\n const max = priceNumber(tier, 'maxContext', 'contextTier.maxContext')\n if (!Number.isSafeInteger(max) || max <= previous || index === tiers.length - 1) priceReject('contextTier.maxContext')\n previous = max\n out.maxContext = max\n } else if (index !== tiers.length - 1) priceReject('contextTier.maxContext')\n return out\n })\n }\n if (source.free !== undefined) price.free = priceBoolean(source, 'free', 'model.free')\n return price\n}\n\n/** Parse the wire result into a {@link CommandCodePriceTable}. */\nfunction parsePriceTable(value: unknown): CommandCodePriceTable {\n const source = priceRecord(value, 'result')\n const models = source.models\n if (!Array.isArray(models)) priceReject('models')\n const peakHours = source.peakHours\n if (!Array.isArray(peakHours)) priceReject('peakHours')\n return {\n models: (models as unknown[]).map(parseModelPrice),\n peakHours: (peakHours as unknown[]).map((window) => {\n if (!Array.isArray(window) || window.length !== 2) priceReject('peakHours[]')\n const [start, end] = window as [unknown, unknown]\n if (typeof start !== 'number' || typeof end !== 'number') priceReject('peakHours[]')\n return [start, end] as [number, number]\n }),\n }\n}\n\n/** The strict result codec for the price-table Remote. */\nexport const pricesSchema: TypertSchema<CommandCodePriceTable> = {\n parse: parsePriceTable,\n}\n\n/**\n * The price-table invocation descriptor, sharing the same `commandcodeUsage`\n * service and `commandcode` namespace as the report and catalog endpoints.\n */\nexport const PRICES_DESCRIPTOR: InvocationDescriptor =\n makeRemoteDescriptor<CommandCodePriceTable>(\n PRICES_ENDPOINT,\n 'prices',\n `${USAGE_REMOTE_PACKAGE}#CommandCodePriceTable`,\n pricesSchema,\n )\n\n/** The Client-face contribution for the price-table endpoint. */\nexport const PRICES_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [PRICES_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 instead of pasting an API key. The loopback server must live\n * in the Host half — it binds a local port and receives the key — so the page\n * drives it through the 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 {\n makeBoundaryValidator,\n makeRemoteDescriptor,\n makeStrictCodec,\n REMOTE_PACKAGE,\n} from './wire-shared.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/** The shared read/validate helpers, prefixed with the login endpoint so\n * rejection messages name the offending boundary. */\nconst { reject, record, stringField } =\n makeBoundaryValidator('commandcode/login result:')\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 const source = record(value, 'status')\n const state = source.state\n if (state === 'idle' || state === 'waiting' || state === 'success' || state === 'failed') {\n const status: CommandCodeLoginStatus = { state }\n if (source.authUrl !== undefined) {\n status.authUrl = stringField(source, 'authUrl', 'authUrl')\n }\n if (source.userName !== undefined) {\n status.userName = stringField(source, 'userName', 'userName')\n }\n if (source.keyName !== undefined) {\n status.keyName = stringField(source, 'keyName', 'keyName')\n }\n if (source.reason !== undefined) {\n const reason = source.reason\n if (typeof reason === 'string' && REASONS.includes(reason as CommandCodeLoginFailureReason)) {\n status.reason = reason as CommandCodeLoginFailureReason\n } else {\n reject('reason')\n }\n }\n if (source.message !== undefined) {\n status.message = stringField(source, 'message', 'message')\n }\n return status\n }\n return reject('state')\n}\n\n/** The strict result codec shared by all three login endpoints. */\nexport const loginStatusSchema: TypertSchema<CommandCodeLoginStatus> = {\n parse: parseLoginStatus,\n}\n\n/** Optional account target; the Host still checks it against saved slots. */\nconst loginTargetSchema: TypertSchema<string | undefined> = {\n parse(value: unknown): string | undefined {\n if (value === undefined || typeof value === 'string') return value\n return reject('targetRef')\n },\n}\n\n/** Build one login invocation descriptor. Only begin accepts an account ref. */\nfunction loginDescriptor(endpoint: string, method: string): InvocationDescriptor {\n const descriptor = makeRemoteDescriptor<CommandCodeLoginStatus>(\n endpoint,\n method,\n `${REMOTE_PACKAGE}#CommandCodeLoginStatus`,\n loginStatusSchema,\n )\n return method === 'loginBegin'\n ? {\n ...descriptor,\n parameters: [{\n name: 'targetRef', wire: 'targetRef', source: 'json',\n codec: makeStrictCodec(`${REMOTE_PACKAGE}#CommandCodeLoginTargetRef`, loginTargetSchema),\n acceptsUndefined: true,\n }],\n }\n : descriptor\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: 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: REMOTE_PACKAGE,\n descriptors: LOGIN_DESCRIPTORS,\n}\n","/** 账号开通的双方使用契约。状态和恢复记录不携带密钥,密钥只出现在手动开通输入。 */\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\nimport { makeBoundaryValidator, makeRemoteDescriptor, makeStrictCodec, REMOTE_PACKAGE } from './wire-shared.ts'\n\nexport interface EnrollmentInput {\n id: string\n pageId: string\n mode: 'browser' | 'manual'\n label: string\n /** 用户未填写名称时,允许使用浏览器登录返回的账号名。 */\n automaticName: boolean\n key?: string\n}\nexport type EnrollmentPhase = 'creating' | 'waiting' | 'writing' | 'naming' | 'finished' | 'cancelling' | 'cancelled' | 'failed' | 'cleanup-needed'\nexport interface EnrollmentState {\n id: string\n ref: string\n phase: EnrollmentPhase\n message: string\n authUrl?: string\n suggestedName?: string\n}\n/** 配置中的恢复日志:先登记,再写凭据;只保留引用与阶段,不保留密钥或连接身份。 */\nexport interface EnrollmentRecord {\n id: string\n ref: string\n phase: 'pending' | 'naming' | 'cleanup'\n label: string\n}\nconst guard = makeBoundaryValidator('commandcode/enrollment')\nconst phases: readonly EnrollmentPhase[] = ['creating', 'waiting', 'writing', 'naming', 'finished', 'cancelling', 'cancelled', 'failed', 'cleanup-needed']\nexport function parseEnrollmentState(value: unknown): EnrollmentState {\n const source = guard.record(value, 'state')\n const phase = source.phase\n if (!phases.includes(phase as EnrollmentPhase)) return guard.reject('phase')\n const state: EnrollmentState = {\n id: guard.stringField(source, 'id', 'id'), ref: guard.stringField(source, 'ref', 'ref'),\n phase: phase as EnrollmentPhase, message: guard.stringField(source, 'message', 'message'),\n }\n for (const field of ['authUrl', 'suggestedName'] as const) {\n if (source[field] !== undefined) state[field] = guard.stringField(source, field, field)\n }\n return state\n}\nexport function parseEnrollmentInput(value: unknown): EnrollmentInput {\n const source = guard.record(value, 'input')\n const id = guard.stringField(source, 'id', 'id')\n if (!/^[a-zA-Z0-9-]{16,80}$/.test(id)) return guard.reject('id')\n if (source.mode !== 'browser' && source.mode !== 'manual') return guard.reject('mode')\n const input: EnrollmentInput = {\n id, pageId: parsePage(source).pageId, mode: source.mode, label: guard.stringField(source, 'label', 'label').trim(),\n automaticName: guard.booleanField(source, 'automaticName', 'automaticName'),\n }\n if (!input.label || input.label.length > 200) return guard.reject('label')\n if (input.mode === 'manual') {\n input.key = guard.stringField(source, 'key', 'key').trim()\n if (!input.key) return guard.reject('key')\n } else if (source.key !== undefined) return guard.reject('key')\n return input\n}\nexport interface EnrollmentPage { pageId: string }\nfunction parsePage(value: unknown): EnrollmentPage {\n const source = guard.record(value, 'page')\n const pageId = guard.stringField(source, 'pageId', 'pageId')\n if (!/^[a-zA-Z0-9-]{16,80}$/.test(pageId)) return guard.reject('pageId')\n return { pageId }\n}\nexport interface EnrollmentAction extends EnrollmentPage { id: string; name?: string }\nconst actionSchema: TypertSchema<EnrollmentAction> = {\n parse(value) {\n const source = guard.record(value, 'action')\n const action: EnrollmentAction = { id: guard.stringField(source, 'id', 'id'), ...parsePage(source) }\n if (!/^[a-zA-Z0-9-]{16,80}$/.test(action.id)) return guard.reject('id')\n if (source.name !== undefined) action.name = guard.stringField(source, 'name', 'name').trim()\n if (action.name !== undefined && (!action.name || action.name.length > 200)) return guard.reject('name')\n return action\n },\n}\nconst stateSchema = { parse: parseEnrollmentState }\nconst listSchema: TypertSchema<EnrollmentState[]> = {\n parse(value) { return Array.isArray(value) ? value.map(parseEnrollmentState) : guard.reject('list') },\n}\nexport const ENROLLMENT_DESCRIPTORS: readonly InvocationDescriptor[] = [\n ...['enrollmentBegin', 'enrollmentStatus', 'enrollmentCancel', 'enrollmentName', 'enrollmentRetry'].map((method) => ({\n ...makeRemoteDescriptor(`commandcode/${method}`, method, `${REMOTE_PACKAGE}#EnrollmentState`, stateSchema),\n parameters: [{ name: 'input', wire: 'input', source: 'json' as const,\n codec: makeStrictCodec(`${REMOTE_PACKAGE}#${method}Input`, method === 'enrollmentBegin' ? { parse: parseEnrollmentInput } : actionSchema) }],\n })),\n { ...makeRemoteDescriptor('commandcode/enrollmentPending', 'enrollmentPending', `${REMOTE_PACKAGE}#EnrollmentStateList`, listSchema),\n parameters: [{ name: 'input', wire: 'input', source: 'json', codec: makeStrictCodec(`${REMOTE_PACKAGE}#EnrollmentPage`, { parse: parsePage }) }] },\n { ...makeRemoteDescriptor('commandcode/enrollmentWatch', 'enrollmentWatch', `${REMOTE_PACKAGE}#EnrollmentReady`, {\n parse(value: unknown) { return value === true ? true : guard.reject('ready') },\n }), mode: 'stream',\n parameters: [{ name: 'input', wire: 'input', source: 'json', codec: makeStrictCodec(`${REMOTE_PACKAGE}#EnrollmentPage`, { parse: parsePage }) }] },\n]\nexport const ENROLLMENT_REMOTE_CONTRIBUTION: TypertRemoteContribution = { package: REMOTE_PACKAGE, descriptors: ENROLLMENT_DESCRIPTORS }\n","/** 每次设置页挂载独立拥有一个开通控制器;共享设置/用量控制器仍保持插件生命周期。 */\nimport type { RemoteResult, RemoteStreamHandle } from '@deepseek-ai/dsh-typert-protocol'\nimport type { EnrollmentAction, EnrollmentInput, EnrollmentPage, EnrollmentState } from '../enrollment-wire.ts'\nimport { createSnapshotStore } from './snapshot-store.ts'\nimport { openLoginPage } from './login-page.ts'\n\nexport interface EnrollmentRemote {\n enrollmentBegin(input: EnrollmentInput): Promise<RemoteResult<EnrollmentState>>\n enrollmentStatus(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentCancel(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentName(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentRetry(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentPending(input: EnrollmentPage): Promise<RemoteResult<EnrollmentState[]>>\n enrollmentWatch(input: EnrollmentPage): RemoteStreamHandle<boolean, never>\n}\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/enrollmentBegin': EnrollmentRemote['enrollmentBegin']\n 'commandcode/enrollmentStatus': EnrollmentRemote['enrollmentStatus']\n 'commandcode/enrollmentCancel': EnrollmentRemote['enrollmentCancel']\n 'commandcode/enrollmentName': EnrollmentRemote['enrollmentName']\n 'commandcode/enrollmentRetry': EnrollmentRemote['enrollmentRetry']\n 'commandcode/enrollmentPending': EnrollmentRemote['enrollmentPending']\n 'commandcode/enrollmentWatch': EnrollmentRemote['enrollmentWatch']\n }\n}\nexport interface EnrollmentPageState { active: EnrollmentState | undefined; pending: EnrollmentState[]; error: string | undefined }\nconst live = (state: EnrollmentState) => ['creating', 'waiting', 'writing', 'cancelling'].includes(state.phase)\nexport class AccountEnrollmentController {\n readonly store = createSnapshotStore<EnrollmentPageState>({ active: undefined, pending: [], error: undefined })\n private id: string | undefined\n private timer: ReturnType<typeof setTimeout> | undefined\n private disposed = false\n private pageId: string\n private watch: RemoteStreamHandle<boolean, never> | undefined\n private ready: Promise<void> | undefined\n private openedPage = false\n constructor(private readonly remote: () => EnrollmentRemote, private readonly changed: () => void, private readonly pollMs = 750, private readonly newId = () => crypto.randomUUID(), private readonly openPage = openLoginPage) { this.pageId = newId() }\n /** 支持 React 开发模式的挂载检查;每次挂载仍重新读取宿主事实。 */\n activate(): void { if (this.disposed) this.pageId = this.newId(); this.disposed = false; void this.refresh() }\n reset(): void { if (!this.id) this.store.set({ ...this.store.getSnapshot(), active: undefined, error: undefined }) }\n async refresh(): Promise<void> {\n try {\n const result = await this.remote().enrollmentPending({ pageId: this.pageId })\n if (result.ok && !this.disposed) this.store.set({ ...this.store.getSnapshot(), pending: result.value })\n } catch { /* 旧宿主或连接暂不可用,开始开通时再提供明确提示。 */ }\n }\n async begin(input: Omit<EnrollmentInput, 'id' | 'pageId'>): Promise<void> {\n if (this.id || this.disposed) return\n const id = this.newId()\n const pageId = this.pageId\n this.id = id\n this.openedPage = false\n this.store.set({ ...this.store.getSnapshot(), error: undefined, active: { id, ref: '', phase: 'creating', message: '正在创建账号' } })\n try {\n await this.ensureWatch()\n if (this.disposed || this.id !== id || this.pageId !== pageId) return\n const result = await this.remote().enrollmentBegin({ ...input, id, pageId })\n if (this.disposed || this.id !== id) {\n // begin 回复晚到时再取消一次,覆盖传输层乱序或早到的取消失败。\n await this.remote().enrollmentCancel({ id, pageId })\n return\n }\n this.receive(id, result)\n } catch {\n if (this.id === id) this.cancel()\n this.failure('账号开通请求失败,请检查连接后重试')\n }\n }\n /** 页面可立即离开;宿主仍等待写入和补偿收尾。 */\n cancel(): void {\n const id = this.id\n const pageId = this.pageId\n this.id = undefined\n this.stopTimer()\n if (!this.disposed) this.store.set({ ...this.store.getSnapshot(), active: undefined })\n if (id) void Promise.resolve().then(() => this.remote().enrollmentCancel({ id, pageId })).then(() => { this.changed(); void this.refresh() }, () => this.failure('取消请求未确认,重新连接后请检查未完成记录'))\n }\n async name(name?: string): Promise<void> {\n const id = this.id\n if (!id) return\n try { this.receive(id, await this.remote().enrollmentName({ id, pageId: this.pageId, ...(name ? { name } : {}) })) }\n catch { this.failure('名称保存失败,请重试或接受已有名称') }\n }\n async recover(record: EnrollmentState, name?: string): Promise<void> {\n try {\n const result = await this.remote().enrollmentRetry({ id: record.id, pageId: this.pageId, ...(name ? { name } : {}) })\n if (!result.ok) this.failure('收尾未完成,请重试')\n else if (!this.disposed && this.store.getSnapshot().active?.id === record.id) {\n this.store.set({ ...this.store.getSnapshot(), active: result.value, error: undefined })\n }\n this.changed()\n await this.refresh()\n } catch { this.failure('收尾请求失败,请检查连接后重试') }\n }\n dispose(): void { this.disposed = true; this.cancel(); this.watch?.dispose(); this.watch = undefined; this.ready = undefined }\n private ensureWatch(): Promise<void> {\n if (this.ready) return this.ready\n const handle = this.remote().enrollmentWatch({ pageId: this.pageId })\n const iterator = handle[Symbol.asyncIterator]()\n this.watch = handle\n this.ready = iterator.next().then((first) => {\n if (first.done || first.value !== true || this.watch !== handle) throw new Error('页面观察流未建立')\n // 不重连原观察流;载体断开就是该页面过程结束,由宿主补偿。\n void (async () => {\n try { while (!(await iterator.next()).done) { /* 保持调用直到载体结束。 */ } }\n catch { /* 终止统一在 finally 中处理。 */ }\n finally {\n if (this.watch === handle && !this.disposed) {\n this.watch = undefined\n this.ready = undefined\n this.cancel()\n this.failure('开通连接已断开,宿主正在收尾;重连后请检查未完成记录')\n }\n }\n })()\n }).catch((error: unknown) => { handle.dispose(); if (this.watch === handle) { this.watch = undefined; this.ready = undefined }; throw error })\n return this.ready\n }\n private receive(id: string, result: RemoteResult<EnrollmentState>): void {\n if (this.disposed || this.id !== id) return\n if (!result.ok) { this.failure('宿主无法完成账号开通,请检查连接与写入权限'); return }\n const active = result.value\n // 地址可能由后续轮询返回;只接受仍属于当前页面过程的地址,且每次过程只打开一次。\n if (active.phase === 'waiting' && active.authUrl && !this.openedPage) {\n this.openedPage = true\n this.openPage(active.authUrl)\n }\n this.store.set({ ...this.store.getSnapshot(), active, error: undefined })\n if (live(active)) {\n this.stopTimer()\n this.timer = setTimeout(() => { void this.poll(id) }, this.pollMs)\n } else {\n this.changed()\n void this.refresh()\n if (active.phase !== 'naming') this.id = undefined\n }\n }\n private async poll(id: string): Promise<void> {\n if (this.disposed || this.id !== id) return\n try { this.receive(id, await this.remote().enrollmentStatus({ id, pageId: this.pageId })) }\n catch {\n this.failure('开通状态暂不可用,正在等待重新连接')\n if (!this.disposed && this.id === id) this.timer = setTimeout(() => { void this.poll(id) }, this.pollMs)\n }\n }\n private failure(message: string): void { if (!this.disposed) this.store.set({ ...this.store.getSnapshot(), error: message }) }\n private stopTimer(): void { if (this.timer) clearTimeout(this.timer); this.timer = undefined }\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 'settings.commandcode': SettingsCommandCodeKey\n }\n}\n\n/** Dictionary keys of the Command Code settings page. */\nexport type SettingsCommandCodeKey =\n | 'openAnalytics'\n | 'nav'\n | 'title'\n | 'intro'\n | 'apiKey'\n | 'apiKeyHint'\n | 'apiKeySet'\n | 'apiKeyUnset'\n | 'apiKeyLocked'\n | 'apiBase'\n | 'apiBaseHint'\n | 'requestTimeoutMs'\n | 'requestTimeoutMsHint'\n | 'streamIdleTimeoutMs'\n | 'streamIdleTimeoutMsHint'\n | 'transportMaxRetries'\n | 'transportMaxRetriesHint'\n | 'offloadSeenImagesForCache'\n | 'offloadSeenImagesForCacheHint'\n | 'advancedSettings'\n | 'advancedSettingsHint'\n | 'advancedOverriddenOne'\n | 'advancedOverriddenMany'\n | 'advancedInvalid'\n | 'filterModelsByPlan'\n | 'filterModelsByPlanHint'\n | 'webSearch'\n | 'webSearchHint'\n | 'showSidebarQuota'\n | 'showSidebarQuotaHint'\n | 'zdr'\n | 'zdrHint'\n | 'accountsTitle'\n | 'accountsHint'\n | 'accountAdd'\n | 'accountDefault'\n | 'modelSearchPlaceholder'\n | 'modelSearchEmpty'\n | 'modelStale'\n | 'visibleModelsTitle'\n | 'visibleModelsHint'\n | 'visibleModelsPick'\n | 'visibleModelsCount'\n | 'visibleModelsShowAll'\n | 'visibleModelsStaleHint'\n | 'visibleModelsCleanStale'\n | 'overridden'\n | 'reset'\n | 'invalidNumber'\n | 'numberTooSmall'\n | 'numberTooLarge'\n | 'durationTooSmall'\n | 'durationTooLarge'\n | 'durationInvalid'\n | 'readOnly'\n | 'save'\n | 'saving'\n | 'saved'\n | 'saveFailed'\n | 'writeConflict'\n | 'writeConfigUnconfirmed'\n | 'writeConfigSaved'\n | 'writeKeyNotIssued'\n | 'writeKeyUnconfirmed'\n | 'writeKeyConfirmed'\n | 'writeTargetBefore'\n | 'writeTargetAfter'\n | 'writeClosed'\n | 'writeCleanupPending'\n | 'writeRefreshFailed'\n | 'writeRefreshRetry'\n | 'writeStateUnknown'\n | 'unsavedChanges'\n | 'saveInvalid'\n | 'discard'\n | 'cancel'\n | 'show'\n | 'hide'\n | 'usageRefresh'\n | 'usageRefreshing'\n | 'usageLoading'\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 | 'usageMonthlyLeft'\n | 'usageExceeded'\n | 'usageReset'\n | 'usagePartial'\n | 'usageKeyInvalid'\n | 'usageKeyInvalidHint'\n | 'usageServiceUnavailable'\n | 'usageServiceUnavailableHint'\n | 'usageNetworkError'\n | 'usageNetworkHint'\n | 'usageInvalidResponse'\n | 'usageInvalidResponseHint'\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 | 'accountsRotationHint'\n | 'accountModeAuto'\n | 'accountModePinned'\n | 'accountStatusPinned'\n | 'accountActions'\n | 'accountActionPin'\n | 'accountActionUnpin'\n | 'accountActionLogin'\n | 'accountActionKey'\n | 'accountActionRename'\n | 'accountActionClearKey'\n | 'accountActionRemove'\n | 'accountRemoveConfirm'\n | 'accountClearKeyConfirm'\n | 'accountConfirmRemove'\n | 'accountConfirmClear'\n | 'accountApply'\n | 'accountNoKeyHint'\n | 'accountAddHint'\n | 'accountAddLogin'\n | 'accountAddPaste'\n | 'accountAddConfirm'\n | 'accountNamePlaceholder'\n | 'accountNameN'\n | 'accountKeyPlaceholder'\n | 'accountOpFailed'\n | 'accountCleanupPending'\n | 'accountCleanupRetry'\n | 'accountModels'\n | 'accountModelsHint'\n | 'accountModelOwner'\n | 'modelPick'\n | 'modelCount'\n | 'modelAllowance'\n | 'modelAllowanceTitle'\n | 'modelCatalogFailed'\n | 'modelsTitle'\n | 'privacyTitle'\n | 'integrationsTitle'\n\nexport const zh: Record<SettingsCommandCodeKey, string> = {\n openAnalytics: '查看模型用量、成本与性能分析',\n nav: 'Command Code',\n title: 'Command Code',\n intro: '账户操作立即生效;其余设置修改后点击底部「保存」。API 密钥仅保存在本机凭据服务中,不会回显。',\n apiKey: 'API 密钥',\n apiKeyHint: '在 commandcode.ai 控制台创建。留空保存不会覆盖已存储的密钥。',\n apiKeySet: '已配置',\n apiKeyUnset: '未配置',\n apiKeyLocked: '密钥由只读来源提供',\n apiBase: 'API 地址',\n apiBaseHint: '默认 https://api.commandcode.ai,一般无需修改。',\n requestTimeoutMs: '请求超时(秒)',\n requestTimeoutMsHint: '等待响应首个字节的超时;默认 300 秒(与官方 CLI 一致)。Provider API 路由要等上游模型吐出第一个 token 才返回响应头,上游慢时仍可能不够;报超时时可按提示调高。',\n streamIdleTimeoutMs: '流空闲超时(秒)',\n streamIdleTimeoutMsHint: '生成流停滞多久视为断连;默认 300 秒(长思考模型可静默数分钟,默认值刻意放宽)。',\n transportMaxRetries: '网络失败重试次数',\n transportMaxRetriesHint: '连接失败时自动重试几次,默认 5(各次等待 0.5+1+2+4+8 秒,合计约 15 秒)。'\n + '超过后直接报错,不再按指数退避长时间等待;填 0 表示不重试。限流、5xx 等由服务端要求重试的失败不受此项影响。',\n offloadSeenImagesForCache: '已看过的图片不再重复发送',\n offloadSeenImagesForCacheHint: '仅 CLI 传输。模型看过图片并回复后,永久用文字占位替代旧图片,以减少新增图片时的缓存回退。模型如需重看旧图,必须重新读取文件或让用户重新附加。默认关闭。',\n advancedSettings: '高级设置',\n advancedSettingsHint: 'API 地址和网络参数,一般无需修改。',\n advancedOverriddenOne: '已自定义 1 项',\n advancedOverriddenMany: '已自定义 {count} 项',\n advancedInvalid: '高级设置中有未填好的数字,请展开修正后再保存。',\n filterModelsByPlan: '隐藏套餐外模型',\n filterModelsByPlanHint: '只显示套餐内模型;按需余额账户仍显示全部。',\n webSearch: '用 Command Code 承载联网搜索',\n webSearchHint: '使用同一密钥承载 dsh 的 web_search;关闭后恢复原搜索后端。',\n showSidebarQuota: '在侧边栏显示额度卡片',\n showSidebarQuotaHint: '在侧边栏底部显示套餐与额度卡片,点击可打开完整仪表盘。默认关闭,关闭时不会为它后台刷新用量。',\n zdr: '零数据保留(ZDR)',\n zdrHint: '仅使用不留存、不训练的上游;可用模型可能更少且价格通常更高。',\n accountsTitle: '账户',\n accountsHint: '账户操作立即生效,无需保存。可以添加多个账户:当前账户达到用量限额或密钥失效时,请求会自动切换到下一个。',\n accountAdd: '添加账户',\n accountDefault: '默认账户',\n modelSearchPlaceholder: '搜索模型…',\n modelSearchEmpty: '没有匹配的模型。',\n modelStale: '已下架',\n modelAllowance: '${amount}/月',\n modelAllowanceTitle: '该模型每月可用的额度(美元)。套餐内所有模型共用同一个月度额度池,这不是额外赠送的额度。',\n visibleModelsTitle: '模型白名单',\n visibleModelsHint:\n '勾选要保留的模型,模型选择器就只列出这些;一个都不勾选时则显示全部模型。'\n + '这里显示网页与终端合并后的有效选择;保存后两端一致,套餐权限仍独立过滤。',\n visibleModelsPick: '选择要保留的模型…',\n visibleModelsCount: '已选 {count} 个模型',\n visibleModelsShowAll: '显示全部',\n visibleModelsStaleHint: '有 {count} 个已选模型在目录中找不到了(可能已下架),不影响其他模型;可清理或保留。',\n visibleModelsCleanStale: '清理失效({count})',\n overridden: '已覆盖',\n reset: '重置',\n invalidNumber: '无效数字',\n numberTooSmall: '重试次数不能小于 0',\n numberTooLarge: '重试次数不能大于 50',\n durationTooSmall: '不能小于 0.001 秒(1 毫秒)',\n durationTooLarge: '不能大于 3600 秒',\n durationInvalid: '请输入秒数,最多保留三位小数',\n readOnly: '当前配置为只读。',\n save: '保存',\n saving: '保存中',\n saved: '设置已保存',\n saveFailed: '保存失败,请重试。',\n writeConflict: '待提交字段已被其他操作修改,配置未写入;请核对后再保存。',\n writeConfigUnconfirmed: '配置提交未获确认;密钥未写入,请核对宿主状态后重试。',\n writeConfigSaved: '配置已保存。',\n writeKeyNotIssued: '密钥操作尚未发出;请核对后重试。',\n writeKeyUnconfirmed: '密钥操作未获确认;请核对后手动重试。',\n writeKeyConfirmed: '原引用的密钥操作已获确认。',\n writeTargetBefore: '默认密钥引用已变化,本次密钥操作未发出;请核对当前目标。',\n writeTargetAfter: '原引用的密钥操作已发出,默认引用随后变化;请核对两个引用。',\n writeClosed: '客户端已销毁,未发出的操作已停止;已确认的修改保留。',\n writeCleanupPending: '账号修改已确认,清理记录尚未收束,请重试清理。',\n writeRefreshFailed: '密钥状态刷新失败;已获确认的写入仍有效。',\n writeRefreshRetry: '仅刷新密钥状态',\n writeStateUnknown: '密钥状态尚未确认',\n unsavedChanges: '有未保存的更改',\n saveInvalid: '有字段填写不正确,修正后才能保存',\n discard: '放弃',\n cancel: '取消',\n show: '显示',\n hide: '隐藏',\n usageRefresh: '刷新',\n usageRefreshing: '刷新中…',\n usageLoading: '正在获取账户用量…',\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 usageMonthlyLeft: '月额度剩余',\n usageExceeded: '已超限',\n usageReset: '重置于',\n usagePartial: '部分端点数据不可用',\n usageKeyInvalid: 'API 密钥无效或已过期',\n usageKeyInvalidHint: '服务端拒绝了全部请求(401)。请检查该账户配置的密钥,或到 commandcode.ai 控制台重新生成。',\n usageServiceUnavailable: 'Command Code 服务暂时不可用',\n usageServiceUnavailableHint: '服务端返回了错误(5xx),稍后点击刷新重试。',\n usageNetworkError: '无法连接 Command Code 服务',\n usageNetworkHint: '所有请求都没有到达服务端。请检查网络连接或 API 地址设置。',\n usageInvalidResponse: 'Command Code 响应无法读取',\n usageInvalidResponseHint: '已收到响应,但正文读取或解析失败。下方详情可区分读取超时、中断与格式异常;可先点击刷新重试。',\n usageUpdated: '更新于',\n usagePeriodEnd: '账期截止',\n usageActive: '当前使用',\n usageCooldown: '限额冷却中',\n usageInvalidKey: '密钥无效',\n usageUnconfigured: '该账户尚未配置 API 密钥。',\n updateAvailable: '可更新',\n updateHint: '已发布新版本,点击查看发布说明;更新插件后刷新本页,提示会自动消失。',\n loginTitle: '通过官方登录获取密钥',\n loginHintIdle: '也可通过网页授权自动获取并保存密钥。',\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 插件提供,正在等待设置页装配,稍后即可显示完整内容。',\n accountsRotationHint: '账户操作立即生效。当前账户达到用量限额或密钥失效时,请求会按列表顺序自动切换到下一个可用账户。',\n accountModeAuto: '使用方式:自动切换(按列表顺序)',\n accountModePinned: '使用方式:固定使用「{name}」,不可用时仍会自动切换',\n accountStatusPinned: '已固定',\n accountActions: '账户操作',\n accountActionPin: '固定使用此账户',\n accountActionUnpin: '恢复自动切换',\n accountActionLogin: '网页登录获取新密钥',\n accountActionKey: '粘贴新密钥',\n accountActionRename: '重命名',\n accountActionClearKey: '删除密钥',\n accountActionRemove: '移除账户',\n accountRemoveConfirm: '移除「{name}」?它保存的密钥和专用模型设置会一起删除。',\n accountClearKeyConfirm: '删除默认账户保存的密钥?之后会回退到环境变量或官方 CLI 的登录信息。',\n accountConfirmRemove: '移除',\n accountConfirmClear: '删除',\n accountApply: '确定',\n accountNoKeyHint: '还没有密钥:通过网页登录自动获取,或粘贴在 commandcode.ai 控制台创建的 API 密钥。',\n accountAddHint: '网页登录会打开 Command Code 授权页,授权完成后账户自动添加;也可以直接粘贴 API 密钥。',\n accountAddLogin: '网页登录',\n accountAddPaste: '粘贴密钥',\n accountAddConfirm: '添加',\n accountNamePlaceholder: '备注名(可选,网页登录时默认使用账户名)',\n accountNameN: '账户 {n}',\n accountKeyPlaceholder: '粘贴 API 密钥',\n accountOpFailed: '账户操作未能完成,请重试。',\n accountCleanupPending: '账户已移除,但有密钥尚未清理。可重试,不影响其他账户。',\n accountCleanupRetry: '重试清理密钥',\n accountModels: '专用模型',\n accountModelsHint: '选中的模型优先由此账户处理,此账户不可用时仍会自动切换。一个模型只属于一个账户,选中会把它从其他账户移过来。',\n accountModelOwner: '属于 {name}',\n modelPick: '选择模型…',\n modelCount: '已选 {count} 个模型',\n modelCatalogFailed: '模型目录获取失败,暂时无法选择模型;已保存的设置仍会生效。',\n modelsTitle: '模型',\n privacyTitle: '隐私与安全',\n integrationsTitle: '集成与显示',\n}\n\nexport const en: Record<SettingsCommandCodeKey, string> = {\n openAnalytics: 'View model usage, cost and performance',\n nav: 'Command Code',\n title: 'Command Code',\n intro: 'Account actions apply immediately; other settings are written by Save at the bottom. The API key stays in the local credential service and is never echoed.',\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 requestTimeoutMs: 'Request timeout (seconds)',\n requestTimeoutMsHint: 'Time to wait for the first response byte; default 300 s (the official CLI’s). The Provider API route withholds headers until the upstream model emits its first token, so a slow upstream can still outlast the default; raise it when a timeout message suggests it.',\n streamIdleTimeoutMs: 'Stream idle timeout (seconds)',\n streamIdleTimeoutMsHint: 'How long a stalled stream is treated as dead; default 300 s'\n + ' (deliberately generous — long-thinking models can stay silent for minutes).',\n transportMaxRetries: 'Transport retries',\n transportMaxRetriesHint: 'How many times a failed connection is retried automatically; default 5'\n + ' (waits of 0.5+1+2+4+8s, ~15s in total). After that the failure is reported instead of waiting'\n + ' on the exponential backoff. 0 disables the retries. Rate limits and 5xx answers keep their'\n + ' own, longer retry window.',\n offloadSeenImagesForCache: 'Stop replaying images already seen',\n offloadSeenImagesForCacheHint: 'CLI transport only. After this model responds to an image, durably replace older pixels with text to avoid cache rollback when another image arrives. To inspect an old image again, the model must reread its file or the user must attach it again. Off by default.',\n advancedSettings: 'Advanced',\n advancedSettingsHint: 'API base URL and network limits; usually leave as-is.',\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: 'Show only models in your plan; on-demand credit accounts still see the full catalog.',\n webSearch: 'Serve dsh web search with Command Code',\n webSearchHint: 'Use the same key for dsh web search; turning it off restores the previous backend.',\n showSidebarQuota: 'Show the quota card in the sidebar',\n showSidebarQuotaHint: 'Show a plan and quota card at the bottom of the sidebar that opens the full dashboard. Off by default; while off, no background usage refresh runs for it.',\n zdr: 'Zero data retention (ZDR)',\n zdrHint: 'Use only upstreams that retain no data and do not train on requests; availability and pricing may differ.',\n accountsTitle: 'Accounts',\n accountsHint: 'Account actions apply immediately, no save needed. Add more accounts and requests switch to the next one when the current account hits its usage limit or its key stops working.',\n accountAdd: 'Add account',\n accountDefault: 'Default account',\n modelSearchPlaceholder: 'Search models…',\n modelSearchEmpty: 'No matching models.',\n modelStale: 'Retired',\n modelAllowance: '${amount}/mo',\n modelAllowanceTitle: 'Monthly usage this model can draw, in USD. Every model shares one monthly pool — this is not extra credit on top of the plan.',\n visibleModelsTitle: 'Model allowlist',\n visibleModelsHint:\n 'Check the models you want to keep, and model pickers will list only those. '\n + 'If nothing is checked, every model is shown. After saving, the change '\n + 'applies in both web and terminal settings. This page shows their effective selection; plan access is filtered separately.',\n visibleModelsPick: 'Select models to keep…',\n visibleModelsCount: '{count} model(s) selected',\n visibleModelsShowAll: 'Show all',\n visibleModelsStaleHint: '{count} selected model(s) are no longer in the catalog (possibly retired);'\n + ' other models are unaffected. Clean them up or keep them.',\n visibleModelsCleanStale: 'Clean stale ({count})',\n overridden: 'Overridden',\n reset: 'Reset',\n invalidNumber: 'Invalid number',\n numberTooSmall: 'Retries must be at least 0',\n numberTooLarge: 'Retries must not exceed 50',\n durationTooSmall: 'Must be at least 0.001 seconds (1 ms)',\n durationTooLarge: 'Must not exceed 3600 seconds',\n durationInvalid: 'Enter seconds with at most three decimal places',\n readOnly: 'Settings are read-only.',\n save: 'Save',\n saving: 'Saving',\n saved: 'Settings saved',\n saveFailed: 'Save failed, please retry.',\n writeConflict: '待提交字段已被其他操作修改,配置未写入;请核对后再保存。',\n writeConfigUnconfirmed: '配置提交未获确认;密钥未写入,请核对宿主状态后重试。',\n writeConfigSaved: '配置已保存。',\n writeKeyNotIssued: '密钥操作尚未发出;请核对后重试。',\n writeKeyUnconfirmed: '密钥操作未获确认;请核对后手动重试。',\n writeKeyConfirmed: '原引用的密钥操作已获确认。',\n writeTargetBefore: '默认密钥引用已变化,本次密钥操作未发出;请核对当前目标。',\n writeTargetAfter: '原引用的密钥操作已发出,默认引用随后变化;请核对两个引用。',\n writeClosed: '客户端已销毁,未发出的操作已停止;已确认的修改保留。',\n writeCleanupPending: '账号修改已确认,清理记录尚未收束,请重试清理。',\n writeRefreshFailed: '密钥状态刷新失败;已获确认的写入仍有效。',\n writeRefreshRetry: '仅刷新密钥状态',\n writeStateUnknown: '密钥状态尚未确认',\n unsavedChanges: 'You have unsaved changes',\n saveInvalid: 'Fix the highlighted field before saving',\n discard: 'Discard',\n cancel: 'Cancel',\n show: 'Show',\n hide: 'Hide',\n usageRefresh: 'Refresh',\n usageRefreshing: 'Refreshing…',\n usageLoading: 'Fetching account usage…',\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 usageMonthlyLeft: 'Monthly left',\n usageExceeded: 'Exceeded',\n usageReset: 'Resets',\n usagePartial: 'Some endpoint data unavailable',\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 usageInvalidResponse: 'Could not read the Command Code response',\n usageInvalidResponseHint: 'Responses arrived, but reading or parsing their bodies failed. Details below distinguish timeouts, interrupted reads, and invalid formats. Try Refresh again.',\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: 'Alternatively, sign in to fetch and store a key automatically.',\n loginButton: 'Sign in to Command Code',\n loginStarting: 'Starting the local callback server…',\n loginWaiting: 'Waiting for authorization in your browser. If the page did not open automatically, use the authorization link.',\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 and is waiting for the settings page to finish assembling.',\n accountsRotationHint: 'Account actions apply immediately. When the current account hits its usage limit or its key stops working, requests switch to the next usable account in list order.',\n accountModeAuto: 'Mode: switch automatically (list order)',\n accountModePinned: 'Mode: pinned to \"{name}\", still switching when it is unavailable',\n accountStatusPinned: 'Pinned',\n accountActions: 'Account actions',\n accountActionPin: 'Pin this account',\n accountActionUnpin: 'Switch automatically',\n accountActionLogin: 'Sign in for a new key',\n accountActionKey: 'Paste a new key',\n accountActionRename: 'Rename',\n accountActionClearKey: 'Delete key',\n accountActionRemove: 'Remove account',\n accountRemoveConfirm: 'Remove \"{name}\"? Its stored key and dedicated models are deleted with it.',\n accountClearKeyConfirm: 'Delete the default account\\'s stored key? The provider then falls back to the environment or the official CLI sign-in.',\n accountConfirmRemove: 'Remove',\n accountConfirmClear: 'Delete',\n accountApply: 'Apply',\n accountNoKeyHint: 'No key yet: sign in through the browser, or paste an API key created in the commandcode.ai console.',\n accountAddHint: 'Sign-in opens the Command Code authorization page and adds the account once you approve; you can also paste an API key.',\n accountAddLogin: 'Sign in',\n accountAddPaste: 'Paste key',\n accountAddConfirm: 'Add',\n accountNamePlaceholder: 'Name (optional; sign-in uses the account name)',\n accountNameN: 'Account {n}',\n accountKeyPlaceholder: 'Paste an API key',\n accountOpFailed: 'The account change did not complete. Try again.',\n accountCleanupPending: 'The account was removed, but credential cleanup is still pending. Retry without affecting other accounts.',\n accountCleanupRetry: 'Retry credential cleanup',\n accountModels: 'Dedicated models',\n accountModelsHint: 'These models prefer this account and still switch when it is unavailable. A model belongs to one account; selecting it here moves it from any other.',\n accountModelOwner: 'on {name}',\n modelPick: 'Choose models…',\n modelCount: '{count} models selected',\n modelCatalogFailed: 'The model catalog could not be loaded; saved settings still apply.',\n modelsTitle: 'Models',\n privacyTitle: 'Privacy & security',\n integrationsTitle: 'Integrations & display',\n}\n\n/** 同一确认结果在设置页和模型卡使用相同措辞,不从 configured 推断写入结果。 */\nexport function settingsWriteNotice(\n result: import('./settings-write.ts').SettingsWriteResult | undefined,\n t: (key: SettingsCommandCodeKey) => string,\n): string {\n if (!result) return ''\n let key: SettingsCommandCodeKey | undefined\n if (result.issue === 'closed') key = 'writeClosed'\n else if (result.issue === 'target-changed') key = result.credential === 'not-issued' ? 'writeTargetBefore' : 'writeTargetAfter'\n else if (result.issue === 'cleanup-pending') key = 'writeCleanupPending'\n else if (result.config === 'conflict') key = 'writeConflict'\n else if (result.config === 'unconfirmed') key = 'writeConfigUnconfirmed'\n else if (result.credential === 'unconfirmed') key = 'writeKeyUnconfirmed'\n else if (result.credential === 'not-issued') key = 'writeKeyNotIssued'\n const messages = key ? [t(key)] : []\n if (result.issue === 'target-changed' && result.credentialRef) {\n messages.push(t(result.credential === 'confirmed' ? 'writeKeyConfirmed' : 'writeKeyUnconfirmed'))\n messages.push(`(原引用:${result.credentialRef})`)\n }\n if (key && result.config === 'confirmed' && result.issue !== 'cleanup-pending') messages.unshift(t('writeConfigSaved'))\n if (result.refreshFailed) messages.push(t('writeRefreshFailed'))\n return messages.join(' ')\n}\n","/** Shared plan-tier presentation facts; safe to inline into the browser bundle. */\n\nexport const PLAN_TIER_ORDER = ['go', 'goat', 'pro', 'provider', 'max'] as const\n\nexport const PLAN_LABELS: Readonly<Record<string, string>> = {\n go: 'Go',\n goat: 'GOAT',\n pro: 'Pro',\n provider: 'Provider',\n max: 'Max',\n}\n\nexport const PLAN_ORDER: Readonly<Record<string, number>> = Object.fromEntries(\n PLAN_TIER_ORDER.map((tier, index) => [tier, index]),\n)\n","/**\n * Model-select helpers for the settings page's model editors (browser half).\n *\n * The routing-rule editor and the visible-models filter both pick catalog models\n * through the same checkbox multi-select dropdown (`ModelMultiSelect` in\n * section.tsx). The dropdown's data shaping — search filtering, stale-id\n * detection, tier grouping — lives here, React-free, so node tests can drive\n * it directly.\n *\n * The shared tier module is dependency-free and inlined into the client bundle;\n * importing the Host's full capability snapshot here would bloat that bundle.\n *\n * @module dsh-commandcode-provider/model-select\n */\n\nimport { PLAN_LABELS } from '../plan-tiers.ts'\n\n/**\n * The dropdown section heading for a catalog model id, or undefined for\n * models outside the known plan tiers (unmapped models and stale ids render\n * unheaded). `knownPlans` is the Host-side `KNOWN_PLANS` table, threaded in\n * by the caller so this module stays dependency-free.\n */\nexport function tierHeadingFor(\n modelId: string,\n knownPlans: Readonly<Record<string, string>>,\n): string | undefined {\n const tier = knownPlans[modelId]\n if (tier === undefined) return undefined\n return PLAN_LABELS[tier] ?? tier\n}\n\n/** One selectable catalog model (mirrors `CatalogModelOption` in settings.ts). */\nexport interface SelectableModel {\n /** Catalog model id (e.g. `deepseek/deepseek-v4-pro`). */\n id: string\n name: string\n /**\n * Per-model monthly allowance in USD, already resolved by the Host. Passed\n * through untouched: this module renders it, it does not interpret it.\n */\n allowance?: number\n}\n\n/** One dropdown row: a live catalog model or a stale selection. */\nexport interface ModelSelectOption {\n /** Catalog model id (stale ids keep their raw id as the value). */\n value: string\n label: string\n /** True when the id is selected but the catalog no longer carries it. */\n stale: boolean\n /**\n * Per-model monthly allowance in USD. Only live catalog rows can carry one —\n * a stale id is no longer priced by the page, so there is nothing to show.\n */\n allowance?: number\n}\n\n/** One dropdown section: a plan-tier heading plus its rows. */\nexport interface ModelSelectGroup {\n /** Section heading, or undefined for models outside the known plan tiers. */\n heading: string | undefined\n /** Rows in this section, in picker order. */\n options: ModelSelectOption[]\n}\n\n/**\n * Whether `text` matches `query` as a case-insensitive substring over the\n * model id AND display name. An empty/blank query matches everything.\n */\nexport function matchesModelQuery(\n model: SelectableModel,\n query: string,\n): boolean {\n const needle = query.trim().toLowerCase()\n if (needle === '') return true\n return model.id.toLowerCase().includes(needle)\n || model.name.toLowerCase().includes(needle)\n}\n\n/**\n * Build the dropdown options: the catalog (already in picker order) plus any\n * selected ids the catalog no longer carries, flagged stale so a saved\n * selection never silently loses an entry. Stale rows survive a non-blank\n * {@link matchesModelQuery} search only while they match too, so a search for\n * a live model does not surface unrelated stale ids.\n */\nexport function buildModelSelectOptions(\n catalog: readonly SelectableModel[],\n selected: readonly string[],\n query = '',\n): ModelSelectOption[] {\n const catalogIds = new Set(catalog.map((model) => model.id))\n const options = catalog\n .filter((model) => matchesModelQuery(model, query))\n .map((model) => ({\n value: model.id,\n label: model.name,\n stale: false,\n ...(model.allowance === undefined ? {} : { allowance: model.allowance }),\n }))\n // Dedupe defensively (order-preserving): hand-edited settings can repeat\n // or blank an id, and duplicate Menu ids would confuse selection state.\n const seen = new Set(catalogIds)\n for (const id of selected) {\n if (id === '' || seen.has(id)) continue\n seen.add(id)\n if (catalogIds.has(id)) continue\n if (!matchesModelQuery({ id, name: id }, query)) continue\n options.push({ value: id, label: id, stale: true })\n }\n return options\n}\n\n/**\n * Group dropdown options under plan-tier headings (`tierOf` maps a model id to\n * its heading, or undefined for unmapped models — see {@link tierHeadingFor}).\n * Live rows keep their relative order and repeats merge, so a catalog\n * interleaving two tiers still renders one section per tier.\n */\nexport function groupModelSelectOptions(\n options: readonly ModelSelectOption[],\n tierOf: (modelId: string) => string | undefined,\n): ModelSelectGroup[] {\n const groups: ModelSelectGroup[] = []\n const byHeading = new Map<string | undefined, ModelSelectGroup>()\n for (const option of options) {\n // Stale ids always render unheaded (their tier is unknowable); unmapped\n // live rows join the same trailing group so `heading: undefined`\n // appears at most once.\n const heading = option.stale ? undefined : tierOf(option.value)\n let group = byHeading.get(heading)\n if (group === undefined) {\n group = { heading, options: [] }\n byHeading.set(heading, group)\n groups.push(group)\n }\n group.options.push(option)\n }\n return groups\n}\n\n/**\n * Toggle one model id in a selection: remove it when present, append it\n * when absent (append keeps catalog order irrelevant — the picker re-sorts\n * by plan tier on render).\n */\nexport function toggleModelSelection(\n selected: readonly string[],\n modelId: string,\n): string[] {\n return selected.includes(modelId)\n ? selected.filter((value) => value !== modelId)\n : [...selected, modelId]\n}\n\n/** The catalog facts the visible-models card reads (mirrors `SettingsPageState`). */\nexport interface CatalogReadiness {\n /** Catalog model ids the Host reported (`[]` before the first fetch lands). */\n catalogIds: readonly string[]\n /** Whether the catalog fetch failed (or the Remote is unavailable). */\n catalogFailed: boolean\n}\n\n/**\n * Whether the catalog is trustworthy enough to call an unlisted selection\n * \"retired\". FALSE while the first fetch is in flight, after a failure, and\n * for a loaded-but-empty catalog — an empty list makes every selected id look\n * stale, which would turn the one-click stale cleanup into a button that\n * silently empties the allowlist. Users who really want it cleared have the\n * explicit \"show all\" entry.\n */\nexport function catalogIsReady(readiness: CatalogReadiness): boolean {\n return readiness.catalogIds.length > 0 && !readiness.catalogFailed\n}\n\n/**\n * Selected ids the loaded catalog no longer carries, in selection order.\n * Callers gate user-visible \"stale\" affordances on {@link catalogIsReady} —\n * the list itself is informational.\n */\nexport function staleModelIds(\n selected: readonly string[],\n readiness: CatalogReadiness,\n): string[] {\n const catalogIds = new Set(readiness.catalogIds)\n return selected.filter((id) => !catalogIds.has(id))\n}\n","","/**\n * The plugin's own version, read from package.json at build time. The client\n * bundle inlines the JSON import (rolldown resolves it during the tsdown\n * build; node tests read it through tsx), so the rendered value always matches\n * the published package version with no second constant to keep in sync —\n * rendered as a muted footer line so a user can report the exact build.\n *\n * @module dsh-commandcode-provider/client/version\n */\n\nimport pkg from '../../package.json'\n\n/** The published package version. */\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 * Tolerates both repository shapes (`{ url }` and the plain string form).\n */\nexport const PLUGIN_RELEASES_URL: string = (() => {\n const repo: unknown = (pkg as { repository?: unknown }).repository\n const url = typeof repo === 'string' ? repo : (repo as { url?: unknown } | undefined)?.url\n return `${typeof url === 'string' ? url.replace(/^git\\+/, '').replace(/\\.git$/, '') : 'https://github.com/Mars-Sea/dsh-commandcode-provider'}/releases`\n})()\n","/**\n * Plugin update hint (browser half).\n *\n * When the \"Command Code\" settings page opens, ask the npm registry for the\n * package's published `latest` version and — only when it is newer than the\n * running build — let the page's footer show a muted \"newer version available\"\n * link to the GitHub releases. Everything here is React-free and side-effect\n * seamed so node tests can drive it.\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` with\n * the attempt time, so re-opening the page is free. A FAILED check records the\n * attempt time too (an offline browser must not hammer the registry) but keeps\n * any previously learned version, so the hint survives transient outages. Every\n * failure mode — blocked network, non-OK status, malformed payload,\n * unavailable storage — degrades to \"no hint\"; nothing ever throws out of\n * {@link checkForUpdate}. The registry serves `access-control-allow-origin: *`,\n * so the plain browser fetch works from the GUI origin with no Host proxy.\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]`): negative when `a`\n * 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. Enough for release tags,\n * not a full 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 // Split on the FIRST dash only: `1.0.0-alpha-1` has prerelease `alpha-1`,\n // not `alpha` (a split on every dash would drop the `-1`).\n const cleaned = value.trim().replace(/^v/i, '')\n const dash = cleaned.indexOf('-')\n const coreText = dash < 0 ? cleaned : cleaned.slice(0, dash)\n const preText = dash < 0 ? undefined : cleaned.slice(dash + 1)\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. All copy comes from the\n * `settings.commandcode` locale namespace; all state comes from the\n * `CommandCodeSettingsController` injected by the slot registration.\n *\n * Layout, top to bottom: Accounts (one card per account, status, quota,\n * actions and dedicated models — every operation commits immediately), Models\n * (plan filter + visible-model allowlist), Privacy & security (ZDR),\n * Integrations & display (web search, sidebar quota card), and a collapsed\n * Advanced card (API base + network limits). Everything below Accounts is a\n * flat group of rows (title/description left, control right) inside the staged\n * form the floating save bar writes.\n *\n * Styles are injected once by the client entry (see src/client/index.ts) and\n * class-prefixed `cc-` to stay local.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } 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 { settingsWriteNotice, type SettingsCommandCodeKey } from './locales.ts'\nimport type { CatalogModelOption, SettingsPageState, StagedField } from './settings.ts'\nimport type { AccountEnrollmentController, EnrollmentPageState } from './enrollment.ts'\nimport type { LoginPageState } from './login.ts'\nimport { loginHint, loginStateForTarget } from './login.ts'\nimport { buildModelSelectOptions, catalogIsReady, groupModelSelectOptions, staleModelIds, tierHeadingFor, toggleModelSelection } from './model-select.ts'\nimport type { UsagePageState } from './usage.ts'\nimport { usageCardState } from './usage.ts'\nimport { formatMoney, formatMoneyExact, formatResetAt, formatSuccessRate, formatTokensCompact, windowRatio } from '../display-format.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 openAnalytics?(): void\n refreshCredentials(): void\n beginLogin(targetRef?: string): void\n cancelLogin(): void\n createEnrollment(): AccountEnrollmentController\n renameAccount(ref: string, label: string): Promise<boolean>\n removeAccount(ref: string): Promise<boolean>\n retryCredentialCleanup(ref: string): Promise<boolean>\n setAccountKey(target: string, key: string): Promise<boolean>\n clearAccountKey(target: string): Promise<boolean>\n setActiveAccount(id: string): Promise<boolean>\n setAccountModels(target: string, ids: string[]): Promise<boolean>\n editVisibleModels(ids: string[]): void\n clearVisibleModels(): void\n}\n\n/** The section fields folded into the collapsible Advanced card. */\ntype AdvancedField = 'apiBase' | 'requestTimeoutMs' | 'streamIdleTimeoutMs' | 'transportMaxRetries' | 'offloadSeenImagesForCache'\nconst ADVANCED_FIELDS: readonly AdvancedField[] = [\n 'apiBase',\n 'requestTimeoutMs',\n 'streamIdleTimeoutMs',\n 'transportMaxRetries',\n 'offloadSeenImagesForCache',\n]\n\n/** The \"customized\" tag and reset link a staged field shows once it differs from the default. */\nfunction FieldOverride({ label, state, disabled, t, onReset }: {\n label: string\n state: StagedField\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onReset(): void\n}) {\n if (!state.overridden && !state.clear) return null\n return (\n <button type=\"button\" className=\"cc-linkButton\" disabled={disabled} onClick={onReset} aria-label={`${label} — ${t('reset')}`}>\n {t('reset')}\n </button>\n )\n}\n\n/**\n * One settings row, laid out like the harness's own General page: the title\n * and description on the left, the control on the right, a hairline between\n * rows.\n */\nfunction SettingRow({ title, titleFor, titleId, tag, description, error, control, className }: {\n title: string\n /** Makes the title a `<label>` for this control id. */\n titleFor?: string\n titleId?: string\n tag?: ReactNode\n description?: ReactNode\n /** Replaces the description while set. */\n error?: string | undefined\n control?: ReactNode\n className?: string\n}) {\n return (\n <div className={className === undefined ? 'cc-row' : `cc-row ${className}`}>\n <div className=\"cc-rowText\">\n <div className=\"cc-rowTitleLine\">\n {titleFor !== undefined\n ? <label className=\"cc-rowTitle\" id={titleId} htmlFor={titleFor}>{title}</label>\n : <span className=\"cc-rowTitle\" id={titleId}>{title}</span>}\n {tag}\n </div>\n {error !== undefined ? <p className=\"cc-rowError\">{error}</p> : null}\n {error === undefined && description !== undefined ? <div className=\"cc-rowDesc\">{description}</div> : null}\n </div>\n {control !== undefined ? <div className=\"cc-rowControl\">{control}</div> : null}\n </div>\n )\n}\n\n/** The tag a row title carries while its field overrides the default. */\nfunction OverrideTag({ state, t }: { state: StagedField; t: Translate<SettingsCommandCodeKey> }) {\n return state.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null\n}\n\n/** One text/number field row. */\nfunction Field({\n id,\n label,\n hint,\n state,\n disabled,\n numeric,\n decimal,\n wide,\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 decimal?: boolean\n wide?: boolean\n placeholder?: string | undefined\n onEdit(text: string): void\n onReset(): void\n t: Translate<SettingsCommandCodeKey>\n}) {\n return (\n <SettingRow\n title={label}\n titleFor={id}\n tag={<OverrideTag state={state} t={t} />}\n description={hint}\n error={state.invalid ? invalidCopy(state.invalidReason, t, decimal) : undefined}\n control={\n <>\n <FieldOverride label={label} state={state} disabled={disabled} t={t} onReset={onReset} />\n <input\n id={id}\n className={`cc-input ${wide ? 'cc-rowInputWide' : 'cc-rowInput'}${state.invalid ? ' cc-inputInvalid' : ''}`}\n type=\"text\"\n inputMode={decimal ? 'decimal' : numeric ? 'numeric' : undefined}\n aria-invalid={state.invalid || undefined}\n value={state.text}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n </>\n }\n />\n )\n}\n\n/** The per-field error copy for a staged draft's failure reason. */\nfunction invalidCopy(reason: StagedField['invalidReason'], t: Translate<SettingsCommandCodeKey>, duration = false): string {\n if (duration) {\n if (reason === 'tooSmall') return t('durationTooSmall')\n if (reason === 'tooLarge') return t('durationTooLarge')\n return t('durationInvalid')\n }\n if (reason === 'tooSmall') return t('numberTooSmall')\n if (reason === 'tooLarge') return t('numberTooLarge')\n return t('invalidNumber')\n}\n\n/**\n * One boolean field row rendered as a switch. 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 <SettingRow\n title={label}\n titleFor={id}\n tag={<OverrideTag state={state} t={t} />}\n description={hint}\n control={\n <>\n <FieldOverride label={label} state={state} disabled={disabled} t={t} onReset={onReset} />\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 </>\n }\n />\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,\n t,\n}: {\n label: string\n limit: NonNullable<CommandCodeCredits['fiveHour']>\n t: Translate<SettingsCommandCodeKey>\n}) {\n const { used, cap, exceeded, resetAt } = limit\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-label={label} 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 pool account's facts (identity, totals, credits, window limits). */\nfunction AccountReport({ entry, fetchedAt, t, headless = false }: {\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 /** Omit the identity header (the account row already shows it). */\n headless?: boolean\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 {!headless ? (\n <div className=\"cc-usageHead\">\n <h4 className=\"cc-usageTitle\">{entry.label}</h4>\n {accountName !== '' ? <span className=\"cc-usageAccount\">{accountName}</span> : null}\n {planName !== '' ? <span className=\"cc-usagePlan\">{planName}</span> : null}\n </div>\n ) : null}\n {planStatus !== '' ? <p className=\"cc-usagePlanStatus\">{planStatus}</p> : null}\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 {/* Keep the per-endpoint failures visible alongside the summary:\n they carry the actual status or transport error for diagnosis. */}\n {report.failures.length > 0 ? (\n <p className=\"cc-usageBlockedDetail\" title={report.failures.join('; ')}>\n {report.failures.join(' · ')}\n </p>\n ) : null}\n </div>\n ) : null}\n\n {report.usage !== undefined ? (\n <div className=\"cc-usageStats cc-usageStatsActivity\">\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={`${formatSuccessRate(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 cc-usageStatsBalance\">\n <UsageStat label={t('usageMonthly')} value={credits.monthlyReported === false ? '—' : formatMoney(credits.monthlyCredits)} />\n <UsageStat label={t('usagePurchased')} value={credits.purchasedReported === false ? '—' : formatMoney(credits.purchasedCredits)} />\n <UsageStat label={t('usageFree')} value={credits.freeReported === false ? '—' : formatMoney(credits.freeCredits)} />\n </div>\n ) : null}\n\n {credits?.fiveHour !== undefined || credits?.weekly !== undefined ? (\n <div className=\"cc-usageWindows\">\n {credits.fiveHour !== undefined ? (\n <UsageWindow label={t('usageFiveHour')} limit={credits.fiveHour} t={t} />\n ) : null}\n {credits.weekly !== undefined ? (\n <UsageWindow label={t('usageWeekly')} limit={credits.weekly} t={t} />\n ) : null}\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 if (reason === 'invalid-response') return t('usageInvalidResponse')\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 if (reason === 'invalid-response') return t('usageInvalidResponseHint')\n return t('usageNetworkHint')\n}\n\n/**\n * A checkbox multi-select dropdown for picking catalog models (the routing-rule\n * rows and the visible-models filter share it). The trigger shows the selection\n * count; the Menu lists every catalog model, grouping under plan-tier headings\n * and flagging selected ids the catalog no longer carries as stale, so a saved\n * selection never silently loses an entry (the VisibleModelsCard offers a\n * one-click cleanup).\n *\n * With `deferCommit` the toggles collect in a local draft that is handed to\n * `onSelect` once, when the menu closes: the per-account picker writes\n * immediately, and one write per click would be a burst of document writes.\n */\nfunction ModelMultiSelect({ id, selected: committed, catalog, disabled, deferCommit = false, ownerOf, t, onSelect }: {\n id: string\n selected: string[]\n catalog: CatalogModelOption[]\n disabled: boolean\n deferCommit?: boolean\n /** Names the other account a model currently belongs to, if any. */\n ownerOf?: (modelId: string) => string | undefined\n t: Translate<SettingsCommandCodeKey>\n onSelect(ids: string[]): void\n}) {\n const [open, setOpen] = useState(false)\n const [query, setQuery] = useState('')\n const [draft, setDraft] = useState<string[] | undefined>(undefined)\n const selected = draft ?? committed\n // The search box must not inherit a stale query from a previous open.\n useEffect(() => {\n if (open) setQuery('')\n }, [open])\n const close = () => {\n setOpen(false)\n if (draft !== undefined) {\n setDraft(undefined)\n const changed = draft.length !== committed.length || draft.some((modelId) => !committed.includes(modelId))\n if (changed) onSelect(draft)\n }\n }\n // Tier headings come from the catalog entries themselves (the Host stamps\n // each entry's plan-tier key on the Remote); rebuild only when the catalog\n // changes.\n const tiers = useMemo(\n () => Object.fromEntries(\n catalog.flatMap((model) => model.tier === undefined ? [] : [[model.id, model.tier] as const]),\n ),\n [catalog],\n )\n const options = buildModelSelectOptions(catalog, selected, query)\n const groups = groupModelSelectOptions(options, (modelId) => tierHeadingFor(modelId, tiers))\n const items: MenuEntry[] = groups.flatMap((group) => [\n ...(group.heading === undefined\n ? []\n : [{ type: 'label' as const, id: `cc-tier-${group.heading}`, text: group.heading }]),\n ...group.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={selected.includes(option.value)}\n readOnly\n tabIndex={-1}\n />\n <span className=\"cc-checkName\">{option.label}</span>\n {option.stale ? <span className=\"cc-badge\">{t('modelStale')}</span> : null}\n {option.allowance !== undefined ? (\n <span className=\"cc-badgeMuted\" title={t('modelAllowanceTitle')}>\n {t('modelAllowance', { amount: option.allowance })}\n </span>\n ) : null}\n {!selected.includes(option.value) && ownerOf?.(option.value) !== undefined ? (\n <span className=\"cc-badgeMuted\">{t('accountModelOwner', { name: ownerOf(option.value)! })}</span>\n ) : null}\n </span>\n ),\n })),\n ])\n // The search box lives INSIDE the Menu anchor (which renders in place\n // inside the Menu's root span): a pointerdown there counts as \"inside\",\n // so focusing/typing never trips the Menu's outside-click close. A box\n // rendered as a sibling would close the Menu on the first click.\n return (\n <Menu\n open={open}\n onClose={close}\n onSelect={(modelId) => {\n const next = toggleModelSelection(selected, modelId)\n if (deferCommit) setDraft(next)\n else onSelect(next)\n }}\n selectedIds={selected}\n items={items}\n footer={options.length === 0 ? [{\n type: 'label' as const,\n id: 'cc-model-search-empty',\n text: t('modelSearchEmpty'),\n }] : []}\n portal\n anchor={\n <span className=\"cc-modelSelectAnchor\">\n <button\n id={id}\n type=\"button\"\n className=\"cc-selector\"\n disabled={disabled || catalog.length === 0}\n onClick={() => (open ? close() : setOpen(true))}\n >\n <span className=\"cc-selectorText\">\n {selected.length === 0 ? t('modelPick') : t('modelCount', { count: selected.length })}\n </span>\n <span className=\"cc-selectorCaret\" aria-hidden=\"true\" />\n </button>\n {open ? (\n <input\n type=\"search\"\n className=\"cc-input cc-modelSearch\"\n placeholder={t('modelSearchPlaceholder')}\n aria-label={t('modelSearchPlaceholder')}\n value={query}\n disabled={disabled}\n autoFocus\n onChange={(event) => setQuery(event.target.value)}\n />\n ) : null}\n </span>\n }\n />\n )\n}\n\n/** The visible-model filter row: an allowlist over the catalog. Empty = show all. */\nfunction VisibleModelsRow({ t, state, disabled, onSelect, onClear }: {\n t: Translate<SettingsCommandCodeKey>\n state: SettingsPageState\n disabled: boolean\n onSelect(ids: string[]): void\n onClear(): void\n}) {\n const count = state.visibleModels.length\n const pickT: Translate<SettingsCommandCodeKey> = (key, params) => {\n if (key === 'modelPick' || key === 'modelCount') {\n return state.visibleModelsAll ? t('visibleModelsShowAll') : t('visibleModelsCount', { count })\n }\n return t(key, params)\n }\n // Selected ids the live catalog no longer carries (retired upstream): kept,\n // flagged stale in the dropdown, removable in one click — never auto-dropped,\n // since an empty catalog (fetch failure) must not wipe the list. Both the\n // cleanup button and its hint are gated on catalogIsReady, whose doc states\n // why an empty catalog makes every selection look retired.\n const readiness = { catalogIds: state.catalogModels.map((model) => model.id), catalogFailed: state.catalogFailed }\n const staleIds = staleModelIds(state.visibleModels, readiness)\n const catalogReady = catalogIsReady(readiness)\n return (\n <SettingRow\n title={t('visibleModelsTitle')}\n titleFor=\"cc-visible-models\"\n description={\n <>\n <p>{t('visibleModelsHint')}</p>\n {staleIds.length > 0 && catalogReady ? <p>{t('visibleModelsStaleHint', { count: staleIds.length })}</p> : null}\n </>\n }\n error={state.catalogFailed ? t('modelCatalogFailed') : undefined}\n control={\n <>\n {catalogReady && staleIds.length > 0 ? (\n <button\n type=\"button\"\n className=\"cc-linkButton\"\n disabled={disabled}\n onClick={() => onSelect(state.visibleModels.filter((id) => !staleIds.includes(id)))}\n >\n {t('visibleModelsCleanStale', { count: staleIds.length })}\n </button>\n ) : null}\n {!state.visibleModelsAll ? (\n <button type=\"button\" className=\"cc-linkButton\" disabled={disabled} onClick={onClear}>\n {t('visibleModelsShowAll')}\n </button>\n ) : null}\n <ModelMultiSelect\n id=\"cc-visible-models\"\n selected={state.visibleModels}\n catalog={state.catalogModels}\n disabled={disabled}\n t={pickT}\n onSelect={onSelect}\n />\n </>\n }\n />\n )\n}\n\n/**\n * One titled group of rows. No card surface: like the harness's own settings\n * pages, a group is a heading over its rows. The hairline between sections is\n * `cc-groupDivided`, so it belongs to every group but the first one on the page\n * (accounts opens it) and never to the rows inside a group.\n */\nfunction SettingsGroup({ title, action, divided = false, children }: { title: string; action?: ReactNode; divided?: boolean; children: ReactNode }) {\n return (\n <section className={divided ? 'cc-group cc-groupDivided' : 'cc-group'} aria-label={title}>\n <div className=\"cc-groupHead\">\n <h3 className=\"cc-groupTitle\">{title}</h3>\n {action}\n </div>\n <div className=\"cc-rows\">{children}</div>\n </section>\n )\n}\n\n/** The staged-field callbacks every form card shares. */\ninterface FormCardProps {\n state: SettingsPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onEdit(field: string, text: string): void\n onReset(field: string): void\n}\n\n/**\n * Models: the plan filter and the allowlist sit together because both decide\n * what the model picker lists (the allowlist applies after the plan filter).\n */\nfunction ModelsCard({ state, disabled, t, onEdit, onReset, onSelect, onClear }: FormCardProps & {\n onSelect(ids: string[]): void\n onClear(): void\n}) {\n return (\n <SettingsGroup title={t('modelsTitle')} divided>\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 <VisibleModelsRow t={t} state={state} disabled={disabled} onSelect={onSelect} onClear={onClear} />\n </SettingsGroup>\n )\n}\n\n/**\n * Privacy & security: the opt-in that changes where data goes. ZDR restricts\n * which upstream serves a request, so it starts off.\n */\nfunction PrivacyCard({ state, disabled, t, onEdit, onReset }: FormCardProps) {\n return (\n <SettingsGroup title={t('privacyTitle')} divided>\n <ToggleField\n id=\"cc-zdr\"\n label={t('zdr')}\n hint={t('zdrHint')}\n state={state.zdr}\n disabled={disabled}\n defaultChecked={false}\n onEdit={(text) => onEdit('zdr', text)}\n onReset={() => onReset('zdr')}\n t={t}\n />\n </SettingsGroup>\n )\n}\n\n/** Integrations & display: surfaces outside chat that reuse this provider. */\nfunction IntegrationsCard({ state, disabled, t, onEdit, onReset }: FormCardProps) {\n return (\n <SettingsGroup title={t('integrationsTitle')} divided>\n <ToggleField\n id=\"cc-web-search\"\n label={t('webSearch')}\n hint={t('webSearchHint')}\n state={state.webSearch}\n disabled={disabled}\n defaultChecked\n onEdit={(text) => onEdit('webSearch', text)}\n onReset={() => onReset('webSearch')}\n t={t}\n />\n {/* Opt-in, and off by default: the sidebar quota card is a display\n surface, so an unset document shows nothing on the left. */}\n <ToggleField\n id=\"cc-show-sidebar-quota\"\n label={t('showSidebarQuota')}\n hint={t('showSidebarQuotaHint')}\n state={state.showSidebarQuota}\n disabled={disabled}\n defaultChecked={false}\n onEdit={(text) => onEdit('showSidebarQuota', text)}\n onReset={() => onReset('showSidebarQuota')}\n t={t}\n />\n </SettingsGroup>\n )\n}\n\n/**\n * The collapsed \"Advanced\" card: the API base and the network limits. Starts\n * collapsed on every visit; while collapsed, a badge names the customized\n * count and an invalid number (which blocks save) is surfaced on the header.\n */\nfunction AdvancedSection({ state, disabled, t, onEdit, onReset }: FormCardProps) {\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 <section className=\"cc-group cc-groupDivided\" aria-label={t('advancedSettings')}>\n <button\n type=\"button\"\n className=\"cc-groupHead cc-disclosure\"\n aria-expanded={expanded}\n aria-controls=\"cc-advanced-body\"\n onClick={() => setExpanded((value) => !value)}\n >\n <span className=\"cc-groupTitle\">{t('advancedSettings')}</span>\n {overridden > 0 ? (\n <span className=\"cc-badge\">\n {overridden === 1 ? t('advancedOverriddenOne') : t('advancedOverriddenMany', { count: overridden })}\n </span>\n ) : null}\n {!expanded && invalid ? (\n <span className=\"cc-badge cc-badgeWarn\">{t('advancedInvalid')}</span>\n ) : null}\n <span className=\"cc-spacer\" />\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-rows\">\n <p className=\"cc-groupDesc\">{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 wide\n onEdit={(text) => onEdit('apiBase', text)}\n onReset={() => onReset('apiBase')}\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 decimal\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 decimal\n onEdit={(text) => onEdit('streamIdleTimeoutMs', text)}\n onReset={() => onReset('streamIdleTimeoutMs')}\n t={t}\n />\n <Field\n id=\"cc-transport-max-retries\"\n label={t('transportMaxRetries')}\n hint={t('transportMaxRetriesHint')}\n state={state.transportMaxRetries}\n disabled={disabled}\n numeric\n onEdit={(text) => onEdit('transportMaxRetries', text)}\n onReset={() => onReset('transportMaxRetries')}\n t={t}\n />\n <ToggleField\n id=\"cc-offload-seen-images-for-cache\"\n label={t('offloadSeenImagesForCache')}\n hint={t('offloadSeenImagesForCacheHint')}\n state={state.offloadSeenImagesForCache}\n disabled={disabled}\n defaultChecked={false}\n onEdit={(text) => onEdit('offloadSeenImagesForCache', text)}\n onReset={() => onReset('offloadSeenImagesForCache')}\n t={t}\n />\n </div>\n ) : null}\n {expanded && invalid ? (\n <p className=\"cc-rowError\" role=\"status\">{t('advancedInvalid')}</p>\n ) : null}\n </section>\n )\n}\n\n/** One row of the unified account list: a stored account merged with its usage entry. */\ninterface AccountRowModel {\n /** Slot id: `default` or the extra account's credential reference. */\n id: string\n label: string\n /** Credential reference for extra accounts; undefined for the default slot. */\n ref: string | undefined\n isDefault: boolean\n /** Whether this page can manage the row (false for literal-only composition entries). */\n managed: boolean\n /** Whether a key resolves for this account (stored credential or a Host-side source). */\n configured: boolean\n /** Whether a stored credential exists this page could delete. */\n storedKey: boolean\n credentialKnown: boolean\n keyWritable: boolean\n usage: CommandCodeAccountUsage | undefined\n}\n\n/**\n * Merge the controller's accounts with the usage report. The default slot is\n * always first; report entries this page cannot manage (literal keys from the\n * composition config) still render, read-only, so the list names every\n * account the pool rotates through.\n */\nfunction accountRows(state: SettingsPageState, usage: UsagePageState, t: Translate<SettingsCommandCodeKey>): AccountRowModel[] {\n const report = new Map((usage.report?.accounts ?? []).map((entry) => [entry.id, entry]))\n const defaultUsage = report.get('default')\n const rows: AccountRowModel[] = [{\n id: 'default',\n label: t('accountDefault'),\n ref: undefined,\n isDefault: true,\n managed: true,\n configured: state.apiKeyConfigured || defaultUsage?.configured === true,\n storedKey: state.apiKeyConfigured,\n credentialKnown: state.apiKeyKnown || typeof defaultUsage?.configured === 'boolean',\n keyWritable: state.apiKeyWritable,\n usage: defaultUsage,\n }]\n for (const account of state.accounts) {\n const entry = report.get(account.id)\n rows.push({\n id: account.id,\n label: account.label,\n ref: account.ref,\n isDefault: false,\n managed: true,\n configured: account.configured || entry?.configured === true,\n storedKey: account.configured,\n credentialKnown: account.credentialKnown || typeof entry?.configured === 'boolean',\n keyWritable: account.writable,\n usage: entry,\n })\n }\n const known = new Set(rows.map((row) => row.id))\n for (const entry of usage.report?.accounts ?? []) {\n if (known.has(entry.id)) continue\n known.add(entry.id)\n rows.push({\n id: entry.id,\n label: entry.label,\n ref: undefined,\n isDefault: false,\n managed: false,\n configured: entry.configured,\n storedKey: false,\n credentialKnown: true,\n keyWritable: false,\n usage: entry,\n })\n }\n return rows\n}\n\n/**\n * The row's status dot. Read top-down, so a problem always outranks \"serving\":\n * red for a key the Host rejected, amber while a rate limit is cooling down,\n * green for the account that is actually serving requests. A standby (or not\n * yet configured) account draws NOTHING — `cc-tabDotBlank` is an unfilled,\n * borderless dot that only holds the column so the account names stay aligned\n * with the rows that do have a verdict. Green therefore means \"in use\", not\n * \"healthy\": a wall of green dots would say nothing.\n */\nfunction statusDotClass(row: AccountRowModel): string {\n const entry = row.usage\n if (entry?.mark === 'invalid-credential') return 'cc-tabDot cc-tabDotError'\n if (entry !== undefined && (entry.mark !== '' || entry.cooldownUntil > 0)) return 'cc-tabDot cc-tabDotWarn'\n if (row.configured && entry?.active === true) return 'cc-tabDot cc-tabDotOk'\n return 'cc-tabDot cc-tabDotBlank'\n}\n\n/**\n * The same verdict as a sentence, for the dot's tooltip. Undefined on a blank\n * dot: there is no verdict to read out, and a hover hotspot on an invisible\n * 8px mark would only invite the question it cannot usefully answer.\n */\nfunction statusDotTitle(row: AccountRowModel, t: Translate<SettingsCommandCodeKey>): string | undefined {\n const entry = row.usage\n if (entry?.mark === 'invalid-credential') return t('usageInvalidKey')\n if (entry !== undefined && (entry.mark !== '' || entry.cooldownUntil > 0)) return t('usageCooldown')\n if (!row.credentialKnown) return t('writeStateUnknown')\n if (!row.configured) return t('apiKeyUnset')\n return entry?.active === true ? t('usageActive') : undefined\n}\n\n/** One compact quota meter for a row's summary line. */\nfunction MiniMeter({ label, limit }: { label: string; limit: NonNullable<CommandCodeCredits['fiveHour']> }) {\n const ratio = windowRatio(limit.used, limit.cap)\n const percent = limit.cap > 0 ? `${Math.round(ratio * 100)}%` : formatMoney(limit.used)\n return (\n <span className=\"cc-miniMeter\" title={limit.cap > 0 ? `${formatMoney(limit.used)} / ${formatMoney(limit.cap)}` : undefined}>\n <span className=\"cc-miniMeterLabel\">{label}</span>\n <span className=\"cc-miniMeterTrack\" aria-hidden=\"true\">\n <span className={limit.exceeded ? 'cc-miniMeterFill cc-usageBarFillWarn' : 'cc-miniMeterFill'} style={{ width: `${ratio * 100}%` }} />\n </span>\n <span className=\"cc-miniMeterValue\">{percent}</span>\n </span>\n )\n}\n\n/**\n * The monthly credit balance for a row's summary line: the billing endpoint's\n * `monthlyCredits` is what is LEFT, shown as the amount alone.\n */\nfunction MonthlyBalance({ label, remaining }: { label: string; remaining: number }) {\n return (\n <span className=\"cc-miniMeter\">\n <span className=\"cc-miniMeterLabel\">{label}</span>\n <span className=\"cc-miniMeterValue\">{formatMoney(Math.max(0, remaining))}</span>\n </span>\n )\n}\n\n/** A single-input inline form (paste key, rename) with confirm/cancel. */\nfunction InlineInput({ id, label, secret, initial, placeholder, confirmLabel, disabled, t, onSubmit, onCancel }: {\n id: string\n label: string\n secret?: boolean\n initial?: string\n placeholder?: string\n confirmLabel: string\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onSubmit(value: string): void\n onCancel(): void\n}) {\n const [value, setValue] = useState(initial ?? '')\n const [visible, setVisible] = useState(false)\n const ready = value.trim() !== ''\n return (\n <form\n className=\"cc-inlineForm\"\n onSubmit={(event) => {\n event.preventDefault()\n if (ready && !disabled) onSubmit(value)\n }}\n >\n <input\n id={id}\n className=\"cc-input\"\n type={secret && !visible ? 'password' : 'text'}\n aria-label={label}\n autoComplete=\"new-password\"\n spellCheck={false}\n autoFocus\n placeholder={placeholder}\n value={value}\n disabled={disabled}\n onChange={(event) => setValue(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') onCancel()\n }}\n />\n <div className=\"cc-inlineActions\">\n {secret && value !== '' ? (\n <button type=\"button\" className=\"cc-reset\" onClick={() => setVisible((shown) => !shown)}>\n {visible ? t('hide') : t('show')}\n </button>\n ) : null}\n <span className=\"cc-spacer\" />\n <Button variant=\"ghost\" size=\"sm\" type=\"button\" onClick={onCancel}>{t('cancel')}</Button>\n <Button variant=\"primary\" size=\"sm\" type=\"submit\" disabled={!ready || disabled}>{confirmLabel}</Button>\n </div>\n </form>\n )\n}\n\n/** A destructive confirmation bar shown in place of a menu action. */\nfunction ConfirmBar({ text, confirmLabel, disabled, t, onConfirm, onCancel }: {\n text: string\n confirmLabel: string\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onConfirm(): void\n onCancel(): void\n}) {\n return (\n <div className=\"cc-confirmBar\" role=\"alertdialog\" aria-label={text}>\n <p className=\"cc-confirmText\">{text}</p>\n <div className=\"cc-inlineActions\">\n <span className=\"cc-spacer\" />\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>{t('cancel')}</Button>\n <Button variant=\"outline\" size=\"sm\" className=\"cc-dangerButton\" disabled={disabled} onClick={onConfirm}>{confirmLabel}</Button>\n </div>\n </div>\n )\n}\n\ntype RowMode = 'key' | 'rename' | 'remove' | 'clearKey' | undefined\n\n/** One account row: identity, status, quota summary, actions and expandable details. */\nfunction AccountItem({ row, rows, state, usage, login, disabled, pinned, t, actions }: {\n row: AccountRowModel\n rows: readonly AccountRowModel[]\n state: SettingsPageState\n usage: UsagePageState\n login: LoginPageState\n disabled: boolean\n pinned: boolean\n t: Translate<SettingsCommandCodeKey>\n actions: AccountActions\n}) {\n const [expanded, setExpanded] = useState(false)\n const [menuOpen, setMenuOpen] = useState(false)\n const [mode, setMode] = useState<RowMode>(undefined)\n const entry = row.usage\n const report = entry?.report\n const accountName = report?.account === undefined ? '' : report.account.userName || report.account.name\n const planName = report?.plan?.name ?? ''\n const credits = report?.credits\n // Only an explicit `false` means the balance was omitted (an older Host\n // never sends the flag and always sent a real number).\n const monthlyReported = credits !== undefined && credits.monthlyReported !== false\n const multi = rows.length > 1\n const loginTarget = row.ref\n const { visible: loginState, busyElsewhere } = loginStateForTarget(login, loginTarget)\n const loginBusy = loginState.phase === 'starting' || loginState.phase === 'waiting'\n const showLogin = loginState.phase !== 'idle'\n const locked = disabled || !row.managed\n const keyActions = !locked && row.keyWritable\n\n const items: MenuEntry[] = []\n if (row.managed && multi) {\n items.push(pinned\n ? { id: 'unpin', label: t('accountActionUnpin'), disabled: locked }\n : { id: 'pin', label: t('accountActionPin'), disabled: locked || !row.configured })\n }\n if (row.managed) {\n if (items.length > 0) items.push({ type: 'separator', id: 'sep-key' })\n items.push(\n { id: 'login', label: t('accountActionLogin'), disabled: !keyActions || loginBusy || busyElsewhere },\n { id: 'key', label: t('accountActionKey'), disabled: !keyActions },\n )\n if (!row.isDefault) items.push({ id: 'rename', label: t('accountActionRename'), disabled: locked })\n if (row.isDefault && row.storedKey) {\n items.push(\n { type: 'separator', id: 'sep-danger' },\n { id: 'clearKey', label: t('accountActionClearKey'), disabled: !keyActions, danger: true },\n )\n }\n if (!row.isDefault) {\n items.push(\n { type: 'separator', id: 'sep-danger' },\n { id: 'remove', label: t('accountActionRemove'), disabled: locked, danger: true },\n )\n }\n }\n\n const onAction = (id: string) => {\n setMenuOpen(false)\n if (id === 'pin') void actions.setActive(row.id)\n else if (id === 'unpin') void actions.setActive('')\n else if (id === 'login') actions.beginLogin(loginTarget)\n else if (id === 'key' || id === 'rename' || id === 'remove' || id === 'clearKey') setMode(id)\n }\n\n const models = state.accountModels[row.id] ?? []\n const ownerOf = (modelId: string): string | undefined => {\n for (const [account, list] of Object.entries(state.accountModels)) {\n if (account === row.id || !list.includes(modelId)) continue\n return rows.find((candidate) => candidate.id === account)?.label ?? account\n }\n return undefined\n }\n\n return (\n <div className={row.usage?.active ? 'cc-accountItem cc-accountItemActive' : 'cc-accountItem'}>\n <div className=\"cc-accountHead\">\n <button\n type=\"button\"\n className=\"cc-accountToggle\"\n aria-expanded={expanded}\n aria-controls={`cc-account-${row.id}-details`}\n onClick={() => setExpanded((value) => !value)}\n >\n <span className={statusDotClass(row)} title={statusDotTitle(row, t)} aria-hidden=\"true\" />\n <span className=\"cc-accountName\">{row.label}</span>\n {accountName !== '' && accountName !== row.label ? <span className=\"cc-usageAccount\">{accountName}</span> : null}\n {planName !== '' ? <span className=\"cc-usagePlan\">{planName}</span> : null}\n {entry?.active && multi ? <span className=\"cc-badge\">{t('usageActive')}</span> : null}\n {pinned ? <span className=\"cc-badge\">{t('accountStatusPinned')}</span> : null}\n {!row.credentialKnown || !row.configured ? <span className=\"cc-badgeMuted\">{t(row.credentialKnown ? 'apiKeyUnset' : 'writeStateUnknown')}</span> : null}\n {entry?.mark === 'invalid-credential' ? <span className=\"cc-usagePlanStatus\">{t('usageInvalidKey')}</span> : null}\n {entry !== undefined && entry.mark !== 'invalid-credential' && (entry.cooldownUntil > 0 || entry.mark === 'rate-limit') ? (\n <span className=\"cc-usagePlanStatus\">\n {t('usageCooldown')}{entry.cooldownUntil > 0 ? ` ${formatResetAt(entry.cooldownUntil)}` : ''}\n </span>\n ) : null}\n <span className=\"cc-spacer\" />\n <span className={expanded ? 'cc-chevron cc-chevronUp' : 'cc-chevron'} aria-hidden=\"true\" />\n </button>\n {items.length > 0 ? (\n <Menu\n open={menuOpen}\n onClose={() => setMenuOpen(false)}\n onSelect={onAction}\n items={items}\n align=\"end\"\n portal\n anchor={\n <button\n type=\"button\"\n className=\"cc-iconButton\"\n aria-label={`${row.label} — ${t('accountActions')}`}\n title={t('accountActions')}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n onClick={() => setMenuOpen((value) => !value)}\n >\n <span className=\"cc-kebab\" aria-hidden=\"true\" />\n </button>\n }\n />\n ) : null}\n </div>\n\n {credits !== undefined && (credits.fiveHour !== undefined || credits.weekly !== undefined || monthlyReported) ? (\n <div className=\"cc-accountMeters\">\n {credits.fiveHour !== undefined ? <MiniMeter label={t('usageFiveHour')} limit={credits.fiveHour} /> : null}\n {credits.weekly !== undefined ? <MiniMeter label={t('usageWeekly')} limit={credits.weekly} /> : null}\n {monthlyReported ? (\n <MonthlyBalance label={t('usageMonthlyLeft')} remaining={credits.monthlyCredits} />\n ) : null}\n </div>\n ) : null}\n\n {row.credentialKnown && !row.configured && row.managed && mode === undefined && !showLogin ? (\n <div className=\"cc-accountSetup\">\n <p className=\"cc-hint\">{row.keyWritable ? t('accountNoKeyHint') : t('apiKeyLocked')}</p>\n {keyActions ? (\n <div className=\"cc-inlineActions\">\n <Button variant=\"primary\" size=\"sm\" disabled={loginBusy || busyElsewhere} onClick={() => actions.beginLogin(loginTarget)}>\n {t('accountAddLogin')}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setMode('key')}>{t('accountAddPaste')}</Button>\n </div>\n ) : null}\n </div>\n ) : null}\n\n {showLogin ? <LoginStatus state={loginState} t={t} onCancel={actions.cancelLogin} /> : null}\n\n {mode === 'key' ? (\n <InlineInput\n id={`cc-account-${row.id}-key`}\n label={t('accountKeyPlaceholder')}\n secret\n placeholder={t('accountKeyPlaceholder')}\n confirmLabel={t('accountApply')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onSubmit={(value) => {\n void actions.setKey(row.id, value).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n {mode === 'rename' && row.ref !== undefined ? (\n <InlineInput\n id={`cc-account-${row.id}-rename`}\n label={t('accountActionRename')}\n initial={row.label}\n confirmLabel={t('accountApply')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onSubmit={(value) => {\n void actions.rename(row.ref!, value).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n {mode === 'remove' && row.ref !== undefined ? (\n <ConfirmBar\n text={t('accountRemoveConfirm', { name: row.label })}\n confirmLabel={t('accountConfirmRemove')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onConfirm={() => {\n void actions.remove(row.ref!).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n {mode === 'clearKey' ? (\n <ConfirmBar\n text={t('accountClearKeyConfirm')}\n confirmLabel={t('accountConfirmClear')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onConfirm={() => {\n void actions.clearKey(row.id).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n\n {expanded ? (\n <div id={`cc-account-${row.id}-details`} className=\"cc-accountDetails\">\n {entry !== undefined ? (\n <AccountReport entry={entry} fetchedAt={usage.fetchedAt} t={t} headless />\n ) : (\n <p className=\"cc-usageHint\">{usage.status === 'loading' ? t('usageLoading') : t('usageUnconfigured')}</p>\n )}\n {multi && row.managed ? (\n <SettingRow\n className=\"cc-rowFlush\"\n title={t('accountModels')}\n titleFor={`cc-account-${row.id}-models`}\n description={t('accountModelsHint')}\n error={state.catalogFailed ? t('modelCatalogFailed') : undefined}\n control={\n <ModelMultiSelect\n id={`cc-account-${row.id}-models`}\n selected={models}\n catalog={state.catalogModels}\n disabled={disabled || state.accountBusy}\n deferCommit\n ownerOf={ownerOf}\n t={t}\n onSelect={(ids) => void actions.setModels(row.id, ids)}\n />\n }\n />\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n\n/** The live status of one browser sign-in: link while waiting, outcome after. */\nfunction LoginStatus({ state, t, onCancel }: {\n state: LoginPageState\n t: Translate<SettingsCommandCodeKey>\n onCancel(): void\n}) {\n const hint = loginHint(state, t)\n const busy = state.phase === 'starting' || state.phase === 'waiting'\n return (\n <div className=\"cc-loginStatus\" role=\"status\">\n <p className={hint.className} title={hint.title}>{hint.text}</p>\n {state.authUrl !== undefined ? (\n <a className=\"cc-loginLink\" href={state.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n ) : null}\n {busy ? <button type=\"button\" className=\"cc-reset\" onClick={onCancel}>{t('loginCancel')}</button> : null}\n </div>\n )\n}\n\n/** The immediate account operations the list and its rows call. */\ninterface AccountActions {\n refreshCredentials(): void\n cleanup(ref: string): Promise<boolean>\n rename(ref: string, label: string): Promise<boolean>\n remove(ref: string): Promise<boolean>\n setKey(target: string, key: string): Promise<boolean>\n clearKey(target: string): Promise<boolean>\n setActive(id: string): Promise<boolean>\n setModels(target: string, ids: string[]): Promise<boolean>\n beginLogin(targetRef?: string): void\n cancelLogin(): void\n}\n\n/** 新增面板只负责输入和操作意图;账号、登录、命名与补偿由宿主过程负责。 */\nfunction AddAccountPanel({ state, disabled, t, enrollment, snapshot, onClose }: {\n state: SettingsPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n enrollment: AccountEnrollmentController\n snapshot: EnrollmentPageState\n onClose(): void\n}) {\n const [label, setLabel] = useState('')\n const [pasting, setPasting] = useState(false)\n const active = snapshot.active\n const busy = active !== undefined && ['creating', 'waiting', 'writing', 'cancelling', 'naming'].includes(active.phase)\n const fallbackName = t('accountNameN', { n: state.accounts.length + 2 })\n useEffect(() => { if (active?.phase === 'finished') onClose() }, [active?.phase, onClose])\n const start = (key?: string) => enrollment.begin({ mode: key === undefined ? 'browser' : 'manual',\n label: label.trim() || fallbackName, automaticName: label.trim() === '', ...(key === undefined ? {} : { key }) })\n const close = () => { enrollment.cancel(); onClose() }\n return (\n <div className=\"cc-addPanel\" aria-label={t('accountAdd')}>\n <span className=\"cc-panelTitle\">{t('accountAdd')}</span>\n <input className=\"cc-input\" type=\"text\" aria-label={t('accountNamePlaceholder')} placeholder={t('accountNamePlaceholder')}\n value={label} disabled={disabled || busy} onChange={(event) => setLabel(event.target.value)} />\n {active ? <p className=\"cc-hint\" role=\"status\">{active.message}</p> : null}\n {active?.authUrl && active.phase === 'waiting' ? <p className=\"cc-hint\">若登录页面未自动打开,请点击下方链接。</p> : null}\n {active?.authUrl && active.phase === 'waiting' ? <a className=\"cc-linkButton\" href={active.authUrl} target=\"_blank\" rel=\"noreferrer\">打开浏览器登录</a> : null}\n {snapshot.error ? <p className=\"cc-loginError\" role=\"status\">{snapshot.error}</p> : null}\n {active?.phase === 'naming' ? (\n <div className=\"cc-inlineActions\">\n <Button variant=\"primary\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.name(active.suggestedName || label || fallbackName)}>重试保存名称</Button>\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.name()}>接受已有名称</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>{t('cancel')}</Button>\n </div>\n ) : pasting ? (\n <InlineInput id=\"cc-add-account-key\" label={t('accountKeyPlaceholder')} secret placeholder={t('accountKeyPlaceholder')}\n confirmLabel={t('accountAddConfirm')} disabled={disabled || busy} t={t}\n onCancel={close} onSubmit={(key) => { void start(key) }} />\n ) : (\n <div className=\"cc-inlineActions\">\n <Button variant=\"primary\" size=\"sm\" disabled={disabled || busy} onClick={() => void start()}>{t('accountAddLogin')}</Button>\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled || busy} onClick={() => setPasting(true)}>{t('accountAddPaste')}</Button>\n <span className=\"cc-spacer\" />\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>{t('cancel')}</Button>\n </div>\n )}\n {busy && active?.phase !== 'naming' && pasting ? <Button variant=\"ghost\" size=\"sm\" onClick={close}>取消开通</Button> : null}\n </div>\n )\n}\n\n/**\n * The unified account card: every account the pool rotates through, one row\n * each, with its status and quota inline — so one account's facts no longer\n * have to be cross-read across separate surfaces.\n */\nfunction AccountsCard({ t, state, usage, login, disabled, actions, onRefresh, createEnrollment }: {\n t: Translate<SettingsCommandCodeKey>\n state: SettingsPageState\n usage: UsagePageState\n login: LoginPageState\n disabled: boolean\n actions: AccountActions\n onRefresh(): void\n createEnrollment(): AccountEnrollmentController\n}) {\n const [adding, setAdding] = useState(false)\n const [enrollment] = useState(createEnrollment)\n const snapshot = useSyncExternalStore(enrollment.store.subscribe, enrollment.store.getSnapshot)\n useEffect(() => { enrollment.activate(); return () => enrollment.dispose() }, [enrollment])\n const closeAdd = useCallback(() => setAdding(false), [])\n const { loading, shouldRefresh } = usageCardState(usage)\n // Ask the Host on first paint: CLI auth and composition keys are not\n // represented by browser credential references.\n useEffect(() => {\n if (shouldRefresh) onRefresh()\n }, [shouldRefresh, onRefresh])\n const rows = accountRows(state, usage, t).filter((row) => row.ref === undefined || !state.accountEnrollmentRefs.includes(row.ref))\n const multi = rows.length > 1\n const pinnedRow = rows.find((row) => row.id === state.activeAccount)\n return (\n <section className=\"cc-group\" aria-label={t('accountsTitle')}>\n <div className=\"cc-groupHead\">\n <h3 className=\"cc-groupTitle\">{t('accountsTitle')}</h3>\n <span className=\"cc-spacer\" />\n <button type=\"button\" className=\"cc-linkButton\" disabled={loading} onClick={() => { onRefresh(); void enrollment.refresh() }}>\n {loading ? t('usageRefreshing') : t('usageRefresh')}\n </button>\n </div>\n <p className=\"cc-groupDesc\">{multi ? t('accountsRotationHint') : t('accountsHint')}</p>\n {multi ? (\n <div className=\"cc-accountMode\">\n <span>{pinnedRow !== undefined ? t('accountModePinned', { name: pinnedRow.label }) : t('accountModeAuto')}</span>\n {pinnedRow !== undefined ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled || state.accountBusy} onClick={() => void actions.setActive('')}>\n {t('accountActionUnpin')}\n </button>\n ) : null}\n </div>\n ) : null}\n {usage.status === 'error' ? (\n <p className=\"cc-rowError\" role=\"status\">\n {t('usageError')}{usage.error !== undefined && usage.error !== '' ? ` — ${usage.error}` : ''}\n </p>\n ) : null}\n {settingsWriteNotice(state.accountResult, t) || state.accountFailed !== undefined ? <p className=\"cc-rowError\" role=\"status\">{settingsWriteNotice(state.accountResult, t) || t('accountOpFailed')}</p> : null}\n {state.credentialRefreshFailed || state.accountResult?.refreshFailed || state.saveResult?.refreshFailed ? <div className=\"cc-rowError\" role=\"status\"><p>{t('writeRefreshFailed')}</p><button type=\"button\" className=\"cc-btn cc-btnSm\" onClick={actions.refreshCredentials}>{t('writeRefreshRetry')}</button></div> : null}\n {!adding && snapshot.error ? <p className=\"cc-rowError\" role=\"status\">{snapshot.error}</p> : null}\n {state.pendingCredentialCleanup.length > 0 ? (\n <div className=\"cc-rowError\" role=\"status\">\n <p>{t('accountCleanupPending')}</p>\n <button type=\"button\" className=\"cc-btn cc-btnSm\" disabled={disabled || state.accountBusy}\n onClick={() => { for (const ref of state.pendingCredentialCleanup) void actions.cleanup(ref) }}>\n {t('accountCleanupRetry')}\n </button>\n </div>\n ) : null}\n {snapshot.pending.filter((record) => record.id !== snapshot.active?.id).map((record) => (\n <div className=\"cc-rowError\" role=\"status\" key={record.id}>\n <p>{record.ref}:{record.message}</p>\n {record.phase === 'naming' && record.suggestedName ? (\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.recover(record, record.suggestedName)}>重试保存名称</Button>\n ) : null}\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.recover(record)}>\n {record.phase === 'naming' ? '接受已有名称' : '重试清理'}\n </Button>\n </div>\n ))}\n {snapshot.active?.phase === 'cleanup-needed' ? (\n <div className=\"cc-rowError\" role=\"status\">\n <p>{snapshot.active.message}</p>\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.recover(snapshot.active!)}>重试清理</Button>\n </div>\n ) : null}\n <div className=\"cc-accountList\">\n {rows.map((row) => (\n <AccountItem\n key={row.id}\n row={row}\n rows={rows}\n state={state}\n usage={usage}\n login={login}\n disabled={disabled}\n pinned={state.activeAccount === row.id}\n t={t}\n actions={actions}\n />\n ))}\n </div>\n {adding ? (\n <AddAccountPanel\n state={state}\n disabled={disabled}\n t={t}\n enrollment={enrollment}\n snapshot={snapshot}\n onClose={closeAdd}\n />\n ) : (\n <button type=\"button\" className=\"cc-addButton\" disabled={disabled} onClick={() => { enrollment.reset(); setAdding(true) }}>\n <span className=\"cc-addGlyph\" aria-hidden=\"true\" />\n {t('accountAdd')}\n </button>\n )}\n </section>\n )\n}\n\n/**\n * Show the save bar's \"saved\" confirmation 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 // The count lives in the shared controller and outlives this component, so\n // a remount (switching settings pages, reopening settings) sees a non-zero\n // count it did not witness. Only a save landing while mounted may flash.\n const seen = useRef(tick)\n useEffect(() => {\n if (tick === seen.current) return\n seen.current = tick\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\ntype SaveBarTone = 'pending' | 'error' | 'success'\n\ninterface SaveBarView {\n visible: boolean\n tone: SaveBarTone\n message: string\n /** Whether Discard/Save apply (hidden while only the saved confirmation shows). */\n actions: boolean\n}\n\n/**\n * What the save bar says. It exists only while there is something to act on\n * or to confirm: pending edits, a save in flight, a failure, or the brief\n * confirmation after a save landed. Account operations never reach it, they\n * commit on their own.\n */\nfunction saveBarView(state: SettingsPageState, savedVisible: boolean, t: Translate<SettingsCommandCodeKey>): SaveBarView {\n const notice = settingsWriteNotice(state.saveResult, t)\n if (notice) return { visible: true, tone: state.failed ? 'error' : 'pending', message: notice, actions: state.dirty || state.failed }\n if (state.failed) return { visible: true, tone: 'error', message: t('saveFailed'), actions: state.dirty || state.failed }\n if (state.dirty || state.saving) {\n return state.invalid\n ? { visible: true, tone: 'error', message: t('saveInvalid'), actions: true }\n : { visible: true, tone: 'pending', message: t('unsavedChanges'), actions: true }\n }\n if (savedVisible) return { visible: true, tone: 'success', message: t('saved'), actions: false }\n return { visible: false, tone: 'success', message: '', actions: false }\n}\n\n/** The save bar's leading status mark: a soft dot while pending, a glyph once there is an outcome. */\nfunction SaveBarIcon({ tone }: { tone: SaveBarTone }) {\n if (tone === 'pending') return <span className=\"cc-saveBarIcon\" aria-hidden=\"true\"><span className=\"cc-saveBarPulse\" /></span>\n return (\n <span className=\"cc-saveBarIcon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" />\n {tone === 'success' ? <path d=\"M5.2 8.2l1.9 1.9 3.7-3.9\" /> : <path d=\"M8 4.8v3.6M8 11.1v.1\" />}\n </svg>\n </span>\n )\n}\n\n/**\n * The floating save bar: pinned to the bottom of the settings scrollport and\n * slid out of view when there is nothing to save. It stays mounted so it can\n * animate out, and keeps showing its last message while it does (the state\n * that hid it has no message of its own).\n */\nfunction SaveBar({ view, state, t, onDiscard, onSave }: {\n view: SaveBarView\n state: SettingsPageState\n t: Translate<SettingsCommandCodeKey>\n onDiscard(): void\n onSave(): void\n}) {\n const last = useRef(view)\n if (view.visible) last.current = view\n const shown = view.visible ? view : last.current\n return (\n <div className=\"cc-saveBarDock\">\n <div\n className={`cc-saveBar cc-saveBar-${shown.tone}${view.visible ? ' cc-saveBarShown' : ''}`}\n role=\"region\"\n aria-label={t('save')}\n aria-hidden={!view.visible}\n >\n <SaveBarIcon tone={shown.tone} />\n <p className=\"cc-saveBarText\" role=\"status\" aria-live=\"polite\" title={shown.message}>{shown.message}</p>\n {shown.actions ? (\n <div className=\"cc-saveBarActions\">\n {/* Own buttons rather than the primitives: they are sized to sit\n concentrically inside the bar (see .cc-saveBar). */}\n <button\n type=\"button\"\n className=\"cc-saveBarButton cc-saveBarGhost\"\n disabled={!view.visible || (!state.dirty && !state.failed) || state.saving}\n onClick={onDiscard}\n >\n {t('discard')}\n </button>\n <button\n type=\"button\"\n className=\"cc-saveBarButton cc-saveBarPrimary\"\n disabled={!view.visible || !state.dirty || state.invalid || state.saving}\n onClick={onSave}\n >\n {t(state.saving ? 'saving' : 'save')}\n </button>\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n\n/** The settings page body: accounts, then the staged provider settings. */\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 savedVisible = useSavedFlash(state.savedCount)\n const updateVersion = usePluginUpdate()\n // 账号行共享稳定的操作对象;新增账号的过程则由页面自己的控制器持有。\n const {\n renameAccount, removeAccount, retryCredentialCleanup, setAccountKey, clearAccountKey,\n setActiveAccount, setAccountModels, beginLogin, cancelLogin, refreshCredentials,\n } = props\n const actions = useMemo<AccountActions>(() => ({\n rename: renameAccount,\n remove: removeAccount,\n cleanup: retryCredentialCleanup,\n refreshCredentials,\n setKey: setAccountKey,\n clearKey: clearAccountKey,\n setActive: setActiveAccount,\n setModels: setAccountModels,\n beginLogin,\n cancelLogin,\n }), [renameAccount, removeAccount, retryCredentialCleanup, setAccountKey, clearAccountKey, setActiveAccount, setAccountModels, beginLogin, cancelLogin, refreshCredentials])\n const bar = saveBarView(state, savedVisible, t)\n const form = { state, disabled, t, onEdit: props.edit, onReset: props.resetField }\n return (\n <section className={bar.visible ? 'cc-section cc-sectionWithBar' : 'cc-section'} aria-label={t('title')}>\n <h2 className=\"cc-title\">{t('title')}</h2>\n <p className=\"cc-intro\">{t('intro')}</p>\n {props.openAnalytics ? <Button variant=\"ghost\" size=\"sm\" onClick={props.openAnalytics}>{t('openAnalytics')}</Button> : null}\n {!state.writable ? <p className=\"cc-readOnly\" role=\"status\">{t('readOnly')}</p> : null}\n <AccountsCard\n t={t}\n state={state}\n usage={usage}\n login={login}\n disabled={disabled}\n actions={actions}\n onRefresh={props.refreshUsage}\n createEnrollment={props.createEnrollment}\n />\n <ModelsCard {...form} onSelect={props.editVisibleModels} onClear={props.clearVisibleModels} />\n <PrivacyCard {...form} />\n <IntegrationsCard {...form} />\n <AdvancedSection {...form} />\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 <SaveBar view={bar} state={state} t={t} onDiscard={props.discard} onSave={props.save} />\n </section>\n )\n}\n","/**\n * The shared login row: one field row that starts the Host-side browser login,\n * links to the Studio authorization page while the attempt is live, and reports\n * the outcome. Rendered by BOTH the settings page (`section.tsx`) and the\n * Models-page provider card (`card.tsx`) so the two surfaces share one\n * component and one hint state machine — whose copy/class logic lives in the\n * JSX-free `./login.ts` (`loginHint`/`loginFailureCopy`) so node tests can drive\n * every phase. This file only renders it.\n *\n * @module dsh-commandcode-provider/client/login-row\n */\n\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsCommandCodeKey } from './locales.ts'\nimport { loginHint, loginStateForTarget } from './login.ts'\nimport type { LoginPageState } from './login.ts'\n\n/** One login row's props (same face both surfaces supply). */\nexport interface LoginRowProps {\n state: LoginPageState\n /** Only the matching attempt appears in this row; omitted means default. */\n targetRef?: string\n disabled: boolean\n disabledHint?: string | undefined\n t: Translate<SettingsCommandCodeKey>\n onBegin(): void\n onCancel(): void\n}\n\nexport function LoginRow({ state, targetRef, disabled, disabledHint, t, onBegin, onCancel }: LoginRowProps) {\n const { visible: visibleState, busyElsewhere } = loginStateForTarget(state, targetRef)\n const busy = visibleState.phase === 'starting' || visibleState.phase === 'waiting'\n const hint = loginHint(visibleState, t)\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 || busyElsewhere} onClick={onBegin}>{t('loginButton')}</button>\n )}\n </span>\n </div>\n {visibleState.authUrl !== undefined ? (\n <p className=\"cc-hint\">\n <a className=\"cc-loginLink\" href={visibleState.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n </p>\n ) : null}\n <p className={hint.className} title={hint.title}>{disabled && !busy && disabledHint !== undefined ? disabledHint : hint.text}</p>\n </div>\n )\n}\n","/**\n * The Command Code configuration panel inside the harness Models settings page,\n * rendered through the `settings.models.provider-card` keyed slot 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 per provider row through its own\n * 编辑 button, and for a namespace it curates no layout for (`llm-commandcode`)\n * that editor is a bare shell: a config hint over a permanently disabled apply.\n * This panel takes its place — it watches the slot outlet's siblings and, while\n * the official editor is open, hides the useless shell and shows the real\n * controls in its slot (credential/route badges, API-key field, sign-in,\n * discard/save). Closed, it renders nothing and the row looks exactly like any\n * other provider row.\n *\n * The slot's owner props (`configured`, `keyConfigured`) mirror what the Models\n * page already knows; the authoritative credential facts still come from this\n * plugin's `CommandCodeSettingsController` — shared with the dedicated settings\n * page, so the two surfaces can never disagree about whether a key is stored.\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. Styles ride the page stylesheet the client entry injects\n * once; 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 { settingsWriteNotice, type SettingsCommandCodeKey } from './locales.ts'\nimport type { SettingsPageState, StagedField } from './settings.ts'\nimport type { LoginPageState } from './login.ts'\nimport { LoginRow } from './login-row.tsx'\n\n/**\n * The Models-page extension slots, merged into the SlotMap with the exact\n * declarations ui-settings-models ships. The merge must stay structurally\n * identical to upstream's (kind/scope/owner), or a dsh carrying its own\n * declaration would fail the duplicate-merge check at 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 readonly displayName: string\n /** The settings namespace the row configures (the slot's dispatch key). */\n readonly settingsNs: string\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 and add-provider\n * cards, where it is always open. The editor is the only such sibling whose\n * CSS module class carries the `editor` stem (`<hash>_editor`); the row header\n * and the add card's provider select never do, so the lookup needs no hash\n * 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 refreshCredentials(): 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/**\n * Decide the card's posture from one settings snapshot. Pure: the component\n * subscribes once and passes the snapshot in, so hook order never depends\n * on the registration→live transition. (The owner facts stay on the\n * component — only the snapshot decides the posture.)\n */\nexport function cardMode(\n snapshot: SettingsPageState | undefined,\n): CardMode {\n if (snapshot === undefined) return { kind: 'registration' }\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/** Credential-state badge: the solid pill when set, the muted outline when not. */\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/** The key paste field, with the show/hide toggle over it. */\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=\"new-password\"\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, add-provider draft).\n *\n * Closed (the official 编辑 toggle off) it renders nothing: the row head the\n * Models page owns already names the provider and shows the credential dot, so\n * a page full of providers stays compact. Open, it hides that editor shell and\n * shows the real controls — badges, API-key field, sign-in, discard/save.\n */\nexport function CommandCodeProviderCard(props: CommandCodeCardProps & ProviderCardOwnerProps) {\n const { t } = props\n // Single subscription: the whole snapshot drives posture + body together.\n const state = props.useCommandCodeSettings !== undefined\n ? props.useCommandCodeSettings((snapshot) => snapshot)\n : undefined\n const mode = cardMode(state)\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 notice = settingsWriteNotice(state?.saveResult, t) || (state?.failed ? t('saveFailed') : '')\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 stable\n // neighbor, so watch ITS siblings for the editor's mount/unmount. The outlet\n // stays mounted either way — it is the observation anchor — so the closed\n // 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 the\n // 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: it is\n // 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(state.apiKeyKnown ? 'apiKeyUnset' : 'writeStateUnknown')} />\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 <LoginRow\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 {notice ? <p className=\"cc-failed\" role=\"status\">{notice}</p> : null}\n {state?.credentialRefreshFailed || state?.saveResult?.refreshFailed ? <button type=\"button\" className=\"cc-reset\" onClick={props.refreshCredentials}>{t('writeRefreshRetry')}</button> : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={(!dirty && !state?.failed) || 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","/** 模型分析沿用宿主语言;每个数值有独立标签,缺失样本与试算前提必须可见。 */\nexport const ANALYTICS_COPY_ZH = {\n analyticsNav: '模型分析', quotaNav: '账号额度',\n analysisRecent: '最近会话', analysisRange: '指定时间', analysisLimit: '会话数量', analysisFrom: '开始日期', analysisTo: '结束日期', analysisApply: '读取统计',\n analysisLoading: '正在读取历史记录…', analysisUnavailable: '宿主未提供历史查询服务,无法统计关闭后的会话。', analysisEmpty: '所选范围内没有 Command Code 请求记录。',\n analysisInvalid: '请输入 1–100 个会话,或不超过 366 天的有效日期范围。', analysisScope: '统计范围', analysisScanned: '已读取会话', analysisMatched: '含请求会话', analysisUnreadable: '读取失败', analysisSkipped: '已跳过',\n analysisPartial: '结果不完整:历史超过读取上限,或部分记录不可读。金额只覆盖已读取且可计价的请求。', analysisCatalog: '模型目录暂不可用,历史统计仍可查看。',\n analysisUnpriced: '部分请求缺少用量或价格,金额与词元仅为已知小计。展开明细可查看样本覆盖。',\n analysisOverview: '用量总览', analysisSections: '分析内容', analysisHistory: '历史用量', analysisSimulation: '价格试算', analysisByModel: '按模型查看', analysisModelHint: '展开模型,查看词元、请求状态与样本。',\n analysisCost: '已知成本 · 美元', analysisRequests: '模型请求', analysisSessionCount: '会话数', analysisResponse: '平均响应', analysisFirstToken: '平均首词元', analysisSpeed: '输出速度', analysisSeconds: '秒', analysisSpeedUnit: '词元/秒',\n analysisPriced: '计价请求', analysisTimed: '响应样本', analysisFirstTokenSamples: '首词元样本', analysisDecodeSamples: '解码样本', analysisUsageSamples: '用量样本', analysisAverage: '每会话均摊', analysisMissing: '无数据',\n analysisDetails: '查看汇总明细', analysisTokens: '词元与缓存', analysisInput: '未缓存输入', analysisOutput: '输出', analysisCacheRead: '缓存读取', analysisCacheWrite: '缓存写入',\n analysisOutcome: '请求状态', analysisCompleted: '完成', analysisFailed: '失败', analysisRetries: '宿主重试', analysisCancelled: '取消', analysisUnknown: '未知状态', analysisSamples: '统计样本', analysisSessionCost: '会话与成本',\n analysisMonthly: '按该时间段折算 30 天', analysisMonthlyHint: '仅完整、全部计价且跨度至少一天的日期范围提供折算。',\n analysisRules: '统计口径与试算说明', analysisShortBasis: '按当前价格估算,非历史账单。缺失用量与耗时不会补零。',\n analysisBasis: '按当前价格快照重算;不是历史账单,不含订阅费和充值,词元用量不等于账号积分。仅有请求数量、没有任务边界;不计算任务质量或智能评分。旧记录缺失的用量和耗时不会补零。',\n analysisAssumption: '沿用原请求的词元与时段,对比不同模型的价格。换模型后的生成长度、缓存命中、重试和质量可能变化;不会调用模型或自动推荐。',\n analysisContext: '上下文词元', analysisCapabilities: '模型能力', analysisEfforts: '推理力度', analysisExcluded: '超出上下文', analysisUnknownPrice: '未知用量或价格', analysisSearch: '筛选试算模型', analysisSearchPlaceholder: '输入模型名称或标识', analysisNoMatches: '没有匹配的模型,请调整筛选条件。',\n analysisImages: '支持图片', analysisTextOnly: '仅文本', analysisNoEfforts: '未提供推理力度',\n analysisCoverageHint: '耗时从步骤或重试开始计至模型结算;包含前置处理,不含后续工具执行。首词元包含推理与工具参数。速度按有解码计时的输出词元总量计算。试算未校验图片及工具兼容性,也不代表账号已获授权。',\n effortNone: '关闭 (none)', effortLow: '低 (low)', effortMedium: '中 (medium)', effortHigh: '高 (high)', effortXhigh: '极高 (xhigh)', effortMax: '最高 (max)',\n} as const\nexport type AnalyticsKey = keyof typeof ANALYTICS_COPY_ZH\n/** 按项目约定,错误、缺失与读取状态在各语言环境中统一为中文。 */\nexport const ANALYTICS_COPY_EN: Record<AnalyticsKey, string> = {\n analyticsNav: 'Model analysis', quotaNav: 'Account quota',\n analysisRecent: 'Recent sessions', analysisRange: 'Date range', analysisLimit: 'Session count', analysisFrom: 'Start date', analysisTo: 'End date', analysisApply: 'Read statistics',\n analysisLoading: ANALYTICS_COPY_ZH.analysisLoading, analysisUnavailable: ANALYTICS_COPY_ZH.analysisUnavailable, analysisEmpty: ANALYTICS_COPY_ZH.analysisEmpty,\n analysisInvalid: ANALYTICS_COPY_ZH.analysisInvalid, analysisScope: 'Scope', analysisScanned: 'Sessions read', analysisMatched: 'Sessions with requests', analysisUnreadable: 'Read failures', analysisSkipped: 'Skipped',\n analysisPartial: ANALYTICS_COPY_ZH.analysisPartial, analysisCatalog: ANALYTICS_COPY_ZH.analysisCatalog,\n analysisUnpriced: ANALYTICS_COPY_ZH.analysisUnpriced,\n analysisOverview: 'Usage overview', analysisSections: 'Analysis sections', analysisHistory: 'Recorded usage', analysisSimulation: 'Price simulation', analysisByModel: 'Usage by model', analysisModelHint: 'Expand a model for tokens, request outcomes and samples.',\n analysisCost: 'Known cost · USD', analysisRequests: 'Model requests', analysisSessionCount: 'Sessions', analysisResponse: 'Mean response', analysisFirstToken: 'Mean first token', analysisSpeed: 'Output speed', analysisSeconds: 's', analysisSpeedUnit: 'tokens/s',\n analysisPriced: 'Priced requests', analysisTimed: 'Response samples', analysisFirstTokenSamples: 'First-token samples', analysisDecodeSamples: 'Decode samples', analysisUsageSamples: 'Usage samples', analysisAverage: 'Per session', analysisMissing: ANALYTICS_COPY_ZH.analysisMissing,\n analysisDetails: 'View aggregate details', analysisTokens: 'Tokens and cache', analysisInput: 'Uncached input', analysisOutput: 'Output', analysisCacheRead: 'Cache read', analysisCacheWrite: 'Cache write',\n analysisOutcome: 'Request outcomes', analysisCompleted: 'Completed', analysisFailed: 'Failed', analysisRetries: 'Host retries', analysisCancelled: 'Cancelled', analysisUnknown: 'Unknown outcome', analysisSamples: 'Samples', analysisSessionCost: 'Sessions and cost',\n analysisMonthly: '30-day extrapolation from this range', analysisMonthlyHint: 'Requires a complete, fully priced date range spanning at least one day.',\n analysisRules: 'Statistics and simulation notes', analysisShortBasis: 'Estimated at current prices, not an invoice. Missing usage and timing stay unknown.',\n analysisBasis: 'Repriced with the current snapshot; not an invoice. Excludes subscriptions and top-ups. Tokens are not account credits. Requests have no task boundaries; no task quality or intelligence scores. Missing usage and timing stay unknown.',\n analysisAssumption: 'Compares model prices using original tokens and request times. Output length, cache hits, retries and quality may change with another model. Makes no model calls or automatic recommendations.',\n analysisContext: 'Context tokens', analysisCapabilities: 'Model capabilities', analysisEfforts: 'Reasoning efforts', analysisExcluded: 'Over context limit', analysisUnknownPrice: 'Unknown usage or price', analysisSearch: 'Filter simulation models', analysisSearchPlaceholder: 'Model name or ID', analysisNoMatches: ANALYTICS_COPY_ZH.analysisNoMatches,\n analysisImages: 'Images supported', analysisTextOnly: 'Text only', analysisNoEfforts: 'No reasoning efforts listed',\n analysisCoverageHint: 'Response time runs from step/retry start to model settlement, includes preparation and excludes subsequent tools. First token includes reasoning and tool arguments. Speed uses output tokens with decode timing. Simulation does not validate image/tool compatibility or prove account entitlement.',\n effortNone: 'None', effortLow: 'Low', effortMedium: 'Medium', effortHigh: 'High', effortXhigh: 'Extra high', effortMax: 'Max',\n}\n","/**\n * Bilingual copy for the Command Code **plans & quota panel** (the sidebar\n * footer card and the center-column dashboard it opens).\n *\n * The panel follows the harness's active language: `PANEL_LOCALE_NS` is a\n * registered locale namespace (`ctx.locale.register`), both panel slot\n * registrations declare it, and the renderer hands the component a `t` seat\n * whose identity changes on a language switch (so a memoized panel re-renders).\n * {@link buildPanelView} takes that translator as an input and builds every\n * string through it, so the projection stays React-free and testable and no\n * component carries copy of its own. The settings page keeps its own\n * `settings.commandcode` namespace (see `./locales.ts`); the two never mix.\n *\n * @module dsh-commandcode-provider/client/panel-copy\n */\n\nimport { ANALYTICS_COPY_ZH, ANALYTICS_COPY_EN, type AnalyticsKey } from './analytics-copy.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Copy of the plans & quota panel (footer card + dashboard). */\n 'panel.commandcode': PanelKey\n }\n}\n\n/**\n * The plans & quota panel key set. `zh` is the source of truth for the key set\n * (repo convention); en must carry the exact same keys — a mismatch is a\n * compile error at the register site.\n */\nexport type PanelKey =\n | AnalyticsKey\n /** Footer card title and panel heading. */\n | 'nav'\n /** Panel sub-heading under the title. */\n | 'subtitle'\n /** Refresh button / in-flight label. */\n | 'refresh'\n | 'refreshing'\n /** Dashboard exit: the button's accessible name and its tooltip. */\n | 'close'\n | 'closeHint'\n /** First-paint fetch. */\n | 'loading'\n /** No credential at all: how to get one. */\n | 'noKey'\n | 'noKeyHint'\n /** Report section headings. */\n | 'plan'\n | 'credits'\n | 'limits'\n | 'usage'\n /** Monthly credit state and its tiles. */\n | 'monthly'\n | 'monthlyLimit'\n | 'monthlyUsed'\n | 'remaining'\n | 'purchased'\n | 'free'\n /** Usage-window rows (long labels in the dashboard, short in the footer). */\n | 'fiveHour'\n | 'weekly'\n | 'fiveHourShort'\n | 'weeklyShort'\n | 'windowUnlimited'\n | 'exceeded'\n | 'exhausted'\n | 'resets'\n /** Usage tiles. */\n | 'requests'\n | 'failed'\n | 'successRate'\n | 'spend'\n | 'tokens'\n | 'tokensIn'\n | 'tokensOut'\n /** Meta line. */\n | 'periodEnds'\n | 'updated'\n | 'partial'\n /** Rotation state on an account. */\n | 'active'\n | 'coolingDown'\n | 'invalidKey'\n /** Footer-card plan fallbacks. */\n | 'unconfigured'\n | 'unavailable'\n /** Whole-report failures (mirrors the settings card's blocked taxonomy). */\n | 'errorInvalidKey'\n | 'errorInvalidKeyHint'\n | 'errorServiceUnavailable'\n | 'errorServiceUnavailableHint'\n | 'errorNetwork'\n | 'errorNetworkHint'\n | 'errorInvalidResponse'\n | 'errorInvalidResponseHint'\n /** A fetch that failed for any other reason. */\n | 'errorGeneric'\n\n/** The locale namespace both panel slots bind their `t` seat to. */\nexport const PANEL_LOCALE_NS = 'panel.commandcode'\n\n/** A panel translator: one key in, one localized string out. */\nexport type PanelTranslator = (key: PanelKey) => string\n\n/** The panel's Simplified Chinese string table (the key-set source of truth). */\nexport const PANEL_COPY_ZH: Record<PanelKey, string> = {\n ...ANALYTICS_COPY_ZH,\n nav: 'Command Code',\n subtitle: '套餐、额度与配额窗口',\n refresh: '刷新',\n refreshing: '刷新中…',\n close: '关闭',\n closeHint: '返回会话',\n loading: '正在获取账户用量…',\n noKey: '尚未配置 API 密钥',\n noKeyHint: '在 设置 → Command Code 中粘贴密钥或登录后,点击刷新。',\n plan: '套餐',\n credits: '额度',\n limits: '配额窗口',\n usage: '用量',\n monthly: '月额度',\n monthlyLimit: '月额度上限',\n monthlyUsed: '本月已用',\n remaining: '剩余',\n purchased: '已购',\n free: '赠送',\n fiveHour: '5 小时窗口',\n weekly: '每周窗口',\n fiveHourShort: '5 小时',\n weeklyShort: '每周',\n windowUnlimited: '不限',\n exceeded: '已超限',\n exhausted: '已用尽',\n resets: '重置于',\n requests: '请求',\n failed: '失败',\n successRate: '成功率',\n spend: '花费',\n tokens: 'Token',\n tokensIn: '入',\n tokensOut: '出',\n periodEnds: '账期截止',\n updated: '更新于',\n partial: '部分端点数据不可用',\n active: '当前使用',\n coolingDown: '限额冷却中',\n invalidKey: '密钥无效',\n unconfigured: '未配置',\n unavailable: '无数据',\n errorInvalidKey: 'API 密钥无效或已过期',\n errorInvalidKeyHint: '服务端拒绝了全部请求(401)。请检查该账户的密钥,或到 commandcode.ai 控制台重新生成。',\n errorServiceUnavailable: 'Command Code 服务暂时不可用',\n errorServiceUnavailableHint: '服务端返回错误(5xx),请稍后点击刷新重试。',\n errorNetwork: '无法连接 Command Code 服务',\n errorNetworkHint: '所有请求都没有到达服务端。请检查网络连接或 API 地址设置。',\n errorInvalidResponse: 'Command Code 响应无法读取',\n errorInvalidResponseHint: '已收到响应,但正文读取或解析失败。下方详情可区分读取超时、中断与格式异常;可先点击刷新重试。',\n errorGeneric: '用量获取失败',\n}\n\n/** The panel's English string table (must mirror {@link PANEL_COPY_ZH}). */\nexport const PANEL_COPY_EN: Record<PanelKey, string> = {\n ...ANALYTICS_COPY_EN,\n nav: 'Command Code',\n subtitle: 'Plans, credits and quota windows',\n refresh: 'Refresh',\n refreshing: 'Refreshing…',\n close: 'Close',\n closeHint: 'Back to the conversation',\n loading: 'Loading account usage…',\n noKey: 'No API key configured',\n noKeyHint: 'Paste a key — or sign in — under Settings → Command Code, then refresh.',\n plan: 'Plan',\n credits: 'Credits',\n limits: 'Quota windows',\n usage: 'Usage',\n monthly: 'Monthly',\n monthlyLimit: 'Monthly limit',\n monthlyUsed: 'Monthly used',\n remaining: 'Remaining',\n purchased: 'Purchased',\n free: 'Free',\n fiveHour: '5-hour window',\n weekly: 'Weekly window',\n fiveHourShort: '5-hour',\n weeklyShort: 'Weekly',\n windowUnlimited: 'unlimited',\n exceeded: 'Exceeded',\n exhausted: 'Used up',\n resets: 'Resets',\n requests: 'Requests',\n failed: 'failed',\n successRate: 'Success rate',\n spend: 'Spend',\n tokens: 'Tokens',\n tokensIn: 'in',\n tokensOut: 'out',\n periodEnds: 'Period ends',\n updated: 'Updated',\n partial: 'Some endpoint data unavailable',\n active: 'Active',\n coolingDown: 'Cooling down',\n invalidKey: 'Invalid key',\n unconfigured: 'Not configured',\n unavailable: 'No data',\n errorInvalidKey: 'API key invalid or expired',\n errorInvalidKeyHint: 'The server rejected every request (401). Check the key for this account, or generate a new one in the commandcode.ai console.',\n errorServiceUnavailable: 'The Command Code service is temporarily unavailable',\n errorServiceUnavailableHint: 'The server returned errors (5xx). Try Refresh again in a moment.',\n errorNetwork: 'Could not reach the Command Code service',\n errorNetworkHint: 'No request reached the server. Check your network connection or the API base setting.',\n errorInvalidResponse: 'Could not read the Command Code response',\n errorInvalidResponseHint: 'Responses arrived, but reading or parsing their bodies failed. Details below distinguish timeouts, interrupted reads, and invalid formats. Try Refresh again.',\n errorGeneric: 'Could not fetch account usage',\n}\n\n/** Every panel key, in the English table's declaration order. */\nexport const PANEL_KEYS: readonly PanelKey[] = Object.keys(PANEL_COPY_EN) as PanelKey[]\n\n/**\n * The English translator. Used as the fallback when no locale seat is\n * available (a defensive path: every supported engine supplies one) and as the\n * default in tests that only assert the projection's figures.\n */\nexport function panelTextEN(key: PanelKey): string {\n return PANEL_COPY_EN[key] ?? key\n}\n","/**\n * View model for the Command Code plans & quota panel (the sidebar footer card\n * and the dashboard it opens).\n *\n * JSX-free and React-free, mirroring `./settings.ts` / `./usage.ts`: it turns\n * the shared usage snapshot into one presentation tree both components render,\n * and owns the one shared side effect (the throttled auto refresh below). Node\n * tests drive everything here without a DOM.\n *\n * Every displayed string is decided here, as a `PanelKey` plus a `text` record\n * resolved through the injected translator, so the components carry no copy of\n * their own and the panel follows the harness's active language\n * (`./panel-copy.ts` owns both dictionaries and the `panel.commandcode` locale\n * namespace; the slots hand the translator in).\n *\n * @module dsh-commandcode-provider/client/panel\n */\n\nimport type { CommandCodeUsageReport } from '../adapter.ts'\nimport type { CommandCodeAccountUsage } from '../usage-wire.ts'\nimport type { UsagePageState } from './usage.ts'\nimport { formatMoney, formatMoneyExact, formatSuccessRate, formatTokensCompact, formatResetAt } from '../display-format.ts'\nimport { PANEL_KEYS, panelTextEN } from './panel-copy.ts'\nimport type { PanelKey, PanelTranslator } from './panel-copy.ts'\n\n/** One quota window (5-hour or weekly) in display form. */\nexport interface PanelWindowView {\n /** Row-label key into the view's `text` record. */\n label: PanelKey\n /** `used / cap`, or just `used` when the window is uncapped. */\n value: string\n /** The window reports a cap, so `percent` is meaningful. */\n capped: boolean\n /** Percentage actually consumed (may exceed 100 when over the cap). */\n percent: number\n /** Fill width for the bar, clamped to [0, 100]. */\n barPercent: number\n /** Window is over its cap. */\n exceeded: boolean\n /** Local reset time, empty when the endpoint reported none. */\n resetsAt: string\n}\n\n/**\n * Monthly credit state. Consumption is derived the way the official CLI derives\n * it (`getCreditDepletionPct`): the plan's credit total is the LIMIT and the\n * billing endpoint's `credits.monthlyCredits` is the REMAINING balance, so\n * consumption is `limit - remaining`. Purchased and free credits are separate\n * balances that extend what an account can spend, so they are their own tiles.\n */\nexport interface PanelMonthlyView {\n /**\n * A ratio is meaningful — the plan published a credit total AND the billing\n * endpoint published the balance left of it. When false the view draws no bar:\n * a percentage needs both halves, and inventing either is how a failed billing\n * call becomes a confident \"100% used\".\n */\n known: boolean\n /** Plan credit total for the period (the limit); a dash when unreported. */\n limit: string\n /** Consumed this period (`limit - remaining`); a dash until both are known. */\n used: string\n /** Credits still available; a dash when the balance was not reported. */\n remaining: string\n /** Purchased top-up balance. */\n purchased: string\n /** Promotional balance. */\n free: string\n /** Consumption as a percentage of the limit; 0 when there is no ratio. */\n percent: number\n /** Fill width for the bar, clamped to [0, 100]. */\n barPercent: number\n /** The plan's credits are used up. */\n exhausted: boolean\n /** Billing period end, local date; empty when unreported. */\n periodEnds: string\n}\n\n/** One compact bar in the sidebar footer card. */\nexport interface PanelFooterBar {\n /** Row label key (short forms: `Monthly`, `5-hour`, `Weekly`). */\n label: PanelKey\n /** Printed right-hand percentage, e.g. `32%`; empty when there is no ratio. */\n percent: string\n /** Fill width, clamped to [0, 100]. */\n barPercent: number\n /** Render in the warning colour. */\n warn: boolean\n /**\n * This window's own spend against its limit, e.g. `$1.32 / $6.00`. RENDERED,\n * not just a tooltip: the card exists to show these figures, and the\n * magnitudes are small dollar amounts.\n */\n detail: string\n}\n\n/** One usage tile. */\nexport interface PanelStatView {\n label: PanelKey\n value: string\n /** Secondary line, empty when there is none. */\n sub: string\n}\n\n/** One pool account's report, ready to render. */\nexport interface PanelAccountView {\n id: string\n label: string\n /** The account's display name (user name, else account name); empty when unreported. */\n owner: string\n /** Subscription display name; empty when unreported. */\n planName: string\n /** Subscription status when it is not a plain `active`; empty otherwise. */\n planStatus: string\n /** Rotation/credential state ('invalidKey' / 'coolingDown'); undefined when plain. */\n mark: PanelKey | undefined\n /** Known cooldown end, appended to the cooling-down badge; empty otherwise. */\n cooldownUntil: string\n /** No credential resolved for this slot. */\n unconfigured: boolean\n /** Billing period end, empty when unreported. */\n periodEnds: string\n /** Whether the account currently serves requests. */\n active: boolean\n /** Monthly credit state; undefined when neither endpoint reported it. */\n monthly: PanelMonthlyView | undefined\n windows: PanelWindowView[]\n stats: PanelStatView[]\n}\n\n/** What actually went wrong, once — for the alert box. */\nexport interface PanelFailureView {\n title: PanelKey\n /** The actionable line under the title. */\n hint: PanelKey\n /** The underlying transport message, shown small; empty when there is none. */\n detail: string\n}\n\n/** The whole panel, in render order. */\nexport interface PanelView {\n /** Every localized string this view references, by key. */\n text: Partial<Record<PanelKey, string>>\n /** Footer-card plan text (`Go`, `Pro`, …), or a state word. */\n planName: string\n /** Footer-card rotation/credential state line; empty when nothing to say. */\n status: string\n /**\n * The compact bars the sidebar footer card stacks: the two quota windows an\n * account actually runs into, 5-hour first then weekly. The monthly bar\n * belongs to the DASHBOARD alone — it moves once a billing period, whereas\n * these two are what stop a session — and a window with no cap is left out\n * (no ratio to draw).\n */\n footerBars: PanelFooterBar[]\n /**\n * This period's spend in dollars; empty when the usage endpoint reported\n * nothing. NOT drawn as its own row — the card's visible figures are the two\n * windows' own spend (see {@link PanelFooterBar.detail}) — so it rides the\n * tooltip and the accessible name instead.\n */\n cost: string\n /**\n * The footer card's accessible name and tooltip: `Command Code · Pro ·\n * 5-hour $0.04 / $3.00 (1%) · Weekly $1.32 / $6.00 (22%) · Spend $1.32`.\n * Always starts with the visible title, so the accessible name contains the\n * visible label.\n */\n footTitle: string\n /** Every account, in rotation order (empty when there is nothing to show). */\n accounts: PanelAccountView[]\n /** Id of the account the panel opens on (the serving one), if any. */\n selectedId: string | undefined\n /** That account's view, for the footer card; undefined with no accounts. */\n selected: PanelAccountView | undefined\n /** A fetch is in flight and no data has landed for this paint. */\n loading: boolean\n /** No credential is configured at all. */\n noKey: boolean\n /** Report-level failure box; undefined when the report is usable. */\n failure: PanelFailureView | undefined\n /** A fetch failed while data is still on screen. */\n staleError: string | undefined\n /** Endpoint-level partial failure note; undefined when every endpoint answered. */\n partial: PanelKey | undefined\n /** Freshness line, empty when nothing has been fetched. */\n updatedAt: string\n}\n\n/** Inputs {@link buildPanelView} needs beyond the usage snapshot. */\nexport interface PanelViewInput {\n usage: UsagePageState\n /** Whether any account holds a credential (the settings controller's fact). */\n apiKeyConfigured: boolean\n /**\n * Locale translator for every label the view composes. The panel slots bind\n * their `t` seat to the `panel.commandcode` namespace and pass it here; an\n * omitted one falls back to English (the tests' default, and the defensive\n * path when no locale face is installed).\n */\n t?: PanelTranslator\n}\n\n/** A quota window's state as the wire carries it. */\ninterface WindowInput {\n used: number\n cap: number\n exceeded: boolean\n resetAt: number\n}\n\n/** `$1.23`, and `$0.0123` only when the amount is too small for cents to show it. */\nfunction money(value: number): string {\n if (value === 0) return formatMoney(0)\n return Math.abs(value) < 0.01 ? formatMoneyExact(value) : formatMoney(value)\n}\n\n/**\n * What a figure shows when the endpoint that carries it did not report one. A\n * dash, never a zero: the panel exists to state what the account has spent, so\n * \"we were not told\" has to look different from \"nothing\".\n */\nconst UNREPORTED = '—'\n\n/** Local reset time; empty when the endpoint reported none. */\nfunction resetText(ms: number): string {\n return formatResetAt(ms)\n}\n\n/** Local short date; empty when unset. */\nfunction dateText(ms: number): string {\n if (ms <= 0) return ''\n return new Date(ms).toLocaleDateString()\n}\n\n/** Local time-of-day; empty when unset. */\nfunction timeText(ms: number): string {\n if (ms <= 0) return ''\n return new Date(ms).toLocaleTimeString()\n}\n\n/**\n * Consumption as a percentage, NOT clamped at 100 — an over-quota window\n * reports its real overshoot (150%), which is what the printed figure should\n * say. Bar widths clamp separately via {@link barPercent}.\n */\nfunction rawPercent(used: number, cap: number): number {\n if (cap <= 0) return 0\n return Math.round((used / cap) * 100)\n}\n\n/** A percentage usable as a CSS width, clamped into [0, 100]. */\nfunction barPercent(percent: number): number {\n return Math.min(100, Math.max(0, percent))\n}\n\n/** Build one quota-window view. */\nfunction windowView(label: PanelKey, limit: WindowInput): PanelWindowView {\n const percent = rawPercent(limit.used, limit.cap)\n const capped = limit.cap > 0\n return {\n label,\n // Spend only: an uncapped window has no denominator, so its row pairs this\n // figure with the \"unlimited\" label instead of a `used / cap` it lacks.\n value: capped ? `${money(limit.used)} / ${money(limit.cap)}` : money(limit.used),\n capped,\n percent,\n barPercent: barPercent(percent),\n exceeded: limit.exceeded,\n resetsAt: resetText(limit.resetAt),\n }\n}\n\n/**\n * Build the monthly credit view from the two endpoints that carry it.\n *\n * The limit is the PLAN's credit total, not the billing endpoint's\n * `monthlyCredits` (that field is a remaining balance — see\n * {@link PanelMonthlyView}), so a plan that publishes no total still shows its\n * balances, just without a ratio.\n *\n * The trap this guards: a MISSING balance is not a consumed one. The billing\n * endpoint is one of four the report fetches in parallel, so it fails on its\n * own while the plan still arrives, and reading the absent balance as 0 turns\n * that partial failure into `limit - 0 = limit` — a confident \"100% used\" for\n * an account that may have spent nothing. The official CLI draws no meter unless\n * the credits payload is present at all (`hasCreditsInfo`); every derived figure\n * here stays a placeholder until the balance reported.\n */\nfunction monthlyView(report: CommandCodeUsageReport): PanelMonthlyView | undefined {\n const credits = report.credits\n const plan = report.plan\n if (credits === undefined && plan === undefined) return undefined\n\n const limitValue = plan?.monthlyCredits ?? null\n // Only an EXPLICIT `false` means the balance was omitted. An unset flag comes\n // from a Host half older than the field, which always sent a real number.\n const remainingReported = credits !== undefined && credits.monthlyReported !== false\n const remaining = remainingReported ? Math.max(0, credits.monthlyCredits) : 0\n // A ratio needs BOTH halves: the plan's total and the balance left of it.\n const known = limitValue !== null && limitValue > 0 && remainingReported\n const used = known ? Math.max(0, limitValue - remaining) : 0\n const percent = known ? rawPercent(used, limitValue) : 0\n\n return {\n known,\n limit: limitValue !== null ? money(limitValue) : UNREPORTED,\n used: known ? money(used) : UNREPORTED,\n remaining: remainingReported ? money(remaining) : UNREPORTED,\n purchased: credits !== undefined && credits.purchasedReported !== false ? money(Math.max(0, credits.purchasedCredits)) : UNREPORTED,\n free: credits !== undefined && credits.freeReported !== false ? money(Math.max(0, credits.freeCredits)) : UNREPORTED,\n percent,\n barPercent: barPercent(percent),\n exhausted: known && remaining <= 0,\n periodEnds: dateText(plan?.currentPeriodEnd ?? 0),\n }\n}\n\n/** Build one account's view. */\nfunction accountView(entry: CommandCodeAccountUsage, t: PanelTranslator): PanelAccountView {\n const { report } = entry\n const account = report.account\n const plan = report.plan\n const credits = report.credits\n const usage = report.usage\n\n const stats: PanelStatView[] = []\n if (usage !== undefined) {\n stats.push({\n label: 'requests',\n value: String(usage.completedCount),\n sub: `${usage.failedCount} ${t('failed')}`,\n })\n stats.push({ label: 'successRate', value: `${formatSuccessRate(usage.successRate)}%`, sub: '' })\n stats.push({\n label: 'spend',\n value: formatMoneyExact(usage.totalCost),\n sub: `${formatMoney(usage.totalCredits)} credits`,\n })\n stats.push({\n label: 'tokens',\n value: formatTokensCompact(usage.totalTokensIn + usage.totalTokensOut),\n sub: `${formatTokensCompact(usage.totalTokensIn)} ${t('tokensIn')} / ${formatTokensCompact(usage.totalTokensOut)} ${t('tokensOut')}`,\n })\n }\n\n const windows: PanelWindowView[] = []\n // One row per window the endpoint actually REPORTED: an unlimited plan\n // reports none, and drawing two zero-cap rows would invent a limit it does not\n // have. A window reporting `cap === 0` is uncapped spend and does get a row.\n if (credits?.fiveHour !== undefined) windows.push(windowView('fiveHour', credits.fiveHour))\n if (credits?.weekly !== undefined) windows.push(windowView('weekly', credits.weekly))\n\n // Rotation/credential state: the serving account first, then the two marks\n // the pool can carry, then a cooldown whose end time is known.\n let mark: PanelKey | undefined\n if (entry.active) mark = 'active'\n else if (entry.mark === 'invalid-credential') mark = 'invalidKey'\n else if (entry.cooldownUntil > 0 || entry.mark === 'rate-limit') mark = 'coolingDown'\n\n return {\n id: entry.id,\n label: entry.label,\n owner: account === undefined ? '' : account.userName || account.name,\n planName: plan?.name ?? '',\n planStatus: plan !== undefined && plan.status !== '' && plan.status !== 'active' ? plan.status : '',\n mark,\n cooldownUntil: entry.cooldownUntil > 0 ? resetText(entry.cooldownUntil) : '',\n unconfigured: !entry.configured,\n periodEnds: dateText(plan?.currentPeriodEnd ?? 0),\n active: entry.active,\n monthly: monthlyView(report),\n windows,\n stats,\n }\n}\n\n/** The report-level failure box, or undefined when the report is usable. */\nfunction failureView(state: UsagePageState): PanelFailureView | undefined {\n const blockedEntry = state.report?.accounts.find((entry) => entry.report.blocked !== undefined)\n const blocked = blockedEntry?.report.blocked\n // Preserve each endpoint's status or transport error beside the summary.\n const detail = (blockedEntry?.report.failures ?? []).join(' · ')\n if (blocked === 'invalid-key') {\n return { title: 'errorInvalidKey', hint: 'errorInvalidKeyHint', detail }\n }\n if (blocked === 'service-unavailable') {\n return { title: 'errorServiceUnavailable', hint: 'errorServiceUnavailableHint', detail }\n }\n if (blocked === 'network') {\n return { title: 'errorNetwork', hint: 'errorNetworkHint', detail }\n }\n if (blocked === 'invalid-response') {\n return { title: 'errorInvalidResponse', hint: 'errorInvalidResponseHint', detail }\n }\n // A transport-level failure (unmounted Remote, offline browser) arrives as\n // the controller's own error rather than as a blocked report.\n if (state.status === 'error' && state.report === undefined) {\n return { title: 'errorGeneric', hint: 'errorGeneric', detail: state.error ?? '' }\n }\n return undefined\n}\n\n/**\n * Every panel string, resolved once per projection through the translator. One\n * object with all keys (rather than per-field lookups in the components) keeps\n * the copy table and the render sites in lockstep: a key cannot be read from\n * `text` unless {@link PANEL_KEYS} declares it.\n */\nfunction panelStrings(t: PanelTranslator): Record<PanelKey, string> {\n const out = {} as Record<PanelKey, string>\n for (const key of PANEL_KEYS) out[key] = t(key)\n return out\n}\n\n/**\n * Project the shared usage snapshot into the panel's render tree.\n *\n * Deduplication matches the settings card: hand-edited settings can name one\n * credential twice.\n */\nexport function buildPanelView(input: PanelViewInput): PanelView {\n const { usage } = input\n const t = input.t ?? panelTextEN\n const seen = new Set<string>()\n const entries = (usage.report?.accounts ?? []).filter((entry) => {\n if (seen.has(entry.id)) return false\n seen.add(entry.id)\n return true\n })\n const accounts = entries.map((entry) => accountView(entry, t))\n const selectedEntry = entries.find((entry) => entry.active) ?? entries[0]\n const selectedView = accounts.find((view) => view.id === selectedEntry?.id)\n\n // The footer card stacks BOTH quota windows — the two limits an account\n // actually runs into — 5-hour first (the tighter and nearer one), then\n // weekly. `barPercent` clamps the fill; the printed percentage keeps the true\n // consumption, so an over-cap window still reads 150%.\n const footerBars: PanelFooterBar[] = []\n const windowBars: Array<[PanelKey, WindowInput | undefined]> = [\n ['fiveHourShort', selectedEntry?.report.credits?.fiveHour],\n ['weeklyShort', selectedEntry?.report.credits?.weekly],\n ]\n for (const [label, window] of windowBars) {\n if (window === undefined || window.cap <= 0) continue\n const percent = rawPercent(window.used, window.cap)\n footerBars.push({\n label,\n percent: `${percent}%`,\n barPercent: barPercent(percent),\n warn: window.exceeded,\n detail: `${money(window.used)} / ${money(window.cap)}`,\n })\n }\n\n // The card's one non-ratio figure: what this period has cost in dollars.\n const totalCost = selectedEntry?.report.usage?.totalCost\n const cost = totalCost === undefined ? '' : money(totalCost)\n\n let status = ''\n if (entries.length > 0 && !entries.some(entry => entry.configured)) status = t('unconfigured')\n else if (selectedView?.mark !== undefined && selectedView.mark !== 'active') status = t(selectedView.mark)\n else if (selectedEntry === undefined) status = t('unavailable')\n\n const planName = selectedView !== undefined && selectedView.planName !== '' ? selectedView.planName : t('nav')\n // `planName` falls back to the panel name, so it is only a second part when it\n // actually names a plan — otherwise the title would read `Command Code ·\n // Command Code`.\n const titleParts = planName === t('nav') ? [planName] : [t('nav'), planName]\n for (const bar of footerBars) {\n const figures = bar.detail === '' ? '' : ` ${bar.detail}`\n titleParts.push(`${t(bar.label)}${figures} (${bar.percent})`)\n }\n if (cost !== '') titleParts.push(`${t('spend')} ${cost}`)\n\n return {\n text: panelStrings(t),\n planName,\n status,\n footerBars,\n cost,\n footTitle: titleParts.join(' · '),\n accounts,\n selectedId: selectedEntry?.id,\n selected: selectedView,\n loading: usage.status === 'loading' && usage.report === undefined,\n noKey: entries.length > 0 && !entries.some(entry => entry.configured),\n failure: failureView(usage),\n staleError: usage.status === 'error' && usage.report !== undefined ? usage.error ?? '' : undefined,\n partial: (usage.report?.accounts.some((entry) => entry.report.failures.length > 0 && entry.report.blocked === undefined) ?? false)\n ? 'partial'\n : undefined,\n updatedAt: timeText(usage.fetchedAt ?? 0),\n }\n}\n\n// --- Auto refresh (one shared loop, started by whichever surface mounts first)\n\n/**\n * How often the panel re-reads the report while a surface is mounted. The quota\n * windows move slowly and one report costs four upstream calls, so this is a\n * background freshness tick, not a live meter.\n */\nexport const PANEL_AUTO_REFRESH_MS = 120_000\n\n/** The narrow face of `CommandCodeUsageController` this module drives. */\nexport interface RefreshSource {\n state(): UsagePageState\n refresh(): Promise<void>\n}\n\n/** Timer seam: injectable so tests never wait on real time. */\nexport interface AutoRefreshTimer {\n set(callback: () => void, ms: number): unknown\n clear(handle: unknown): void\n}\n\n/** The default timer (the client bundle runs in a browser; node tests inject one). */\nconst REAL_TIMER: AutoRefreshTimer = {\n set: (callback, ms) => setTimeout(callback, ms),\n clear: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),\n}\n\n/** Live mount count of {@link startPanelAutoRefresh}. */\nlet references = 0\n/** Owner ticket of the running loop, if any. */\nlet activeTicket: number | undefined\n/** Ticket handed to the next starter. */\nlet ticketSeq = 0\n/** Pending timer handle of the running loop. */\nlet handle: unknown\n\n/**\n * Start the shared auto refresh. One fetch when the surface appears (the sidebar\n * row is the point of the panel — it must be current, not wait for a click), then\n * a tick every {@link PANEL_AUTO_REFRESH_MS} while a surface stays mounted.\n *\n * Reference-counted: the sidebar entry and the dashboard can be mounted at once,\n * so only the first start fetches and only the last stop halts the loop. Every\n * tick goes through `usage.refresh()`, which collapses a concurrent fetch onto\n * the in-flight one. Returns the disposer that drops this surface's reference.\n *\n * @param usage - the shared usage controller.\n * @param isConfigured - whether a credential exists right now (re-read per tick).\n * @param timer - timer seam for tests.\n */\nexport function startPanelAutoRefresh(\n usage: RefreshSource,\n isConfigured: () => boolean,\n timer: AutoRefreshTimer = REAL_TIMER,\n): () => void {\n references += 1\n const ticket = ++ticketSeq\n const tick = (): void => {\n if (activeTicket !== ticket) return\n if (isConfigured()) void usage.refresh()\n handle = timer.set(tick, PANEL_AUTO_REFRESH_MS)\n }\n\n if (activeTicket === undefined) {\n activeTicket = ticket\n handle = timer.set(tick, PANEL_AUTO_REFRESH_MS)\n // First paint: refresh immediately so the row is never blank on arrival.\n if (isConfigured()) void usage.refresh()\n }\n\n let stopped = false\n return () => {\n if (stopped) return\n stopped = true\n references -= 1\n // Still mounted elsewhere: drop this reference only. The check is the\n // REFCOUNT, not this surface's ticket — the surface that started the loop\n // is not necessarily the last to unmount.\n if (references > 0) return\n activeTicket = undefined\n if (handle !== undefined) {\n timer.clear(handle)\n handle = undefined\n }\n }\n}\n\n/**\n * Drop every live reference and halt the loop without a timer.\n *\n * Exported for tests only: the loop's state is module-level on purpose (two\n * surfaces, one upstream poll). Production code releases through the disposer\n * {@link startPanelAutoRefresh} returns.\n */\nexport function resetPanelAutoRefresh(): void {\n references = 0\n activeTicket = undefined\n handle = undefined\n}\n","/** 模型分析的只读契约;只传数字和模型能力,不传会话正文、标题、路径或密钥。 */\nimport type { InvocationDescriptor, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { makeBoundaryValidator, makeRemoteDescriptor, makeStrictCodec, REMOTE_PACKAGE } from './wire-shared.ts'\nimport type { CostTokens } from './cost-facts.ts'\n\nexport type AnalyticsQuery = { mode: 'recent'; limit: number } | { mode: 'range'; from: number; to: number }\nexport interface AnalyticsMetrics {\n sessions: number; requests: number; completed: number; failed: number; cancelled: number; unknown: number; retries: number\n usageSamples: number; pricedRequests: number; cost: number; tokens: CostTokens\n latencySamples: number; latencyMs: number; ttftSamples: number; ttftMs: number; decodeSamples: number; decodeMs: number; decodeTokens: number\n}\nexport interface AnalyticsModel extends AnalyticsMetrics { id: string }\nexport interface AnalyticsScenario {\n id: string; name: string; contextWindow: number | null; images: boolean; efforts: string[]\n cost: number; pricedRequests: number; excludedRequests: number; unknownRequests: number\n}\nexport interface AnalyticsReport {\n generatedAt: number; pricingKey: number; query: AnalyticsQuery\n status: 'ready' | 'unavailable'\n scannedSessions: number; matchedSessions: number; unreadableSessions: number; skippedSessions: number; truncated: boolean; catalogUnavailable: boolean\n totals: AnalyticsMetrics; models: AnalyticsModel[]; scenarios: AnalyticsScenario[]\n monthlyEstimate: number | null\n}\nconst g = makeBoundaryValidator('commandcode/analytics')\nconst nonnegative = (s: Record<string, unknown>, k: string): number => {\n const n = g.numberField(s, k, k)\n return n >= 0 ? n : g.reject(k)\n}\nconst count = (s: Record<string, unknown>, k: string): number => {\n const n = nonnegative(s, k)\n return Number.isSafeInteger(n) ? n : g.reject(k)\n}\nexport function parseAnalyticsQuery(value: unknown): AnalyticsQuery {\n const s = g.record(value, 'query')\n if (s.mode === 'recent') {\n const limit = count(s, 'limit')\n if (limit < 1 || limit > 100) return g.reject('limit')\n return { mode: 'recent', limit }\n }\n if (s.mode !== 'range') return g.reject('mode')\n const from = count(s, 'from'), to = count(s, 'to')\n if (to <= from || to - from > 366 * 86400000 || to > 8640000000000000) return g.reject('range')\n return { mode: 'range', from, to }\n}\nconst counts = ['sessions', 'requests', 'completed', 'failed', 'cancelled', 'unknown', 'retries', 'usageSamples', 'pricedRequests', 'latencySamples', 'ttftSamples', 'decodeSamples'] as const\nconst quantities = ['cost', 'latencyMs', 'ttftMs', 'decodeMs', 'decodeTokens'] as const\nconst tokenKeys = ['uncachedInputTokens', 'outputTokens', 'cacheReadTokens', 'cacheWriteTokens'] as const\nfunction metrics(value: unknown): AnalyticsMetrics {\n const s = g.record(value, 'metrics'), result = {} as AnalyticsMetrics\n for (const k of counts) result[k] = count(s, k)\n for (const k of quantities) result[k] = nonnegative(s, k)\n const tokens = g.record(s.tokens, 'tokens')\n result.tokens = Object.fromEntries(tokenKeys.map(k => [k, nonnegative(tokens, k)])) as unknown as CostTokens\n if (result.completed + result.failed + result.cancelled + result.unknown !== result.requests\n || result.pricedRequests > result.usageSamples || result.usageSamples > result.requests\n || result.retries > result.requests || result.ttftSamples > result.requests || result.latencySamples > result.requests || result.decodeSamples > result.requests) return g.reject('coverage')\n return result\n}\nconst nullable = (s: Record<string, unknown>, k: string): number | null => s[k] === null ? null : nonnegative(s, k)\nexport function parseAnalyticsReport(value: unknown): AnalyticsReport {\n const s = g.record(value, 'report')\n if (s.status !== 'ready' && s.status !== 'unavailable') return g.reject('status')\n if (!Array.isArray(s.models) || !Array.isArray(s.scenarios) || s.models.length > 1000 || s.scenarios.length > 1000) return g.reject('models')\n return {\n generatedAt: count(s, 'generatedAt'), pricingKey: count(s, 'pricingKey'), query: parseAnalyticsQuery(s.query), status: s.status,\n scannedSessions: count(s, 'scannedSessions'), matchedSessions: count(s, 'matchedSessions'), unreadableSessions: count(s, 'unreadableSessions'), skippedSessions: count(s, 'skippedSessions'),\n truncated: g.booleanField(s, 'truncated', 'truncated'), catalogUnavailable: g.booleanField(s, 'catalogUnavailable', 'catalogUnavailable'),\n totals: metrics(s.totals), monthlyEstimate: nullable(s, 'monthlyEstimate'),\n models: s.models.map(value => { const m = g.record(value, 'model'); return { ...metrics(m), id: g.stringField(m, 'id', 'id') } }),\n scenarios: s.scenarios.map(value => {\n const m = g.record(value, 'scenario')\n if (!Array.isArray(m.efforts) || !m.efforts.every(v => typeof v === 'string')) return g.reject('efforts')\n return { id: g.stringField(m, 'id', 'id'), name: g.stringField(m, 'name', 'name'), contextWindow: nullable(m, 'contextWindow'), images: g.booleanField(m, 'images', 'images'), efforts: m.efforts as string[], cost: nonnegative(m, 'cost'), pricedRequests: count(m, 'pricedRequests'), excludedRequests: count(m, 'excludedRequests'), unknownRequests: count(m, 'unknownRequests') }\n }),\n }\n}\nexport const ANALYTICS_DESCRIPTOR: InvocationDescriptor = {\n ...makeRemoteDescriptor('commandcode/analytics', 'analytics', `${REMOTE_PACKAGE}#AnalyticsReport`, { parse: parseAnalyticsReport }),\n parameters: [{ name: 'query', wire: 'query', source: 'json' as const, codec: makeStrictCodec(`${REMOTE_PACKAGE}#AnalyticsQuery`, { parse: parseAnalyticsQuery }) }],\n}\nexport const ANALYTICS_REMOTE_CONTRIBUTION: TypertRemoteContribution = { package: REMOTE_PACKAGE, descriptors: [ANALYTICS_DESCRIPTOR] }\n","/** 只展示数字快照;筛选提交后才查询,页签、展开与模型筛选不触发历史读取。 */\nimport { useEffect, useId, useState } from 'react'\nimport type { KeyboardEvent } from 'react'\nimport type { AnalyticsMetrics, AnalyticsQuery, AnalyticsScenario } from '../analytics-wire.ts'\nimport { parseAnalyticsQuery } from '../analytics-wire.ts'\nimport type { AnalyticsState } from './analytics.ts'\nimport type { AnalyticsKey } from './analytics-copy.ts'\n\nexport interface AnalyticsViewProps {\n useCommandCodeAnalytics<T>(selector: (state: AnalyticsState) => T): T\n refreshAnalytics(query?: AnalyticsQuery): void\n text(key: AnalyticsKey): string\n}\ntype Text = AnalyticsViewProps['text']\nfunction localDate(time: number): string {\n const d = new Date(time)\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n/** 日期按用户本地日历展开为半开区间;截止日包括当日全部时间,夏令时不固定加 24 小时。 */\nexport function dateRange(from: string, to: string): AnalyticsQuery {\n const start = new Date(`${from}T00:00:00`), end = new Date(`${to}T00:00:00`)\n if (localDate(start.getTime()) !== from || localDate(end.getTime()) !== to) throw new TypeError('无效日期')\n end.setDate(end.getDate() + 1)\n return parseAnalyticsQuery({ mode: 'range', from: start.getTime(), to: end.getTime() })\n}\nconst money = (n: number) => `$${n.toFixed(4)}`\nconst digits = (n: number) => n.toLocaleString()\nconst meanSeconds = (ms: number, samples: number, text: Text) => samples ? `${(ms / samples / 1000).toFixed(2)} ${text('analysisSeconds')}` : text('analysisMissing')\nconst speed = (m: AnalyticsMetrics, text: Text) => m.decodeSamples && m.decodeMs ? `${(m.decodeTokens * 1000 / m.decodeMs).toFixed(1)} ${text('analysisSpeedUnit')}` : text('analysisMissing')\nfunction effortName(effort: string, text: Text): string {\n const keys: Record<string, AnalyticsKey> = { none: 'effortNone', low: 'effortLow', medium: 'effortMedium', high: 'effortHigh', xhigh: 'effortXhigh', max: 'effortMax' }\n return keys[effort] ? text(keys[effort]!) : effort\n}\nfunction Chevron() {\n return <svg className=\"ccp-analysisChevron\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"m9 5 7 7-7 7\" /></svg>\n}\nfunction Metric({ label, value, sub }: { label: string; value: string; sub?: string }) {\n return <span className=\"ccp-analysisMetric\"><span className=\"ccp-analysisLabel\">{label}</span><span className=\"ccp-analysisValue\">{value}</span>{sub ? <span className=\"ccp-analysisSub\">{sub}</span> : null}</span>\n}\nfunction DetailGroup({ title, values, text }: { title: AnalyticsKey; values: Array<[AnalyticsKey, string]>; text: Text }) {\n return <div className=\"ccp-analysisDetailGroup\"><h4 className=\"ccp-analysisDetailTitle\">{text(title)}</h4><dl className=\"ccp-analysisFacts\">{values.map(([key, value]) => <div className=\"ccp-analysisFact\" key={key}><dt className=\"ccp-analysisLabel\">{text(key)}</dt><dd className=\"ccp-analysisFactValue\">{value}</dd></div>)}</dl></div>\n}\n/** 样本为零时词元仍为未知;汇总和单模型复用相同口径,展开只改变展示。 */\nfunction MetricsDetails({ m, text }: { m: AnalyticsMetrics; text: Text }) {\n const tokens = m.tokens, tokenValue = (n: number) => m.usageSamples ? digits(n) : text('analysisMissing')\n return <div className=\"ccp-analysisDetails\">\n <DetailGroup title=\"analysisTokens\" text={text} values={[\n ['analysisInput', tokenValue(tokens.uncachedInputTokens)], ['analysisOutput', tokenValue(tokens.outputTokens)],\n ['analysisCacheRead', tokenValue(tokens.cacheReadTokens)], ['analysisCacheWrite', tokenValue(tokens.cacheWriteTokens)],\n ]} />\n <DetailGroup title=\"analysisOutcome\" text={text} values={[\n ['analysisCompleted', digits(m.completed)], ['analysisFailed', digits(m.failed)], ['analysisRetries', digits(m.retries)],\n ['analysisCancelled', digits(m.cancelled)], ['analysisUnknown', digits(m.unknown)],\n ]} />\n <DetailGroup title=\"analysisSamples\" text={text} values={[\n ['analysisUsageSamples', digits(m.usageSamples)], ['analysisPriced', digits(m.pricedRequests)], ['analysisTimed', digits(m.latencySamples)],\n ['analysisFirstTokenSamples', digits(m.ttftSamples)], ['analysisDecodeSamples', digits(m.decodeSamples)],\n ]} />\n <DetailGroup title=\"analysisSessionCost\" text={text} values={[\n ['analysisSessionCount', digits(m.sessions)], ['analysisRequests', digits(m.requests)],\n ['analysisAverage', m.sessions && m.pricedRequests ? money(m.cost / m.sessions) : text('analysisMissing')], ['analysisSpeed', speed(m, text)],\n ]} />\n </div>\n}\nfunction ModelRow({ m, text }: { m: AnalyticsMetrics & { id: string }; text: Text }) {\n return <details className=\"ccp-analysisModelRow\"><summary className=\"ccp-analysisModelSummary\">\n <span className=\"ccp-analysisIdentity\"><span className=\"ccp-analysisModelName\">{m.id}</span><span className=\"ccp-analysisSub\">{text('analysisRequests')} {digits(m.requests)} · {text('analysisSessionCount')} {digits(m.sessions)}</span></span>\n <Metric label={text('analysisCost')} value={m.pricedRequests ? money(m.cost) : text('analysisMissing')} sub={`${text('analysisPriced')} ${m.pricedRequests}/${m.requests}`} />\n <Metric label={text('analysisResponse')} value={meanSeconds(m.latencyMs, m.latencySamples, text)} />\n <Metric label={text('analysisFirstToken')} value={meanSeconds(m.ttftMs, m.ttftSamples, text)} />\n <Metric label={text('analysisSpeed')} value={speed(m, text)} />\n <Chevron />\n </summary><MetricsDetails m={m} text={text} /></details>\n}\nfunction ScenarioRow({ m, text }: { m: AnalyticsScenario; text: Text }) {\n return <details className=\"ccp-analysisModelRow\"><summary className=\"ccp-analysisScenarioSummary\">\n <span className=\"ccp-analysisIdentity\"><span className=\"ccp-analysisModelName\">{m.name}</span><span className=\"ccp-analysisSub\">{m.id}</span></span>\n <Metric label={text('analysisCost')} value={m.pricedRequests ? money(m.cost) : text('analysisMissing')} sub={`${text('analysisPriced')} ${m.pricedRequests}/${m.pricedRequests + m.excludedRequests + m.unknownRequests}`} />\n <Metric label={text('analysisContext')} value={m.contextWindow === null ? text('analysisMissing') : digits(m.contextWindow)} />\n <span className=\"ccp-analysisCapability\">{text(m.images ? 'analysisImages' : 'analysisTextOnly')}</span><Chevron />\n </summary><div className=\"ccp-analysisDetails ccp-analysisScenarioDetails\">\n <DetailGroup title=\"analysisSamples\" text={text} values={[\n ['analysisPriced', digits(m.pricedRequests)], ['analysisExcluded', digits(m.excludedRequests)], ['analysisUnknownPrice', digits(m.unknownRequests)],\n ]} />\n <DetailGroup title=\"analysisCapabilities\" text={text} values={[\n ['analysisEfforts', m.efforts.length ? m.efforts.map(e => effortName(e, text)).join(', ') : text('analysisNoEfforts')],\n ]} />\n </div></details>\n}\nexport function AnalyticsView(props: AnalyticsViewProps) {\n const { text } = props, state = props.useCommandCodeAnalytics(s => s), report = state.report\n const [mode, setMode] = useState<'recent' | 'range'>(report?.query.mode ?? 'recent')\n const [limit, setLimit] = useState(report?.query.mode === 'recent' ? String(report.query.limit) : '20')\n const [from, setFrom] = useState(localDate(report?.query.mode === 'range' ? report.query.from : Date.now() - 29 * 86400000))\n const [to, setTo] = useState(localDate(report?.query.mode === 'range' ? report.query.to - 1 : Date.now()))\n const [invalid, setInvalid] = useState(false), [filter, setFilter] = useState('')\n const [page, setPage] = useState<'history' | 'simulation'>('history'), id = useId()\n const refresh = props.refreshAnalytics\n useEffect(() => { if (state.status === 'idle') refresh() }, [state.status, refresh])\n const busy = state.status === 'loading'\n const apply = () => {\n try {\n const query = mode === 'recent' ? parseAnalyticsQuery({ mode, limit: Number(limit) }) : dateRange(from, to)\n setInvalid(false); refresh(query)\n } catch { setInvalid(true) }\n }\n // 页签遵循键盘导航;只切换本地展示,不重读会话或丢弃筛选草稿。\n const navigateTab = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return\n event.preventDefault()\n const next = event.key === 'Home' ? 'history' : event.key === 'End' ? 'simulation' : page === 'history' ? 'simulation' : 'history'\n setPage(next)\n event.currentTarget.querySelector<HTMLButtonElement>(`[data-page=\"${next}\"]`)?.focus()\n }\n const scenarios = report?.scenarios.filter(m => `${m.id} ${m.name}`.toLowerCase().includes(filter.trim().toLowerCase())) ?? []\n const m = report?.totals\n return <section className=\"ccp-analysis\" aria-label={text('analyticsNav')} aria-busy={busy}>\n <form className=\"ccp-analysisFilters\" noValidate onSubmit={e => { e.preventDefault(); if (!busy) apply() }}>\n <label className=\"ccp-analysisField ccp-analysisScopeField\">{text('analysisScope')}<span className=\"ccp-analysisSelectShell\"><select className=\"ccp-analysisInput ccp-analysisSelect\" value={mode} disabled={busy} onChange={e => setMode(e.target.value as 'recent' | 'range')}><option value=\"recent\">{text('analysisRecent')}</option><option value=\"range\">{text('analysisRange')}</option></select><Chevron /></span></label>\n {mode === 'recent' ? <label className=\"ccp-analysisField\">{text('analysisLimit')}<input className=\"ccp-analysisInput\" type=\"number\" min=\"1\" max=\"100\" required value={limit} disabled={busy} onChange={e => setLimit(e.target.value)} /></label> : <>\n <label className=\"ccp-analysisField\">{text('analysisFrom')}<input className=\"ccp-analysisInput\" type=\"date\" required value={from} disabled={busy} onChange={e => setFrom(e.target.value)} /></label>\n <label className=\"ccp-analysisField\">{text('analysisTo')}<input className=\"ccp-analysisInput\" type=\"date\" required value={to} disabled={busy} onChange={e => setTo(e.target.value)} /></label>\n </>}\n <button className=\"ccp-analysisApply\" type=\"submit\" disabled={busy}>{text('analysisApply')}</button>\n </form>\n {invalid ? <p className=\"ccp-analysisMessage ccp-analysisError\" role=\"alert\">{text('analysisInvalid')}</p> : null}\n {busy ? <p className=\"ccp-analysisMessage\" role=\"status\">{text('analysisLoading')}</p> : null}\n {state.error ? <p className=\"ccp-analysisMessage ccp-analysisError\" role=\"alert\">{state.error}</p> : null}\n {report?.status === 'unavailable' ? <p className=\"ccp-analysisMessage\" role=\"status\">{text('analysisUnavailable')}</p> : null}\n {report?.status === 'ready' && m ? <>\n <div className=\"ccp-analysisScope\"><span>{text('analysisScope')}: {report.query.mode === 'recent' ? `${text('analysisRecent')} ${report.query.limit}` : `${localDate(report.query.from)} — ${localDate(report.query.to - 1)}`}</span><span>{text('analysisScanned')} {report.scannedSessions} · {text('analysisMatched')} {report.matchedSessions} · {text('analysisUnreadable')} {report.unreadableSessions} · {text('analysisSkipped')} {report.skippedSessions}</span></div>\n <div className=\"ccp-analysisOverview\" role=\"group\" aria-label={text('analysisOverview')}>\n <Metric label={text('analysisCost')} value={m.pricedRequests ? money(m.cost) : text('analysisMissing')} sub={`${text('analysisPriced')} ${m.pricedRequests}/${m.requests}`} />\n <Metric label={text('analysisRequests')} value={digits(m.requests)} sub={`${text('analysisSessionCount')} ${digits(m.sessions)}`} />\n <Metric label={text('analysisResponse')} value={meanSeconds(m.latencyMs, m.latencySamples, text)} sub={`${text('analysisTimed')} ${digits(m.latencySamples)}`} />\n <Metric label={text('analysisFirstToken')} value={meanSeconds(m.ttftMs, m.ttftSamples, text)} sub={`${text('analysisFirstTokenSamples')} ${digits(m.ttftSamples)}`} />\n </div>\n <p className=\"ccp-analysisNote\">{text('analysisShortBasis')}</p>\n {report.truncated || report.unreadableSessions > 0 || report.skippedSessions > 0 ? <p className=\"ccp-analysisMessage ccp-analysisWarning\" role=\"status\">{text('analysisPartial')}</p> : null}\n {m.pricedRequests < m.requests ? <p className=\"ccp-analysisMessage ccp-analysisWarning\" role=\"status\">{text('analysisUnpriced')}</p> : null}\n <div className=\"ccp-analysisTabs\" role=\"tablist\" aria-label={text('analysisSections')} onKeyDown={navigateTab}>\n {(['history', 'simulation'] as const).map(tab => <button className=\"ccp-analysisTab\" key={tab} id={`${id}-${tab}-tab`} data-page={tab} type=\"button\" role=\"tab\" aria-selected={page === tab} aria-controls={`${id}-${tab}`} tabIndex={page === tab ? 0 : -1} onClick={() => setPage(tab)}>{text(tab === 'history' ? 'analysisHistory' : 'analysisSimulation')}</button>)}\n </div>\n <section className=\"ccp-analysisPanel\" id={`${id}-history`} role=\"tabpanel\" aria-labelledby={`${id}-history-tab`} tabIndex={0} hidden={page !== 'history'}>\n <div className=\"ccp-analysisSectionHead\"><h3 className=\"ccp-analysisHeading\">{text('analysisByModel')}</h3><p className=\"ccp-analysisNote\">{text('analysisModelHint')}</p></div>\n {m.requests === 0 ? <p className=\"ccp-analysisEmpty\">{text('analysisEmpty')}</p> : <div className=\"ccp-analysisModels\">{report.models.map(model => <ModelRow key={model.id} m={model} text={text} />)}</div>}\n <details className=\"ccp-analysisAggregate\"><summary className=\"ccp-analysisDisclosure\"><Chevron />{text('analysisDetails')}</summary><MetricsDetails m={m} text={text} /></details>\n <div className=\"ccp-analysisMonthly\"><span>{text('analysisMonthly')}</span><strong className=\"ccp-analysisMonthlyValue\">{report.monthlyEstimate === null || report.truncated || report.unreadableSessions || report.skippedSessions ? text('analysisMissing') : money(report.monthlyEstimate)}</strong><p className=\"ccp-analysisNote\">{text('analysisMonthlyHint')}</p></div>\n </section>\n <section className=\"ccp-analysisPanel\" id={`${id}-simulation`} role=\"tabpanel\" aria-labelledby={`${id}-simulation-tab`} tabIndex={0} hidden={page !== 'simulation'}>\n <p className=\"ccp-analysisAssumption\">{text('analysisAssumption')}</p>\n {report.catalogUnavailable ? <p className=\"ccp-analysisMessage ccp-analysisWarning\" role=\"status\">{text('analysisCatalog')}</p> : null}\n <label className=\"ccp-analysisField ccp-analysisSearch\">{text('analysisSearch')}<input className=\"ccp-analysisInput\" type=\"search\" placeholder={text('analysisSearchPlaceholder')} value={filter} onChange={e => setFilter(e.target.value)} /></label>\n {m.requests === 0 ? <p className=\"ccp-analysisEmpty\">{text('analysisEmpty')}</p> : scenarios.length ? <div className=\"ccp-analysisModels\">{scenarios.map(model => <ScenarioRow key={model.id} m={model} text={text} />)}</div> : !report.catalogUnavailable ? <p className=\"ccp-analysisEmpty\" role=\"status\">{text('analysisNoMatches')}</p> : null}\n </section>\n <details className=\"ccp-analysisRules\"><summary className=\"ccp-analysisDisclosure\"><Chevron />{text('analysisRules')}</summary><div className=\"ccp-analysisRulesBody\"><p>{text('analysisBasis')}</p><p>{text('analysisCoverageHint')}</p></div></details>\n </> : null}\n </section>\n}\n","/**\n * React components for the Command Code plans & quota panel: the sidebar footer\n * card and the dashboard it opens in the center column.\n *\n * Both render one {@link PanelView} projected by `./panel.ts` — no fact is\n * derived here. Strings arrive already localized in `view.text`: the slots\n * declare the `panel.commandcode` locale namespace, so the renderer hands this\n * component a `t` seat that is passed into `buildPanelView`, and a language\n * switch mints a new `t` identity, which re-renders both surfaces.\n *\n * The footer card is the panel's home — the shell renders it in the foot area\n * directly above the Settings seat, and unlike a `sidebar.panellist` row (whose\n * chrome and label the SHELL owns) this entry owns its whole surface and\n * therefore calls `open()` itself. Styles ride the stylesheet\n * `./panel-styles.ts` returns; classes are `ccp-` prefixed.\n *\n * @module dsh-commandcode-provider/client/panel-view\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 { SnapshotStore } from './snapshot-store.ts'\nimport type { UsagePageState } from './usage.ts'\nimport type { SettingsPageState } from './settings.ts'\nimport { buildPanelView } from './panel.ts'\nimport type { PanelAccountView, PanelView, PanelWindowView } from './panel.ts'\nimport { panelTextEN } from './panel-copy.ts'\nimport type { PanelKey } from './panel-copy.ts'\n// SlotMap merge for `main` / `sidebar.footer.action` (load-bearing: the slots\n// this file's components register into are typed only by that augmentation).\nimport './panel-slots.ts'\nimport { AnalyticsView } from './analytics-view.tsx'\nimport type { AnalyticsState } from './analytics.ts'\nimport type { AnalyticsQuery } from '../analytics-wire.ts'\n\n/**\n * Owner share of the sidebar-foot action hole: the shell renders the foot area\n * and hands each action only the column fold state. There is no button chrome\n * and no `label` seat — the entry is the whole surface.\n */\nexport interface SidebarFooterActionOwnerProps {\n /** Whether the sidebar renders wide content (false = 56px rail). */\n wide: boolean\n}\n\n/**\n * The injected face both panel slots carry. Bound by the client entry so the\n * components stay unaware of the settings controller, the login controller, the\n * layout service and the module-level auto-refresh loop.\n *\n * NOTE the split from {@link PanelComponentProps}: this is what the\n * registration's `inject` factory RETURNS, and the renderer does not hand it to\n * the component verbatim — `bindInjectSources` destructures the `hooks`\n * compartment OUT and re-exposes each member as a `use<Name>` prop\n * (`commandCodeUsage` → `useCommandCodeUsage`). A component that reads\n * `props.hooks.*` finds `undefined` at runtime and crashes on render, which the\n * slot renderer contains by ABDICATING the entry, so the surface vanishes with\n * no visible error.\n */\nexport interface PanelInjected {\n hooks: {\n commandCodeUsage: SnapshotStore<UsagePageState>\n commandCodeSettings: SnapshotStore<SettingsPageState>\n commandCodeAnalytics?: SnapshotStore<AnalyticsState>\n commandCodePanelMode?: SnapshotStore<'quota' | 'analysis'>\n }\n /** Fetch the report now (the dashboard's Refresh action). */\n refresh(): void\n /**\n * Leave the dashboard and show the Conversation again\n * (`ctx.layout.selectPanel(null)`; the current Session is untouched).\n */\n close(): void\n /** Start the shared background poll for this mount; returns its disposer. */\n startAutoRefresh(): () => void\n /** Select this panel in the center column (`ctx.layout.selectPanel`). */\n open(): void\n refreshAnalytics?(query?: AnalyticsQuery): void\n selectPanelMode?(mode: 'quota' | 'analysis'): void\n}\n\n/**\n * The props a panel component actually receives: the bound `useX` seats (what\n * {@link PanelInjected}'s `hooks` compartment becomes), the pass-through\n * actions, and no raw `hooks` key.\n *\n * `buildPanelView` is cheap (one pass over the account list) and recomputing it\n * per notification is what keeps a store update from ever rendering a stale\n * quota, so the selector is deliberately the whole snapshot.\n */\nexport interface PanelComponentProps {\n useCommandCodeAnalytics?<T>(selector: (state: AnalyticsState) => T): T\n useCommandCodePanelMode?<T>(selector: (state: 'quota' | 'analysis') => T): T\n refreshAnalytics?(query?: AnalyticsQuery): void\n selectPanelMode?(mode: 'quota' | 'analysis'): void\n useCommandCodeUsage<T>(selector: (state: UsagePageState) => T): T\n useCommandCodeSettings<T>(selector: (state: SettingsPageState) => T): T\n /**\n * Locale seat for the `panel.commandcode` namespace, bound by the\n * registration's own `locale` declaration. Optional so a missing locale face\n * degrades to English instead of crashing the surface.\n */\n t?: Translate<PanelKey>\n refresh(): void\n close(): void\n startAutoRefresh(): () => void\n open(): void\n}\n\n/** Props of the sidebar footer card: the panel face plus the shell's fold state. */\nexport interface CommandCodeFooterEntryProps extends PanelComponentProps, SidebarFooterActionOwnerProps {}\n\n/** The panel's view, recomputed from both seats on every notification. */\nfunction usePanelView(props: PanelComponentProps): PanelView {\n const usage = props.useCommandCodeUsage((state) => state)\n const settings = props.useCommandCodeSettings((state) => state)\n return buildPanelView({\n usage,\n apiKeyConfigured: settings.anyAccountConfigured,\n t: props.t ?? panelTextEN,\n })\n}\n\n/**\n * The quota ring. One glyph serves the rail button, the footer card's top row\n * and the dashboard header: a faint track plus an arc whose sweep is the\n * consumption, drawn from 12 o'clock. Circumference 2πr = 45.55 at r = 7.25.\n */\nfunction Ring({ percent, warn, size }: { percent: number; warn: boolean; size: number }) {\n const clamped = Math.min(100, Math.max(0, percent))\n const circumference = 45.55\n // Rounded to three decimals: the raw product lands on floats like\n // 34.162499999999994, which is a needless DOM diff churn.\n const dashoffset = Math.round(circumference * (1 - clamped / 100) * 1000) / 1000\n return (\n <span className=\"ccp-glyph\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" width={size} height={size} focusable=\"false\">\n <circle cx=\"10\" cy=\"10\" r=\"7.25\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" opacity=\"0.4\" />\n <circle\n cx=\"10\"\n cy=\"10\"\n r=\"7.25\"\n fill=\"none\"\n stroke={warn ? 'var(--dsw-alias-state-error-primary)' : 'currentColor'}\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeDasharray={String(circumference)}\n strokeDashoffset={String(dashoffset)}\n transform=\"rotate(-90 10 10)\"\n />\n </svg>\n </span>\n )\n}\n\n/** One labelled bar. `compact` drops the reset line; the footer draws its own. */\nfunction QuotaBar({ label, value, percent, barPercent, warn, resetsAt, resetsLabel }: {\n label: string\n value: string\n percent: string\n barPercent: number\n warn: string\n resetsAt: string\n resetsLabel: string\n}) {\n const clamped = Math.min(100, Math.max(0, barPercent))\n return (\n <div className=\"ccp-window\">\n <div className=\"ccp-windowHead\">\n <span className=\"ccp-windowLabel\">{label}</span>\n {warn !== '' ? <span className=\"ccp-warnTag\">{warn}</span> : null}\n <span className=\"ccp-spacer\" />\n {value !== '' ? <span className=\"ccp-windowValue\">{value}</span> : null}\n <span className=\"ccp-windowPct\">{percent}</span>\n </div>\n <div className=\"ccp-bar\" role=\"progressbar\" aria-label={label} aria-valuemin={0} aria-valuemax={100} aria-valuenow={clamped}>\n <div className={warn !== '' ? 'ccp-barFill ccp-barFillWarn' : 'ccp-barFill'} style={{ width: `${clamped}%` }} />\n </div>\n {resetsAt !== '' ? <p className=\"ccp-windowReset\">{resetsLabel} {resetsAt}</p> : null}\n </div>\n )\n}\n\n/** A labelled figure. */\nfunction Tile({ label, value, sub }: { label: string; value: string; sub?: string }) {\n return (\n <div className=\"ccp-tile\">\n <span className=\"ccp-tileLabel\">{label}</span>\n <span className=\"ccp-tileValue\">{value}</span>\n {sub !== undefined && sub !== '' ? <span className=\"ccp-tileSub\">{sub}</span> : null}\n </div>\n )\n}\n\n/** The rotation/credential badge line for one account. */\nfunction markText(account: PanelAccountView, text: (key: PanelKey) => string): string {\n if (account.mark === undefined) return ''\n if (account.mark === 'coolingDown' && account.cooldownUntil !== '') {\n return `${text('coolingDown')} · ${account.cooldownUntil}`\n }\n return text(account.mark)\n}\n\n/** `Default account` → `D`; used for the card's monogram chip. */\nfunction initial(label: string): string {\n const trimmed = label.trim()\n return trimmed === '' ? '?' : trimmed[0]!.toUpperCase()\n}\n\n/**\n * One account's full report: the monthly limit/usage bar, the two quota\n * windows, then the credit and usage totals.\n */\nfunction AccountCard({ account, view }: { account: PanelAccountView; view: PanelView }) {\n const text = (key: PanelKey): string => view.text[key] ?? key\n const mark = markText(account, text)\n const monthly = account.monthly\n\n return (\n <section className=\"ccp-card\" aria-label={account.label}>\n <header className=\"ccp-cardHead\">\n <span className=\"ccp-avatar\" aria-hidden=\"true\">{initial(account.label)}</span>\n <span className=\"ccp-cardIdentity\">\n <span className=\"ccp-cardTitle\">{account.label}</span>\n {account.owner !== '' ? <span className=\"ccp-cardOwner\">{account.owner}</span> : null}\n </span>\n <span className=\"ccp-spacer\" />\n {account.planName !== '' ? <span className=\"ccp-badge\">{account.planName}</span> : null}\n {account.planStatus !== '' ? <span className=\"ccp-badge ccp-badgeWarn\">{account.planStatus}</span> : null}\n {mark !== '' ? (\n <span className={account.mark === 'invalidKey' ? 'ccp-badge ccp-badgeError' : 'ccp-badgeMuted'}>{mark}</span>\n ) : null}\n {account.periodEnds !== '' ? (\n <span className=\"ccp-meta\">{text('periodEnds')} {account.periodEnds}</span>\n ) : null}\n </header>\n\n {account.unconfigured ? <p className=\"ccp-hint\">{text('unconfigured')}</p> : null}\n\n {monthly !== undefined && monthly.known ? (\n <QuotaBar\n label={text('monthly')}\n value={`${monthly.used} / ${monthly.limit}`}\n percent={`${monthly.percent}%`}\n barPercent={monthly.barPercent}\n warn={monthly.exhausted ? text('exhausted') : ''}\n resetsAt=\"\"\n resetsLabel=\"\"\n />\n ) : (\n <div className=\"ccp-planRow\">\n {/* The plan is already in the card's header badge; what is missing\n here is the RATIO, so the row names the plan the report carries\n and falls back to a placeholder only when the report is silent. */}\n <span className=\"ccp-fieldLabel\">{text('plan')}</span>\n <span className=\"ccp-planName\">{account.planName !== '' ? account.planName : text('unavailable')}</span>\n </div>\n )}\n\n {/* A balance the billing endpoint DID report, so a card without a ratio\n still states something true. */}\n {monthly !== undefined && monthly.remaining !== '—' ? (\n <div className=\"ccp-planRow\">\n <span className=\"ccp-fieldLabel\">{text('remaining')}</span>\n <span className=\"ccp-planName\">{monthly.remaining}</span>\n </div>\n ) : null}\n\n {account.windows.length > 0 ? (\n <div className=\"ccp-windows\">\n {account.windows.map((window: PanelWindowView) => (\n <QuotaBar\n key={window.label}\n label={text(window.label)}\n value={window.value}\n percent={window.capped ? `${window.percent}%` : text('windowUnlimited')}\n barPercent={window.barPercent}\n warn={window.exceeded ? text('exceeded') : ''}\n resetsAt={window.resetsAt}\n resetsLabel={text('resets')}\n />\n ))}\n </div>\n ) : null}\n\n {monthly !== undefined ? (\n <div className=\"ccp-block\">\n <h4 className=\"ccp-blockTitle\">{text('credits')}</h4>\n <div className=\"ccp-tiles\">\n <Tile label={text('monthlyLimit')} value={monthly.limit} />\n <Tile label={text('monthlyUsed')} value={monthly.used} />\n <Tile label={text('remaining')} value={monthly.remaining} />\n <Tile label={text('purchased')} value={monthly.purchased} />\n <Tile label={text('free')} value={monthly.free} />\n </div>\n </div>\n ) : null}\n\n {account.stats.length > 0 ? (\n <div className=\"ccp-block\">\n <h4 className=\"ccp-blockTitle\">{text('usage')}</h4>\n <div className=\"ccp-tiles\">\n {account.stats.map((stat) => (\n <Tile key={stat.label} label={text(stat.label)} value={stat.value} sub={stat.sub} />\n ))}\n </div>\n </div>\n ) : null}\n </section>\n )\n}\n\n/**\n * The center-column dashboard, registered into the layout's keyed `main` slot\n * under the same id the footer card selects, so the two are one navigation\n * entry: the card shows the plan, the monthly bar and the quota window; the\n * panel shows everything, including the per-account breakdown.\n */\nexport function CommandCodePanel(props: PanelComponentProps) {\n const view = usePanelView(props)\n const [fallbackMode, setFallbackMode] = useState<'quota' | 'analysis'>('quota')\n const mode = props.useCommandCodePanelMode?.(s => s) ?? fallbackMode\n const analyticsBusy = props.useCommandCodeAnalytics?.(s => s.status === 'loading') ?? false\n const selectMode = (next: 'quota' | 'analysis') => { setFallbackMode(next); props.selectPanelMode?.(next) }\n const text = (key: PanelKey): string => view.text[key] ?? key\n const [selectedId, setSelectedId] = useState<string | undefined>(undefined)\n\n const startAutoRefresh = props.startAutoRefresh\n useEffect(() => mode === 'quota' ? startAutoRefresh() : undefined, [startAutoRefresh, mode])\n\n const accounts = view.accounts\n const selected = accounts.find((account) => account.id === selectedId)\n ?? view.selected\n ?? accounts[0]\n\n return (\n <div className=\"ccp-main\" role=\"region\" aria-label={text('nav')}>\n <div className={`ccp-mainInner${mode === 'analysis' ? ' ccp-mainInnerAnalysis' : ''}`}>\n <header className=\"ccp-header\">\n <div className=\"ccp-headerText\">\n <h2 className=\"ccp-title\">{mode === 'analysis' ? `Command Code · ${text('analyticsNav')}` : text('nav')}</h2>\n {mode === 'quota' ? <p className=\"ccp-subtitle\">{text('subtitle')}</p> : null}\n </div>\n <span className=\"ccp-spacer\" />\n {mode === 'quota' && view.updatedAt !== '' ? <span className=\"ccp-meta\">{text('updated')} {view.updatedAt}</span> : null}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={mode === 'quota' ? view.loading : analyticsBusy}\n onClick={() => mode === 'quota' ? props.refresh() : props.refreshAnalytics?.()}\n >\n {mode === 'quota' && view.loading ? text('refreshing') : text('refresh')}\n </Button>\n {/* The dashboard REPLACES the conversation in the center column and\n this panel is the only surface that selects it, so without an exit\n the user cannot get back to the session at all (issue #41): the\n sidebar card only re-selects this same panel. The glyph is the\n button's whole content, so the name and tooltip carry the words. */}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ccp-close\"\n aria-label={text('close')}\n title={text('closeHint')}\n onClick={() => props.close()}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"m6 6 12 12M18 6 6 18\" /></svg>\n </Button>\n </header>\n\n <nav className=\"ccp-tabs\" aria-label={text('nav')}>\n <button className={mode === 'quota' ? 'ccp-tab ccp-tabActive' : 'ccp-tab'} type=\"button\" aria-pressed={mode === 'quota'} onClick={() => selectMode('quota')}>{text('quotaNav')}</button>\n <button className={mode === 'analysis' ? 'ccp-tab ccp-tabActive' : 'ccp-tab'} type=\"button\" aria-pressed={mode === 'analysis'} onClick={() => selectMode('analysis')}>{text('analyticsNav')}</button>\n </nav>\n {mode === 'analysis' ? props.useCommandCodeAnalytics && props.refreshAnalytics ? <AnalyticsView useCommandCodeAnalytics={props.useCommandCodeAnalytics} refreshAnalytics={props.refreshAnalytics} text={text} /> : <p className=\"ccp-hint\">{text('analysisUnavailable')}</p> : <>\n\n {view.noKey ? (\n <div className=\"ccp-notice\">\n <p className=\"ccp-noticeTitle\">{text('noKey')}</p>\n <p className=\"ccp-noticeHint\">{text('noKeyHint')}</p>\n </div>\n ) : null}\n\n {view.failure !== undefined ? (\n <div className=\"ccp-notice ccp-noticeError\" role=\"alert\">\n <p className=\"ccp-noticeTitle\">{text(view.failure.title)}</p>\n <p className=\"ccp-noticeHint\">{text(view.failure.hint)}</p>\n {view.failure.detail !== '' ? <p className=\"ccp-noticeDetail\">{view.failure.detail}</p> : null}\n </div>\n ) : null}\n\n {!view.noKey && view.failure === undefined && accounts.length === 0 && view.loading ? (\n <p className=\"ccp-hint\">{text('loading')}</p>\n ) : null}\n\n {view.staleError !== undefined && view.staleError !== '' ? (\n <p className=\"ccp-hint\" role=\"status\">{text('errorGeneric')} — {view.staleError}</p>\n ) : null}\n\n {accounts.length > 1 ? (\n <div className=\"ccp-tabs\" role=\"tablist\" aria-label={text('nav')}>\n {accounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected?.id === account.id}\n className={selected?.id === account.id ? 'ccp-tab ccp-tabActive' : 'ccp-tab'}\n onClick={() => setSelectedId(account.id)}\n >\n {account.label}\n </button>\n ))}\n </div>\n ) : null}\n\n {selected !== undefined ? <AccountCard account={selected} view={view} /> : null}\n\n {view.partial !== undefined ? <p className=\"ccp-hint\">{text(view.partial)}</p> : null}\n </>}\n </div>\n </div>\n )\n}\n\n/**\n * The sidebar footer card, registered into `sidebar.footer.action` — the list\n * the shell renders in the foot area directly ABOVE the Settings seat, so the\n * panel reads as a bottom-pinned sibling of Settings rather than a global panel\n * icon at the top of the column.\n *\n * The shell wraps nothing here, so this component owns the surface: the button,\n * its chrome and its accessible name. Expanded, it draws the title row and one\n * block per quota window (5-hour, then weekly) — the window's own spend and\n * limit, its percentage and its bar — and nothing else, because those two\n * windows are the figures an account runs into, so the period total stays in the\n * tooltip. In the 56px rail it collapses to a 36px icon button carrying the ring,\n * matching the shell's own rail geometry; `wide` comes from the shell.\n *\n * Rendering is gated on the settings page's `showSidebarQuota` toggle, which\n * defaults OFF: a fresh install shows no quota surface in the sidebar and runs\n * no background poll. The gate reads the STORED document (the settings\n * controller's `sidebarQuota` fact), so an unsaved draft cannot show the card\n * while a landed save flips it live. The entry stays REGISTERED — this is a\n * render decision, so nothing churns the slot ledger.\n */\nexport function CommandCodeFooterEntry(props: CommandCodeFooterEntryProps) {\n // While hidden this component renders NOTHING — no expanded card, no rail\n // icon — and starts no background usage poll; the dashboard cell stays\n // registered but has no trigger, which is exactly what \"hide the quota\n // display\" means.\n const visible = props.useCommandCodeSettings((snapshot) => snapshot.sidebarQuota)\n const view = usePanelView(props)\n\n const startAutoRefresh = props.startAutoRefresh\n useEffect(() => {\n if (!visible) return undefined\n return startAutoRefresh()\n }, [visible, startAutoRefresh])\n\n if (!visible) return null\n\n const text = (key: PanelKey): string => view.text[key] ?? key\n // The ring tracks the tightest window — the 5-hour one whenever it is capped,\n // which is the limit an account runs into first, and `footerBars` is ordered\n // that way, so the leading bar is the headline.\n const headline = view.footerBars[0]\n // The tooltip doubles as the accessible name; it always begins with the\n // visible title, so the label the user reads is contained in the name.\n const title = view.footTitle\n\n if (!props.wide) {\n return (\n <button\n type=\"button\"\n className=\"ccp-railButton\"\n aria-label={title}\n title={title}\n onClick={() => props.open()}\n >\n <Ring percent={headline?.barPercent ?? 0} warn={headline?.warn ?? false} size={18} />\n </button>\n )\n }\n\n return (\n <button\n type=\"button\"\n className=\"ccp-foot\"\n aria-label={title}\n title={title}\n onClick={() => props.open()}\n >\n <span className=\"ccp-footTop\">\n <Ring percent={headline?.barPercent ?? 0} warn={headline?.warn ?? false} size={16} />\n <span className=\"ccp-footName\">{text('nav')}</span>\n <span className=\"ccp-spacer\" />\n {view.status !== '' ? (\n <span className=\"ccp-badgeMuted\">{view.status}</span>\n ) : view.planName !== text('nav') ? (\n <span className=\"ccp-badge\">{view.planName}</span>\n ) : null}\n </span>\n\n {view.footerBars.map((bar) => (\n <span className=\"ccp-footRow\" key={bar.label}>\n <span className=\"ccp-footHead\">\n <span className=\"ccp-footLabel\">{text(bar.label)}</span>\n <span className=\"ccp-spacer\" />\n {bar.detail !== '' ? <span className=\"ccp-footAmount\">{bar.detail}</span> : null}\n <span className=\"ccp-footPct\">{bar.percent}</span>\n </span>\n <span className=\"ccp-footBar\">\n <span\n className={bar.warn ? 'ccp-footFill ccp-footFillWarn' : 'ccp-footFill'}\n style={{ width: `${bar.barPercent}%` }}\n />\n </span>\n </span>\n ))}\n </button>\n )\n}\n","/** Shared, JSON-only billing facts. No Host or browser runtime imports. */\nimport type { CommandCodeModelPrice, CommandCodeModelRates, CommandCodePriceTable } from './usage-wire.ts'\n\nexport interface CostTokens {\n uncachedInputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n}\n\n/** Requests with identical model/rates are folded into one group. */\nexport interface CostUsageGroup {\n provider: string\n model: string\n at: number | null\n contextTokens: number\n tokens: CostTokens\n}\n\nexport interface SessionCostFacts {\n pricingKey: number\n groups: CostUsageGroup[]\n}\n\nexport const zeroCostTokens = (): CostTokens => ({ uncachedInputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 })\nexport const COST_TOKEN_KEYS = ['uncachedInputTokens', 'outputTokens', 'cacheReadTokens', 'cacheWriteTokens'] as const\n\nexport function peakHour(at: number, windows: ReadonlyArray<readonly [number, number]>): boolean {\n const time = new Date(at)\n return time.getUTCDay() !== 0 && time.getUTCDay() !== 6\n && windows.some(([start, end]) => time.getUTCHours() >= start && time.getUTCHours() < end)\n}\n\n/**\n * All prompt billing buckets determine a request's band, never cumulative\n * session input.\n *\n * A tiered model returns the matching band and does NOT then apply `peak`: the\n * page publishes those two dimensions independently and no row carries both\n * today, so the combination becoming real is visible before it reaches a user.\n * This ordering is a latent choice, not a verified upstream rule.\n */\nexport function requestRates(price: CommandCodeModelPrice, at: number | null, contextTokens: number, table: CommandCodePriceTable): CommandCodeModelRates {\n // ORDER IS LOAD-BEARING: the generator refuses non-ascending bounds or a\n // bounded last band and the wire parser rejects the same shapes, so a\n // conforming table cannot present bands out of order.\n const tier = price.contextTiers?.find(tier => tier.maxContext === undefined || contextTokens <= tier.maxContext)\n if (tier !== undefined) return tier\n return price.peak !== undefined && at !== null && peakHour(at, table.peakHours) ? price.peak : price\n}\n\n/** Cache version and wire guard: changing bands/rates must refold historical groups. */\nexport function pricingKey(table: CommandCodePriceTable): number {\n const rates = (r: CommandCodeModelRates) => [r.inputCost, r.outputCost, r.cacheReadCost, r.cacheWriteCost ?? null]\n const canonical = JSON.stringify(['commandCodeCost-v1', table.peakHours, table.models.map(p => [p.id, p.slug, p.free === true, rates(p), p.peak ? rates(p.peak) : null, p.contextTiers?.map(t => [t.maxContext ?? null, rates(t)]) ?? null])])\n let hash = 2166136261\n for (const c of canonical) hash = Math.imul(hash ^ c.charCodeAt(0), 16777619) >>> 0\n return hash\n}\n\n/** Only safe to merge requests whose billing classification is identical. */\nexport function costGroupKey(group: CostUsageGroup, table: CommandCodePriceTable): string {\n // The table is mutable, so an identity-keyed index can keep stale model\n // mappings after its rows are changed in place. The projection already\n // indexes its usage groups once per settlement; scan the small price table\n // here so every call observes the current rows.\n const price = table.models.find(p => p.id === group.model || p.slug === group.model)\n return JSON.stringify([group.provider, group.model, price === undefined ? null : requestRates(price, group.at, group.contextTokens, table), group.at === null])\n}\n","/**\n * Session-cost view model for the composer readout.\n *\n * JSX-free and React-free, mirroring `./panel.ts`: it turns the session's token\n * accounting plus the Host's price table into one presentation value AND the\n * exact text the two surfaces of the harness's token-usage UI receive — the\n * amount appended to the shipped pill, and the rows appended to the shipped\n * usage dialog. Node tests therefore drive the whole calculation, and every\n * user-visible string, without a DOM.\n *\n * It prices the session's DURABLE cumulative buckets, which is what the\n * composer's own \"N tokens\" pill reads too (`tokenUsage`), so the two surfaces\n * can never disagree about how much was used. Dollars are computed here because\n * Command Code publishes per-token rates and bills against dollar-denominated\n * windows; the account's own reported `totalCost` is a billing PERIOD figure,\n * not this session's.\n *\n * Three rules are load-bearing: only Command Code usage is priced (a session\n * served by another provider must render nothing, never a Command Code\n * estimate); a missing rate is never invented (the pricing page publishes a\n * cache-WRITE rate for only some models, so unpriced cache-write tokens are\n * surfaced as such rather than charged at a guessed multiple of the input rate);\n * and unpriceable means invisible — a confident `$0.00` would be a lie, and\n * this module never returns one.\n *\n * @module dsh-commandcode-provider/client/session-cost\n */\n\nimport { COST_TOKEN_KEYS, pricingKey, requestRates, peakHour, zeroCostTokens, type SessionCostFacts } from '../cost-facts.ts'\nimport type { CommandCodeModelPrice, CommandCodeModelRates, CommandCodePriceTable } from '../usage-wire.ts'\nimport { formatMoney, formatMoneyExact, formatTokensCompact } from '../display-format.ts'\n\n/** Tokens per published rate unit — the pricing page quotes USD per million. */\nconst TOKENS_PER_RATE_UNIT = 1_000_000\n\n/** The provider route whose usage this surface prices. */\nconst COMMANDCODE_PROVIDER = 'commandcode'\n\n/**\n * The English copy for this surface.\n *\n * A plain constant, NOT the `settings.commandcode` locale namespace: like the\n * plans & quota panel, the readout stays English on a Chinese harness. Do not\n * route it through `ctx.locale`.\n */\nexport const SESSION_COST_COPY = {\n /** Shown instead of an amount when the model costs nothing on every plan. */\n free: 'Free',\n /**\n * The separator the readout prefixes itself with, so the cost reads as the\n * last item of the token-usage pill's text run rather than a control beside\n * it. Rendered with the same colour and margins the shipped pill uses\n * between its own items.\n */\n separator: '·',\n panelTitle: 'Session cost',\n /** Marks an estimate from published rates rather than an invoice. */\n approximate: '≈',\n unpricedCacheWrite: 'cache write tokens have no published rate',\n /** Tooltip line naming the rate half in force. */\n peakRates: 'peak rates',\n offPeakRates: 'off-peak rates',\n /** Tooltip line explaining the approximate marker. */\n approximateNote: 'estimate from published rates, not the provider invoice',\n /** Row/tooltip label for uncached prompt tokens. */\n uncachedInput: 'uncached input',\n /** Row/tooltip label for completion tokens. */\n output: 'output',\n /** Row/tooltip label for cache-served input tokens. */\n cacheRead: 'cache read',\n /** Row/tooltip label for cache-written input tokens. */\n cacheWrite: 'cache write',\n} as const\n\n/**\n * The session's cumulative token buckets, as the `tokenUsage` projection\n * carries them. Declared structurally: this bundle does not depend on the\n * session-controller package, and a bucket the provider never reported is\n * absent rather than zero.\n */\nexport interface SessionUsageBuckets {\n readonly uncachedInputTokens?: number\n readonly outputTokens?: number\n readonly cacheReadTokens?: number\n readonly cacheWriteTokens?: number\n}\n\n/** One entry of the `modelSelection` projection. */\nexport interface SessionModelSelection {\n readonly provider: string\n readonly model: string\n}\n\n/**\n * The `modelSelection` projection: the selection the latest request consumed,\n * and the one the next request will use (falling back to the former).\n */\nexport interface SessionModelSelectionProjection {\n readonly lastUsed: SessionModelSelection | null\n readonly next: SessionModelSelection | null\n}\n\n/** Everything the view needs, already read off the seats by the component. */\nexport interface SessionCostInput {\n /** Durable billing groups; absent on older Hosts means no trustworthy estimate. */\n facts?: SessionCostFacts | undefined\n /** The durable cumulative token buckets, or undefined before any request. */\n usage: SessionUsageBuckets | undefined\n /** The session's model selection fold, or undefined on an older Host. */\n selection: SessionModelSelectionProjection | undefined\n /** The Host's price table, or undefined until it lands. */\n table: CommandCodePriceTable | undefined\n /** Legacy caller field; historical request timestamps alone determine rates. */\n now: number\n}\n\n/** One bucket's line in the usage dialog. */\nexport interface SessionCostBucketRow {\n /** Stable key. */\n key: 'uncachedInput' | 'cacheRead' | 'cacheWrite' | 'output'\n /** Row label. */\n label: string\n /** Tokens charged in this bucket; a bucket that charged nothing withholds its\n * row rather than printing a meaningless zero. */\n tokens: number\n /** What this bucket cost, or undefined when the table has no rate for it. */\n costText: string | undefined\n}\n\n/** The composer readout's presentation value. */\nexport interface SessionCostView {\n /** Priced total in dollars. */\n total: number\n /** Visible amount text, e.g. `$0.0123` (or the free word, when free). */\n value: string\n /** Full tooltip/accessible text, including the bucket breakdown. */\n title: string\n /** Per-bucket lines for the usage dialog, in reading order. */\n rows: SessionCostBucketRow[]\n /** Caveat lines for the pill's tooltip (rate half, approximation, unpriced). */\n notes: string[]\n /** The model costs nothing on every plan right now. */\n free: boolean\n /** The model's `peak` rates are in force. */\n peak: boolean\n /** Cache-write tokens the table has no rate for (never guessed, so the\n * total is a floor rather than an estimate). */\n unpricedCacheWriteTokens: number\n /** Published-rate totals are estimates rather than provider invoices. */\n approximate: boolean\n}\n\n/** A finite, non-negative count — anything else reads as absent. */\nfunction count(value: number | undefined): number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0\n}\n\n/**\n * Index a price table for lookup. Rows are keyed by catalog id and by pricing\n * slug, both exact and lowercased, because a session reports a catalog id while\n * a row no catalog model claims is served under the page's slug.\n */\nfunction indexTable(table: CommandCodePriceTable): Map<string, CommandCodeModelPrice> {\n const index = new Map<string, CommandCodeModelPrice>()\n for (const price of table.models) {\n for (const key of [price.id, price.slug]) {\n if (typeof key !== 'string' || key === '') continue\n if (!index.has(key)) index.set(key, price)\n const lower = key.toLowerCase()\n if (!index.has(lower)) index.set(lower, price)\n }\n }\n return index\n}\n\n/**\n * The dollar cost of each bucket, plus the total and the unpriced remainder.\n *\n * Every bucket is charged at its own published rate; the cache-write bucket\n * contributes only when the model publishes a rate for it, otherwise its tokens\n * come back as {@link SessionCostView.unpricedCacheWriteTokens} and its own cost\n * stays undefined so the panel can say so instead of printing a zero.\n */\ninterface SessionCostBreakdown {\n uncachedInput: number\n cacheRead: number\n cacheWrite: number | undefined\n output: number\n total: number\n unpricedCacheWriteTokens: number\n}\n\nfunction costOf(\n usage: SessionUsageBuckets,\n rates: CommandCodeModelRates,\n free: boolean,\n): SessionCostBreakdown {\n if (free) {\n return { uncachedInput: 0, cacheRead: 0, cacheWrite: 0, output: 0, total: 0, unpricedCacheWriteTokens: 0 }\n }\n const perUnit = (tokens: number, rate: number): number => (tokens * rate) / TOKENS_PER_RATE_UNIT\n const uncachedInput = perUnit(count(usage.uncachedInputTokens), rates.inputCost)\n const output = perUnit(count(usage.outputTokens), rates.outputCost)\n const cacheRead = perUnit(count(usage.cacheReadTokens), rates.cacheReadCost)\n const cacheWriteTokens = count(usage.cacheWriteTokens)\n const cacheWrite = rates.cacheWriteCost === undefined\n ? undefined\n : perUnit(cacheWriteTokens, rates.cacheWriteCost)\n return {\n uncachedInput,\n cacheRead,\n cacheWrite,\n output,\n total: uncachedInput + output + cacheRead + (cacheWrite ?? 0),\n unpricedCacheWriteTokens: rates.cacheWriteCost === undefined ? cacheWriteTokens : 0,\n }\n}\n\n/**\n * Amount text for a session cost.\n *\n * The panel's `money()` convention (2 decimals, 4 below a cent) is right for\n * billing windows, but a live session total starts far below a cent, where\n * `toFixed(4)` would print a flat `$0.0000` — broken rather than small. So a\n * total under $0.0001 is stated as a bound instead.\n */\nexport function sessionCostAmount(total: number): string {\n if (!Number.isFinite(total) || total <= 0) return formatMoney(0)\n if (total < 0.0001) return `<$0.0001`\n return total < 0.01 ? formatMoneyExact(total) : formatMoney(total)\n}\n\n/** One `label value` clause of the tooltip. */\nfunction clause(label: string, tokens: number): string | undefined {\n return tokens > 0 ? `${label} ${formatTokensCompact(tokens)}` : undefined\n}\n\n/**\n * Build the composer readout, or undefined when there is nothing honest to show.\n *\n * Undefined is the correct answer for a session with no usage yet, a session\n * another provider served, a model the price table does not know, and a table\n * that has not landed — the pill simply is not there.\n */\nexport function buildSessionCostView(input: SessionCostInput): SessionCostView | undefined {\n const { usage, table, facts } = input\n if (!usage || !table || !facts || facts.pricingKey !== pricingKey(table)) return undefined\n const totals = zeroCostTokens()\n const index = indexTable(table)\n const breakdown: SessionCostBreakdown = { uncachedInput: 0, cacheRead: 0, cacheWrite: 0, output: 0, total: 0, unpricedCacheWriteTokens: 0 }\n let free = true\n let peak = false\n let partial = false\n let priced = false\n const notes: string[] = []\n for (const group of facts.groups) {\n for (const key of COST_TOKEN_KEYS) totals[key] += group.tokens[key]\n if (group.provider !== COMMANDCODE_PROVIDER) { partial = true; continue }\n const price = index.get(group.model)\n if (!price) { partial = true; continue }\n const isFree = price.free === true\n free &&= isFree\n if (price.peak && group.at === null) {\n partial = true\n notes.push('request time unavailable; off-peak lower bound')\n }\n const rates = requestRates(price, group.at, group.contextTokens, table)\n const part = costOf(group.tokens, rates, isFree)\n priced ||= isFree || part.total > 0\n for (const key of ['uncachedInput', 'cacheRead', 'output', 'total', 'unpricedCacheWriteTokens'] as const) breakdown[key] += part[key]\n breakdown.cacheWrite = (breakdown.cacheWrite ?? 0) + (part.cacheWrite ?? 0)\n if (price.peak) {\n const isPeak = group.at !== null && peakHour(group.at, table.peakHours)\n peak ||= isPeak\n notes.push(isPeak ? SESSION_COST_COPY.peakRates : SESSION_COST_COPY.offPeakRates)\n }\n }\n // Both projections must describe the same durable cut. Never decorate token\n // rows from a newer/older fold, and never price an old Host's cumulative usage.\n if (COST_TOKEN_KEYS.some(key => totals[key] !== count(usage[key])) || !priced) return undefined\n const { total, unpricedCacheWriteTokens } = breakdown\n partial ||= unpricedCacheWriteTokens > 0\n free &&= !partial\n if (partial) notes.push('Command Code priced subtotal only; unpriced or other-provider usage excluded')\n notes.push(SESSION_COST_COPY.approximateNote)\n const uncachedInput = totals.uncachedInputTokens\n const output = totals.outputTokens\n const cacheRead = totals.cacheReadTokens\n const cacheWrite = totals.cacheWriteTokens\n // No billed token of any kind means there is nothing to report yet: a `$0.00`\n // pill on a session that has not made a request would be noise, not\n // information, and on a free model it would be redundant.\n if (uncachedInput === 0 && output === 0 && cacheRead === 0 && cacheWrite === 0) return undefined\n\n // Free priced groups do not establish zero spending for unpriced groups:\n // keep the pure-Free label and real sub-cent amounts, but never a zero\n // subtotal.\n if (!free && total <= 0) return undefined\n\n const value = free\n ? SESSION_COST_COPY.free\n : `${partial ? '≥' : SESSION_COST_COPY.approximate}${sessionCostAmount(total)}`\n const money = (amount: number | undefined): string | undefined =>\n amount === undefined ? undefined : sessionCostAmount(amount)\n // Reading order mirrors the prompt's own order: what was charged at the input\n // rate, then the two cache buckets, then what the model produced.\n const rows: SessionCostBucketRow[] = [\n { key: 'uncachedInput', label: SESSION_COST_COPY.uncachedInput, tokens: uncachedInput, costText: money(breakdown.uncachedInput) },\n { key: 'cacheRead', label: SESSION_COST_COPY.cacheRead, tokens: cacheRead, costText: money(breakdown.cacheRead) },\n { key: 'cacheWrite', label: SESSION_COST_COPY.cacheWrite, tokens: cacheWrite, costText: unpricedCacheWriteTokens === cacheWrite && cacheWrite > 0 ? undefined : money(breakdown.cacheWrite) },\n { key: 'output', label: SESSION_COST_COPY.output, tokens: output, costText: money(breakdown.output) },\n ]\n if (unpricedCacheWriteTokens > 0) notes.push(SESSION_COST_COPY.unpricedCacheWrite)\n // Empty clauses are dropped BEFORE joining: `clause()` returns undefined for\n // a bucket with no tokens, and joining the raw list would leave a `· ·` gap\n // per absent bucket — a tooltip that reads as a rendering bug.\n const title = ([\n `${SESSION_COST_COPY.panelTitle} ${free ? SESSION_COST_COPY.free : sessionCostAmount(total)}`,\n clause(SESSION_COST_COPY.uncachedInput, uncachedInput),\n clause(SESSION_COST_COPY.output, output),\n clause(SESSION_COST_COPY.cacheRead, cacheRead),\n clause(SESSION_COST_COPY.cacheWrite, cacheWrite),\n ...notes,\n ] as Array<string | undefined>).filter((part): part is string => part !== undefined).join(' · ')\n\n return {\n total,\n value,\n title,\n rows,\n notes: [...new Set(notes)],\n free,\n peak,\n unpricedCacheWriteTokens,\n approximate: !free,\n }\n}\n\n/**\n * The two nodes the text appended to the harness's token-usage pill is made of.\n *\n * The separator is a node of its own because it carries the shipped pill's\n * SEPARATOR colour rather than its label colour; the pill is a flex row whose\n * `gap` already spaces the appended item, so the separator is what makes the\n * result read as one continuous run (`1.2M tokens · Cache hit 87% · $0.0123`).\n */\nexport interface SessionCostPillRun {\n /** The shipped pill's own separator glyph. */\n separator: string\n /** The amount, `≈` marker and free word included. */\n value: string\n}\n\n/** Split the appended run into the two nodes the display creates. */\nexport function sessionCostPillRun(view: SessionCostView): SessionCostPillRun {\n return { separator: SESSION_COST_COPY.separator, value: view.value }\n}\n\n/**\n * How the harness's own usage dialog is decorated: one entry per row the\n * shipped component renders, IN ITS OWN ORDER.\n *\n * The price goes on the right of the row it belongs to (`3,206,544 tok $0.07`)\n * rather than in a block of our own rows beneath them, so the dialog keeps the\n * harness's layout and gains nothing to read past.\n *\n * Two rows are special. `cacheHit` carries a percentage, not a count, so it is\n * never priced. `cacheWrite` may be HIDDEN, and only then: the pricing page\n * publishes a cache-write rate for a minority of models, so its cell read\n * `unpriced` far more often than a number — but its tokens still count toward\n * the total the pill shows.\n */\nexport type SessionCostShippedRow = 'cacheHit' | 'uncachedInput' | 'cacheRead' | 'cacheWrite' | 'output'\n\n/** One shipped dialog row and what to do with it. */\nexport interface SessionCostRowDecoration {\n /** Which shipped row this is. */\n row: SessionCostShippedRow\n /**\n * The exact token count that row must be showing, or undefined for a row that\n * carries no count. The display layer verifies it before decorating anything:\n * the shipped labels are the `chat` locale's own strings (never English), so\n * rows are matched POSITIONALLY and this is what proves the position is right.\n */\n tokens: number | undefined\n /** The price to append to the row's value, or undefined to leave it alone. */\n amount: string | undefined\n /** Whether the row is dropped from the dialog entirely. */\n hidden: boolean\n}\n\n/**\n * Decorate the harness's usage dialog, row by row.\n *\n * The row sequence mirrors the shipped component's conditions exactly — the\n * cache-hit row exists while there is billed prompt input, the cache-write row\n * while those tokens are non-zero — because the display layer matches what it\n * finds positionally. A shape it cannot confirm is a shape it does not touch.\n *\n * A free model decorates nothing: every row's cost is zero by definition, the\n * pill already says `Free`, and a column of `$0.00` would be noise. A bucket\n * whose rate the page does not publish is likewise left unfilled rather than\n * filled with an invented number.\n */\nexport function sessionCostRowDecorations(view: SessionCostView): SessionCostRowDecoration[] {\n const bucket = (key: SessionCostBucketRow['key']): number =>\n view.rows.find((row) => row.key === key)?.tokens ?? 0\n const price = (key: SessionCostBucketRow['key']): string | undefined => {\n if (view.free) return undefined\n return view.rows.find((row) => row.key === key)?.costText\n }\n const uncachedInput = bucket('uncachedInput')\n const cacheRead = bucket('cacheRead')\n const cacheWrite = bucket('cacheWrite')\n const output = bucket('output')\n const plan: SessionCostRowDecoration[] = []\n if (uncachedInput + cacheRead + cacheWrite > 0) {\n plan.push({ row: 'cacheHit', tokens: undefined, amount: undefined, hidden: false })\n }\n plan.push({ row: 'uncachedInput', tokens: uncachedInput, amount: price('uncachedInput'), hidden: false })\n plan.push({ row: 'cacheRead', tokens: cacheRead, amount: price('cacheRead'), hidden: false })\n if (cacheWrite !== 0) {\n // Hidden only when the page publishes NO cache-write rate: those tokens are\n // genuinely unpriced, the note says so, and the row would otherwise show a\n // blank cell. When the rate IS known its price is part of the total, so the\n // row must stay — hiding it leaves the visible rows unable to explain the\n // figure above them.\n const amount = price('cacheWrite')\n plan.push({ row: 'cacheWrite', tokens: cacheWrite, amount, hidden: amount === undefined })\n }\n plan.push({ row: 'output', tokens: output, amount: price('output'), hidden: false })\n return plan\n}\n","/**\n * The DOM half of the composer's session-cost figure (browser only).\n *\n * The cost is not a surface of its own any more: it is injected INTO the two\n * surfaces the harness already draws under the composer — the token-usage pill\n * and the usage dialog that pill opens. This module owns that injection;\n * `./session-cost.ts` owns every number and string, and `./session-cost-view.tsx`\n * the two seats the figures come from.\n *\n * Why inject rather than take the pill's cell over (registering a `stats` entry\n * REPLACES the shipped readout, it does not extend it): that row is one component\n * owning its tokens / cache-hit / duration figures through the `chat` locale\n * namespace, and its cache-hit percentage obeys an exact-integer rule this plugin\n * must not re-derive. Owning it would mean reproducing all of it in English, and\n * every upstream change would stop reaching users.\n *\n * Four properties make the injection safe:\n *\n * 1. **The dialog's rows are styled by ELEMENT.** `dsh-client-ui-chat`'s\n * `stat-dialog` module styles its `dl` as a two-column grid and then\n * `.details dt` / `.details dd` — not by class, so a price node appended\n * INSIDE a shipped value cell inherits that cell's tabular numerals and right\n * alignment, and this plugin ships no CSS at all.\n * 2. **The dialog's rows are matched by POSITION and confirmed by value.** Their\n * labels are the `chat` locale's own strings, so no label is ever read: the\n * shape is predicted from the session's buckets and each value cell must then\n * carry exactly the token count predicted for it. A dialog that does not\n * confirm is left alone.\n * 3. **The pill keeps the cost visible when space runs out.** The button is an\n * inline flex row with `gap` and its label carries `min-width:0` plus ellipsis;\n * our appended span keeps the default `min-width:auto`, so the LABEL is what\n * truncates, and the cost inherits the button's typography and tint.\n * 4. **React owns those value cells' text, so a price is re-attached, never\n * assumed.** The shipped component renders each count as a single string, and\n * React rewrites such a cell through `textContent` when the count changes —\n * dropping every child with it, our price included. Every sync therefore\n * re-checks that the node is still where it was put; the cost of that is a\n * read, and the alternative is a price that silently disappears mid-session.\n *\n * A `MutationObserver` on `document.body` with `childList` (deliberately NOT\n * `subtree`, so streaming text never wakes it) is the only way to learn that the\n * portaled dialog has opened or closed. That observer is also what decorates a\n * newly opened dialog from the last view this module was handed.\n *\n * @module dsh-commandcode-provider/client/session-cost-display\n */\n\nimport type { SessionCostPillRun, SessionCostRowDecoration, SessionCostShippedRow, SessionCostView } from './session-cost.ts'\nimport {\n SESSION_COST_COPY,\n sessionCostPillRun,\n sessionCostRowDecorations,\n} from './session-cost.ts'\n\n/**\n * The shipped composer stats row (dsh-client-ui-chat `StatsPills`).\n *\n * A PREFERENCE, not a requirement: the attribute has been dropped TWICE\n * upstream — in 0.1.6-alpha.2, and again in 0.2.1-alpha.1, where the single\n * `StatsPills` component became two independent dock entries (`activity` and\n * `usage`) and each pill lost the shared row wrapper this selector named. A\n * lookup that insisted on it would silently stop finding the row. When it is\n * absent the search falls back to the dock OUTLET — deliberately the outlet\n * and never the outlet's parent, because the parent is the composer footer,\n * which holds the `ContextMeter` as well, and that meter's trigger is itself a\n * `button[aria-haspopup=\"dialog\"]` rendered AFTER the dock. A parent-scoped\n * \"last trigger wins\" would append the cost to the context ring instead.\n *\n * The fallback is still correct on 0.2.1-alpha.1: the dock registers `activity`\n * at order 0 and `usage` at order 1, both keep `aria-haspopup=\"dialog\"` on their\n * trigger button, and `data-session-stats-usage` remains unique to the token\n * dialog — so \"last trigger wins\" still selects the usage pill.\n */\nconst STATS_ROOT = '[data-composer-stats]'\n\n/**\n * The shipped token-usage dialog's `<dl>`. Unique WITHIN one `StatsPills`\n * render (the per-message turn-usage panel has its own dialog with different\n * markup), but not across the document once two composers are live — see\n * {@link resolveDialog}.\n */\nconst USAGE_DIALOG = '[data-session-stats-usage]'\n\n/**\n * The usage dialog's trigger. Both pills announce a dialog, but the token one is\n * rendered LAST — and when no step carries timing the time pill is not a button\n * at all, so \"last\" still selects the token pill in both cases.\n */\nconst DIALOG_TRIGGER = 'button[aria-haspopup=\"dialog\"]'\n\n/**\n * Stable id for the hidden node the appended cost is described by. The pill's own\n * `aria-label` is recomputed by the harness on every render and cannot be\n * extended, so a description is how the cost reaches assistive technology.\n */\nconst A11Y_ID = 'dsh-commandcode-session-cost'\n\n/** How many consecutive misses before the missing anchor is worth a console line. */\nconst MISSES_BEFORE_WARNING = 3\n\n/**\n * How the display learns that the shipped usage dialog opened or closed.\n *\n * `target` is `document.body`, and the returned function detaches. The default\n * is a `MutationObserver`; the seam exists so tests can announce the dialog\n * without a global observer (the repository's usual injected-seam shape).\n */\nexport type SessionCostObserverFactory = (target: Node, listener: () => void) => (() => void) | undefined\n\n/**\n * The default observer: `childList` on `body`, and deliberately NOT `subtree`, so\n * streaming text inside the page never wakes it while the panel the harness\n * portals straight onto `body` does.\n */\nconst observeBodyChildren: SessionCostObserverFactory = (target, listener) => {\n if (typeof MutationObserver === 'undefined') return undefined\n const observer = new MutationObserver(listener)\n observer.observe(target, { childList: true })\n return () => observer.disconnect()\n}\n\n/** What the display layer reads: the injected document and where to look in it. */\nexport interface SessionCostDisplayOptions {\n /** The document to inject into (injected so node tests can drive a double). */\n doc: Document\n /**\n * The composer that owns this entry — our own dock OUTLET, so a session-scoped\n * composer looks in its OWN card rather than at whichever `[data-composer-stats]`\n * happens to come first in the document.\n */\n scope: () => ParentNode | null\n /** Observer seam; defaults to a `childList` `MutationObserver` on `body`. */\n observe?: SessionCostObserverFactory\n}\n\n/**\n * Owns the nodes injected into the shipped token-usage UI.\n *\n * One instance per mounted entry. `sync()` is cheap and idempotent: it re-reads\n * both targets on every call, which is what lets it self-heal when React\n * remounts the row or replaces the dialog, and it rewrites a node only when its\n * text actually changed.\n */\nexport class SessionCostDisplay {\n private readonly doc: Document\n private readonly scope: () => ParentNode | null\n private readonly observe: SessionCostObserverFactory\n private view: SessionCostView | undefined = undefined\n /** Detaches the observer installed by `start()`. */\n private detach: (() => void) | undefined = undefined\n /** The button we appended into, while it is still connected. */\n private pillHost: Element | undefined = undefined\n /** Our appended root, and the two nodes whose text changes. */\n private pillRoot: HTMLElement | undefined = undefined\n private pillValue: HTMLElement | undefined = undefined\n private pillA11y: HTMLElement | undefined = undefined\n /** Whether WE set `aria-describedby` on the button (so only we take it back). */\n private described = false\n /** The dialog we decorated, the price nodes we own, and the cells we hid. */\n private dialogHost: Element | undefined = undefined\n private dialogPrices = new Map<HTMLElement, HTMLElement>()\n private dialogHidden = new Set<HTMLElement>()\n private pillMisses = 0\n\n constructor(options: SessionCostDisplayOptions) {\n this.doc = options.doc\n this.scope = options.scope\n this.observe = options.observe ?? observeBodyChildren\n }\n\n /** Begin watching for the shipped usage dialog opening and closing. */\n start(): void {\n if (this.detach !== undefined) return\n const body = this.doc.body\n if (body === null || body === undefined) return\n this.detach = this.observe(body, () => this.apply())\n }\n\n /**\n * Hand the display the current figure.\n *\n * Undefined — nothing priceable about this session — removes everything this\n * module injected, leaving both shipped surfaces exactly as they ship.\n */\n sync(view: SessionCostView | undefined): void {\n this.view = view\n this.apply()\n }\n\n /** Remove every injected node and stop observing. Safe to call twice. */\n dispose(): void {\n this.detach?.()\n this.detach = undefined\n this.removePill()\n this.clearDialog()\n this.view = undefined\n }\n\n /** Re-apply the last known view to whatever both targets are right now. */\n private apply(): void {\n this.applyPill()\n this.applyDialog()\n }\n\n // --- The pill: the cost as the last item of the shipped token pill's run\n\n private applyPill(): void {\n const view = this.view\n if (view === undefined) {\n this.removePill()\n return\n }\n if (this.pillHost?.isConnected !== true) {\n const button = this.resolvePillButton()\n if (button === null) {\n this.pillMisses += 1\n if (this.pillMisses === MISSES_BEFORE_WARNING) {\n console.warn(\n '[dsh-commandcode-provider] no shipped token pill in this composer\\'s dock outlet to append the session cost to; the figure stays in the usage dialog only',\n )\n }\n return\n }\n this.pillMisses = 0\n this.removePill()\n this.buildPill(button, sessionCostPillRun(view))\n }\n if (this.pillValue !== undefined) {\n const amount = sessionCostPillRun(view).value\n if (this.pillValue.textContent !== amount) this.pillValue.textContent = amount\n }\n if (this.pillRoot !== undefined) {\n if (this.pillRoot.title !== view.title) this.pillRoot.title = view.title\n const approximate = view.approximate ? 'true' : null\n if (this.pillRoot.getAttribute('data-approximate') !== approximate) {\n if (approximate === null) this.pillRoot.removeAttribute('data-approximate')\n else this.pillRoot.setAttribute('data-approximate', approximate)\n }\n }\n if (this.pillA11y !== undefined) {\n const described = `${SESSION_COST_COPY.panelTitle} ${view.value}`\n if (this.pillA11y.textContent !== described) this.pillA11y.textContent = described\n }\n }\n\n /**\n * The shipped token pill, scoped to this entry's own composer.\n *\n * The scope is the dock OUTLET (`display: contents`, one per slot), which holds\n * exactly that slot's entries — the shipped `stats` cell and ours, in their\n * registration order. {@link STATS_ROOT} narrows that to the stats row where\n * the markup marks it; where it does not, the outlet is already the narrowest\n * correct container, because the composer footer's `ContextMeter` sits BESIDE\n * the outlet rather than inside it. A missing scope is \"no pill\", never a\n * document-wide search: the outlet is what makes this lookup per-composer, and\n * two composers can be live at once.\n */\n private resolvePillButton(): Element | null {\n const scope = this.scope()\n if (scope === null) return null\n const root = scope.querySelector(STATS_ROOT) ?? scope\n const triggers = root.querySelectorAll(DIALOG_TRIGGER)\n return triggers.length === 0 ? null : (triggers[triggers.length - 1] ?? null)\n }\n\n /**\n * Create and append the cost run. The button's child list is static\n * (`[svg, label]`), so appending once is enough for it to stay last.\n */\n private buildPill(button: Element, run: SessionCostPillRun): void {\n const doc = this.doc\n const root = doc.createElement('span')\n root.setAttribute('data-composer-session-cost', '')\n // The separator is its own node so it can carry the shipped pill's separator\n // colour. Its LEFT spacing comes from the button's flex gap; the right margin\n // reproduces the shipped separator's `margin:0 6px` rhythm, so the run reads\n // at one consistent rhythm.\n const separator = doc.createElement('span')\n separator.textContent = run.separator\n separator.setAttribute('aria-hidden', 'true')\n separator.style.color = 'var(--dsw-alias-separator-primary)'\n separator.style.margin = '0 6px 0 0'\n const value = doc.createElement('span')\n value.textContent = run.value\n value.style.fontWeight = '500'\n // Referenced by the button's `aria-describedby`: a hidden node named by id is\n // still read out, which is how the cost survives the aria-label override.\n const a11y = doc.createElement('span')\n a11y.id = A11Y_ID\n a11y.style.display = 'none'\n root.appendChild(separator)\n root.appendChild(value)\n root.appendChild(a11y)\n button.appendChild(root)\n // Only ever claim the attribute when the button has none of its own: a\n // shipped `aria-describedby` is the harness's, and overwriting it would\n // delete a description we cannot restore.\n if (!button.hasAttribute('aria-describedby')) {\n button.setAttribute('aria-describedby', A11Y_ID)\n this.described = true\n }\n this.pillHost = button\n this.pillRoot = root\n this.pillValue = value\n this.pillA11y = a11y\n }\n\n private removePill(): void {\n if (this.pillRoot !== undefined && this.pillRoot.parentNode !== null) {\n this.pillRoot.parentNode.removeChild(this.pillRoot)\n }\n if (this.described) {\n this.pillHost?.removeAttribute('aria-describedby')\n this.described = false\n }\n this.pillHost = undefined\n this.pillRoot = undefined\n this.pillValue = undefined\n this.pillA11y = undefined\n }\n\n // --- The dialog: a price on the right of each row the harness already draws\n\n private applyDialog(): void {\n const view = this.view\n const host = view === undefined ? null : this.resolveDialog()\n if (host === null || view === undefined) {\n this.clearDialog()\n return\n }\n this.pruneDialog(host)\n const plan = sessionCostRowDecorations(view)\n const pairs = dialogPairs(host)\n if (!dialogShapeMatches(pairs, plan, this.dialogPrices)) {\n // Not the shape this session's buckets predict — a different build, or a\n // projection carrying values the counts cannot explain. Leave it as the\n // harness drew it rather than pricing the wrong row.\n this.clearDialog()\n return\n }\n const hidden = new Set<HTMLElement>()\n for (const [index, row] of plan.entries()) {\n const pair = pairs[index]\n if (pair === undefined) continue\n const span = this.dialogPrices.get(pair.dd)\n if (row.hidden) {\n // Both cells go, or the grid leaves an empty label behind. An inline\n // `display` survives the harness's own re-renders (React pins no style\n // on these nodes) and is given back on disposal.\n if (pair.dt.style.display !== 'none') pair.dt.style.display = 'none'\n if (pair.dd.style.display !== 'none') pair.dd.style.display = 'none'\n hidden.add(pair.dt)\n hidden.add(pair.dd)\n this.removeDialogPrice(pair.dd, span)\n continue\n }\n if (pair.dt.style.display === 'none') pair.dt.style.display = ''\n if (pair.dd.style.display === 'none') pair.dd.style.display = ''\n if (row.amount === undefined) {\n this.removeDialogPrice(pair.dd, span)\n continue\n }\n const price = span ?? this.createDialogPrice(pair.dd, row.row)\n // React owns this cell's text and rewrites it through `textContent` when\n // the count changes, dropping every child with it — so the price is\n // re-attached on a miss rather than assumed to still be there.\n if (price.parentNode !== pair.dd) pair.dd.appendChild(price)\n if (price.textContent !== row.amount) price.textContent = row.amount\n }\n // Cells hidden by an earlier shape (a cache-write row React then rewrote) go\n // back to the harness.\n for (const cell of [...this.dialogHidden]) {\n if (hidden.has(cell)) continue\n if (cell.style.display === 'none') cell.style.display = ''\n this.dialogHidden.delete(cell)\n }\n for (const cell of hidden) this.dialogHidden.add(cell)\n this.dialogHost = host\n }\n\n /** Forget the cells and prices a re-rendered dialog took with it. */\n private pruneDialog(host: Element): void {\n for (const [dd, price] of [...this.dialogPrices]) {\n if (dd.parentNode === host) continue\n if (price.parentNode !== null) price.parentNode.removeChild(price)\n this.dialogPrices.delete(dd)\n }\n for (const cell of [...this.dialogHidden]) {\n if (cell.parentNode === host) continue\n // The dialog was re-rendered and this cell went with the old tree. Give\n // the style back BEFORE dropping the reference: a detached node can be\n // recycled by the next render (React reuses DOM nodes across a remount of\n // the same shape), and a surviving `display: none` would hide a row of a\n // dialog we are no longer decorating, with nothing left tracking it.\n if (cell.style.display === 'none') cell.style.display = ''\n this.dialogHidden.delete(cell)\n }\n }\n\n /** The price node for one shipped value cell, appended as its last child. */\n private createDialogPrice(dd: HTMLElement, row: SessionCostShippedRow): HTMLElement {\n const price = this.doc.createElement('span')\n price.setAttribute('data-session-cost-price', row)\n // The cell is right-aligned over tabular numerals, so a fixed-width\n // inline-block lines the prices up as a column of their own.\n price.style.marginLeft = '6px'\n price.style.display = 'inline-block'\n price.style.minWidth = '56px'\n price.style.textAlign = 'right'\n price.style.fontWeight = '500'\n dd.appendChild(price)\n this.dialogPrices.set(dd, price)\n return price\n }\n\n private removeDialogPrice(dd: HTMLElement, price: HTMLElement | undefined): void {\n if (price === undefined) return\n if (price.parentNode !== null) price.parentNode.removeChild(price)\n this.dialogPrices.delete(dd)\n }\n\n /**\n * The shipped usage dialog, or null while it is closed (or ambiguous).\n *\n * The dialog is portaled onto `body`, so unlike the pill it cannot be scoped\n * from this entry, and the attribute is unique per DIALOG rather than per\n * document. While one composer was guaranteed a document-level lookup was\n * exact; 0.1.6-alpha.2 ended that guarantee by mounting an embedded\n * Conversation in the sidebar, so a second composer — its own session, dock and\n * dialog — can be live and open at the same time.\n *\n * There is no DOM link from a dialog back to its trigger (the portaled panel\n * carries no id and no `aria-controls`), so document order says nothing about\n * ownership. The shape confirmation in {@link dialogShapeMatches} would usually\n * reject the stranger, but it compares against THIS entry's counts, so a\n * coincidentally matching dialog would be priced with another session's\n * figures. Ambiguity is therefore answered by declining to decorate at all:\n * a dialog we cannot prove is ours is left alone.\n */\n private resolveDialog(): Element | null {\n if (this.dialogHost?.isConnected === true) return this.dialogHost\n // The dialog we injected into is gone: our nodes went with it, so only the\n // bookkeeping is left to drop.\n this.clearDialog()\n const dialogs = this.doc.querySelectorAll(USAGE_DIALOG)\n return dialogs.length === 1 ? (dialogs[0] ?? null) : null\n }\n\n /** Give the dialog back: every price removed, every hidden row restored. */\n private clearDialog(): void {\n for (const price of this.dialogPrices.values()) {\n if (price.parentNode !== null) price.parentNode.removeChild(price)\n }\n this.dialogPrices.clear()\n for (const cell of this.dialogHidden) {\n if (cell.style.display === 'none') cell.style.display = ''\n }\n this.dialogHidden.clear()\n this.dialogHost = undefined\n }\n}\n\n/** The shipped dialog's `dt`/`dd` pairs, in document order. */\nfunction dialogPairs(host: Element): Array<{ dt: HTMLElement; dd: HTMLElement }> {\n const pairs: Array<{ dt: HTMLElement; dd: HTMLElement }> = []\n let label: HTMLElement | null = null\n for (const node of Array.from(host.childNodes)) {\n const tag = tagNameOf(node)\n if (tag === 'DT') label = node as HTMLElement\n else if (tag === 'DD' && label !== null) {\n pairs.push({ dt: label, dd: node as HTMLElement })\n label = null\n }\n }\n return pairs\n}\n\n/** `tagName` upper-cased, or an empty string for a non-element node. */\nfunction tagNameOf(node: Node): string {\n const tag = (node as Element).tagName\n return typeof tag === 'string' ? tag.toUpperCase() : ''\n}\n\n/**\n * Whether the dialog really holds the rows this session's buckets predict.\n *\n * The shipped labels belong to the `chat` locale and differ per language, so rows\n * are matched by POSITION, and this is what makes that safe: the row count must\n * agree, the cache-hit row must be the percentage it is, and every other value\n * must carry exactly the token count of the bucket predicted for it. A mismatch\n * means the dialog is not what this view describes, and nothing is decorated.\n */\nfunction dialogShapeMatches(\n pairs: ReadonlyArray<{ dt: HTMLElement; dd: HTMLElement }>,\n plan: readonly SessionCostRowDecoration[],\n prices: ReadonlyMap<HTMLElement, HTMLElement>,\n): boolean {\n if (pairs.length !== plan.length) return false\n return plan.every((row, index) => {\n const pair = pairs[index]\n if (pair === undefined) return false\n const text = hostValueText(pair.dd, prices.get(pair.dd))\n if (row.tokens === undefined) return text.includes('%')\n return digitsOf(text) === String(row.tokens)\n })\n}\n\n/**\n * A value cell's own text, without the price this module appended to it — the\n * digits of `3,206,544 tok` are the host's, the digits of `$0.07` are ours.\n */\nfunction hostValueText(dd: HTMLElement, price: HTMLElement | undefined): string {\n let text = ''\n for (const node of Array.from(dd.childNodes)) {\n if (node === price) continue\n text += node.textContent ?? ''\n }\n return text\n}\n\n/** Every digit of a display string, so locale grouping cannot break the match. */\nfunction digitsOf(text: string): string {\n return text.replace(/\\D/g, '')\n}\n","/**\n * The composer's live session-cost figure (browser half).\n *\n * This component renders NO surface of its own: the cost lives inside the\n * harness's own token-usage UI, the amount as the last item of the shipped\n * pill's text run (`1.2M tokens · Cache hit 87% · $0.0123`) and the breakdown as\n * extra rows in the usage dialog that pill opens. `./session-cost-display.ts`\n * owns that injection and `./session-cost.ts` every number and string; this file\n * owns the two seats the figures come from and the injection's lifetime.\n *\n * It is registered in `conversation.composer.dock` because that registration is\n * what delivers the seats: `useProjection` is a standard prop the composer hands\n * every dock occupant, and registering under the shipped `stats` cell's id would\n * REPLACE the harness's readout instead of extending it.\n *\n * The rendered node is a hidden marker — `display:none`, so it adds neither a box\n * nor a flex gap. It locates THIS composer from the entry (`closest()` on the\n * dock's outlet anchor), so a session-scoped composer reads its own card rather\n * than whichever row comes first, and it renders only while there is something\n * to show.\n *\n * Two seats are read, from two different owners: `useProjection` comes from the\n * composer (a standard prop, not part of this registration) and\n * `useCommandCodePrices` from our own `inject` face. Reading `props.hooks.*`\n * instead finds `undefined` at runtime and crashes the render, which the slot\n * renderer contains by ABDICATING the entry — a surface that vanishes with no\n * visible error. Both effects are `useEffect`, never `useLayoutEffect`: there is\n * nothing on screen to align with, and a layout effect would warn from the\n * server render the tests use.\n *\n * @module dsh-commandcode-provider/client/session-cost-view\n */\n\nimport type { SessionCostFacts } from '../cost-facts.ts'\nimport { useEffect, useRef } from 'react'\nimport type { SnapshotStore } from './snapshot-store.ts'\nimport type { SessionCostPricesState } from './prices.ts'\nimport { SessionCostDisplay } from './session-cost-display.ts'\nimport {\n buildSessionCostView,\n type SessionModelSelectionProjection,\n type SessionUsageBuckets,\n} from './session-cost.ts'\n\n/**\n * The dock outlet this entry renders inside, i.e. what it scopes itself from.\n *\n * The OUTLET, not its parent. The outlet is one `display:contents` div holding\n * exactly this slot's entries (the shipped `stats` cell and ours), so it is the\n * narrowest container that is still per-composer. Its parent is NOT: from\n * 0.1.6-alpha.2 the composer stacks the dock inside a footer that also holds the\n * `ContextMeter`, whose trigger is another `button[aria-haspopup=\"dialog\"]`\n * rendered after the dock — scoping to the parent would let the cost land on the\n * context ring.\n */\nconst DOCK_ANCHOR = '[data-slot=\"conversation.composer.dock\"]'\n\n/** Module-level constant so the marker's `style` prop never diffs. */\nconst HIDDEN_STYLE = { display: 'none' } as const\n\n/**\n * The injected face this registration carries. Bound by the client entry so the\n * component stays unaware of the Remote, the controller, and its caching.\n *\n * NOTE the split from {@link SessionCostComponentProps}: the renderer\n * destructures this face's `hooks` compartment and re-exposes each member as a\n * `use<Name>` prop (`commandCodePrices` → `useCommandCodePrices`); it does not\n * hand the component this object verbatim.\n */\nexport interface SessionCostInjected {\n hooks: {\n commandCodePrices: SnapshotStore<SessionCostPricesState>\n }\n}\n\n/**\n * The projection keys this readout reads, declared structurally because the\n * plugin bundle does not depend on the session-controller package (whose\n * `UseProjection` this mirrors).\n */\ninterface ProjectionSeats {\n commandCodeCost: SessionCostFacts\n tokenUsage: SessionUsageBuckets\n modelSelection: SessionModelSelectionProjection\n}\n\n/** The projection reader the composer supplies to every dock occupant. */\nexport interface UseProjectionLike {\n <K extends keyof ProjectionSeats>(key: K): ProjectionSeats[K] | undefined\n <K extends keyof ProjectionSeats, S>(\n key: K,\n selector: (value: ProjectionSeats[K] | undefined) => S,\n eq?: (a: S, b: S) => boolean,\n ): S\n}\n\n/** The props this component actually receives. */\nexport interface SessionCostComponentProps {\n useCommandCodePrices<T>(selector: (state: SessionCostPricesState) => T): T\n useProjection: UseProjectionLike\n}\n\n/** Log a missing seat once per page, so a silent no-op stays diagnosable. */\nlet warnedMissingSeat = false\n\n/**\n * The composer's session-cost entry. Guards the two seats before rendering the\n * mount: a dsh that does not supply the projection seat to dock occupants gets\n * an absent cost and one console line, never a render crash — which the renderer\n * would answer by abdicating the entry with no visible trace.\n */\nexport function CommandCodeSessionCost(props: SessionCostComponentProps) {\n if (typeof props.useProjection !== 'function' || typeof props.useCommandCodePrices !== 'function') {\n if (!warnedMissingSeat) {\n warnedMissingSeat = true\n console.error(\n '[dsh-commandcode-provider] the composer does not supply the projection/hook seats the session-cost readout needs; the readout stays hidden',\n )\n }\n return null\n }\n return <SessionCostEntry {...props} />\n}\n\n/** The mount: one injection lifetime, one hidden marker. Every hook lives here. */\nfunction SessionCostEntry(props: SessionCostComponentProps) {\n const markerRef = useRef<HTMLSpanElement | null>(null)\n const displayRef = useRef<SessionCostDisplay | null>(null)\n const prices = props.useCommandCodePrices((state) => state)\n const usage = props.useProjection('tokenUsage')\n const selection = props.useProjection('modelSelection')\n const facts = props.useProjection('commandCodeCost')\n const view = buildSessionCostView({ usage, selection, facts, table: prices.table, now: Date.now() })\n\n useEffect(() => {\n // No DOM outside a browser: the server render used by the tests, and a\n // node-hosted assembly, must both stay no-ops.\n if (typeof document === 'undefined') return\n const display = new SessionCostDisplay({\n doc: document,\n scope: () => markerRef.current?.closest(DOCK_ANCHOR) ?? null,\n })\n displayRef.current = display\n display.start()\n return () => {\n displayRef.current = null\n display.dispose()\n }\n }, [])\n\n // Every render: the projection is a fresh fold, so there is nothing cheaper to\n // compare than the plan the display derives from it — and the display rewrites\n // a node only when that node's own text actually moved.\n useEffect(() => {\n displayRef.current?.sync(view)\n })\n\n if (view === undefined) return null\n return <span ref={markerRef} style={HIDDEN_STYLE} data-ccp-session-cost-anchor=\"\" />\n}\n","/**\n * Stylesheet for the Command Code settings page — and the Models-page provider\n * card, which shares its `cc-` classes.\n *\n * Returned as a string, not injected here, so importing this module has no DOM\n * side effect: `./index.ts` installs it once under {@link PAGE_CSS_ID}. It is a\n * module of its own rather than a literal in the entry so `tests/styles.test.ts`\n * can audit every rule without importing the React tree (which pulls\n * `*.module.css` through the primitives package and needs a loader registered\n * first). The rules are GLOBAL CSS, so containment is a contract (issue #48):\n * every selector is qualified by one of our own `cc-` classes. Colours are\n * harness theme aliases with neutral fallbacks, and the `cc-` prefix keeps\n * these clear of the panel's `ccp-` set.\n *\n * @module dsh-commandcode-provider/client/page-styles\n */\n\n/**\n * Stylesheet id — the `data-plugin-css` value that makes injection idempotent.\n *\n * The prefix must match this package's real name and the panel stylesheet's\n * (`PANEL_CSS_ID`); the two ids must also stay DISTINCT, since they key two\n * separate style tags and a shared id would make the second injection a no-op.\n */\nexport const PAGE_CSS_ID = '@mars-sea/dsh-commandcode-provider/CommandCodeSettingsPage.module.css'\n\n/**\n * The settings-page stylesheet.\n *\n * The metrics are the harness's own settings pages', read out of the 0.1.7\n * bundles so the page sits beside General and Models without looking foreign:\n * a row is 12px of padding, its title 14/22 label-primary and its description\n * 12/18 label-tertiary, the control on the right. The hairline rhythm is\n * section-level: a 0.5px border-l2 rule separates the GROUPS (see\n * `cc-groupDivided`), never the rows inside one, so a group's rows read as one\n * list. Selectors and buttons are capsules (36px / 28px compact), inputs are\n * 32px with an 8px radius and a 0.5px border-l4 edge, a card is a 0.5px\n * border-l4 outline with a 16px radius, and a nested panel is a\n * bg-module-platform fill with a 12px radius. Errors use state-error-primary.\n */\nexport const PAGE_CSS = `\n.cc-section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;display:flex}\n.cc-title{margin:0;color:var(--dsw-alias-label-primary);font-size:16px;font-weight:500;line-height:24px}\n.cc-intro{margin:4px 0 0;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px}\n.cc-readOnly{margin:8px 0 0;color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-tertiary));font-size:12px;line-height:18px}\n.cc-spacer{flex:1}\n.cc-group{flex-direction:column;display:flex;margin-top:28px}\n.cc-groupDivided{margin-top:24px;padding-top:20px;border-top:.5px solid var(--dsw-alias-border-l2)}\n.cc-groupHead{align-items:center;gap:8px;display:flex;min-height:28px;padding-bottom:4px}\n.cc-groupTitle{margin:0;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}\n.cc-groupDesc{margin:0 0 12px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-rows>.cc-groupDesc{margin:0;padding:4px 0 0}\n.cc-disclosure{width:100%;padding:0 0 4px;border:0;background:0 0;font:inherit;text-align:left;cursor:pointer;border-radius:6px}\n.cc-disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\n.cc-rows{flex-direction:column;display:flex}\n.cc-row{align-items:center;gap:8px;display:flex;padding:12px 0}\n.cc-rowFlush{padding:0}\n.cc-rowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:32px;display:flex}\n.cc-rowTitleLine{align-items:center;gap:8px;display:flex;min-width:0}\n.cc-rowTitle{min-width:0;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}\n.cc-rowDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-rowDesc p{margin:0}\n.cc-rowDesc p+p{margin-top:4px}\n.cc-rowError{margin:0;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.cc-rowControl{flex:none;align-items:center;justify-content:flex-end;gap:8px;display:inline-flex;max-width:60%}\n.cc-rowInput{width:200px}\n.cc-rowInputWide{width:280px}\n.cc-linkButton{box-sizing:border-box;flex:none;align-items:center;display:inline-flex;height:28px;padding:0 10px;border:0;border-radius:14px;background:0 0;color:var(--dsw-alias-label-tertiary);font:inherit;font-size:12px;line-height:18px;white-space:nowrap;cursor:pointer}\n.cc-linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}\n.cc-linkButton:disabled{cursor:default;opacity:.4}\n.cc-linkButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-badges{align-items:center;gap:8px;display:inline-flex}\n.cc-badge,.cc-badgeMuted{flex:none;align-items:center;display:inline-flex;white-space:nowrap;border-radius:999px;corner-shape:round;padding:1px 8px;font-size:12px;font-weight:500;line-height:17px}\n.cc-badge{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary)}\n.cc-badgeMuted{border:.5px solid var(--dsw-alias-border-l4);color:var(--dsw-alias-label-tertiary)}\n.cc-badgeWarn{background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-secondary))}\n.cc-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}\n.cc-field+.cc-field{border-top:.5px 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-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:18px}\n.cc-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.cc-reset:disabled{cursor:default;opacity:.4}\n.cc-input{box-sizing:border-box;height:32px;min-width:0;padding:0 10px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-1);font:inherit;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}\n.cc-input::placeholder{color:var(--dsw-alias-label-dimmed)}\n.cc-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}\n.cc-input:disabled{opacity:.6;cursor:default}\n.cc-inputInvalid{border-color:var(--dsw-alias-state-error-primary)}\n.cc-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n.cc-modelSelectAnchor{flex-direction:column;align-items:stretch;gap:6px;display:inline-flex;min-width:160px}\n.cc-selector{box-sizing:border-box;align-items:center;gap:12px;display:inline-flex;height:36px;padding:0 14px;border:0;border-radius:18px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;text-align:left;cursor:pointer}\n.cc-selector:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.cc-selector:disabled{cursor:default;opacity:.4}\n.cc-selector:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-selectorText{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.cc-selectorCaret{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-bottom:3px;transform:rotate(45deg)}\n/* The search box sits inside the Menu anchor, so typing in it never trips\n * the Menu's outside-click close. */\n.cc-modelSearch{width:100%}\n.cc-modelSearch::-webkit-search-cancel-button{cursor:pointer}\n.cc-checkRow{align-items:center;gap:8px;display:inline-flex;min-width:0}\n.cc-checkRow:hover{cursor:pointer}\n/* A hand-drawn box, not the platform's accent-color checkbox: the native\n * control's colours come from color-scheme, which the theme sets once at BOOT\n * and never re-applies in-session, so a native box can paint light-chrome white\n * on a dark page. The mark rides a brand-primary fill, so it takes the brand\n * foreground (the only pairing that survives dark mode's near-white brand), and\n * the outline is a border-l3 hairline because border-l2 leaves an unchecked box\n * invisible against the menu surface. */\n.cc-check{box-sizing:border-box;appearance:none;flex-shrink:0;width:16px;height:16px;margin:0;border:1px solid var(--dsw-alias-border-l3);border-radius:4px;background:0 0;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:3px;left:5px;width:3px;height:7px;border:solid var(--dsw-alias-label-primary-foreground,#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/* Modelled on the platform's own Switch primitive (ui-primitives\n * Switch.module.css): a 36x20 capsule padding its track by 2px and sliding a\n * 16px thumb across the 32px content box. Three things are load-bearing.\n * (1) corner-shape:round on BOTH track and thumb — the theme sets a global\n * superellipse corner shape, which squares a capsule's ends off around a round\n * thumb. (2) No literal colours: brand-primary INVERTS between the modes, so a\n * hardcoded white thumb vanishes on the checked track in dark mode; the brand\n * foreground is what the platform paints on that fill. (3) border-l3 as the\n * off track — border-l2 leaves it indistinguishable from the page. */\n.cc-toggle{box-sizing:border-box;appearance:none;flex-shrink:0;width:36px;height:20px;margin:0;padding:2px;border:0;border-radius:10px;corner-shape:round;background:var(--dsw-alias-border-l3);cursor:pointer;position:relative}\n.cc-toggle:checked{background:var(--dsw-alias-brand-primary)}\n.cc-toggle::after{content:'';display:block;width:16px;height:16px;border-radius:50%;corner-shape:round;background:var(--dsw-alias-label-primary-foreground);transition:transform .12s ease}\n.cc-toggle:checked::after{transform:translateX(16px)}\n.cc-toggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\n.cc-toggle:disabled{cursor:default;opacity:.5}\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:7px;height:7px;margin-right:6px;margin-bottom:3px;transform:rotate(45deg);transition:transform .15s ease}\n.cc-chevronUp{transform:rotate(-135deg);margin-bottom:-3px}\n.cc-accountMode{align-items:center;gap:4px;display:flex;margin:-4px 0 12px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}\n.cc-accountList{flex-direction:column;gap:8px;display:flex}\n.cc-accountList+.cc-addButton,.cc-accountList+.cc-addPanel{margin-top:8px}\n.cc-accountItem{flex-direction:column;gap:10px;display:flex;padding:12px 14px;border:.5px solid var(--dsw-alias-border-l4);border-radius:16px}\n.cc-accountItemActive{border-color:var(--dsw-static-neutral-bluish-400,var(--dsw-alias-border-l3))}\n.cc-accountHead{align-items:center;gap:4px;display:flex;min-height:28px}\n.cc-accountToggle{align-items:center;gap:8px;display:flex;flex:1;min-width:0;padding:0;background:0 0;border:0;color:inherit;cursor:pointer;font:inherit;text-align:left}\n.cc-accountToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;border-radius:4px}\n.cc-accountName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}\n.cc-iconButton{flex-shrink:0;align-items:center;justify-content:center;display:inline-flex;width:28px;height:28px;padding:0;background:0 0;border:0;border-radius:6px;color:var(--dsw-alias-label-tertiary);cursor:pointer}\n.cc-iconButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.cc-iconButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n/* Three dots from one element: the dot plus two box-shadow copies. */\n.cc-kebab{width:3px;height:3px;border-radius:50%;corner-shape:round;background:currentColor;box-shadow:0 -5px 0 currentColor,0 5px 0 currentColor}\n.cc-tabDot{flex-shrink:0;width:8px;height:8px;border-radius:50%;corner-shape:round}\n.cc-tabDotOk{background:var(--dsw-alias-state-success-primary)}\n.cc-tabDotBlank{background:0 0;border:0}\n.cc-tabDotWarn{background:var(--dsw-alias-state-warn-primary,#d97706)}\n.cc-tabDotError{background:var(--dsw-alias-state-error-primary)}\n.cc-accountMeters{flex-wrap:wrap;gap:6px 20px;display:flex;padding-left:16px}\n.cc-miniMeter{align-items:center;gap:8px;display:inline-flex;font-size:12px;line-height:18px}\n.cc-miniMeterLabel{color:var(--dsw-alias-label-tertiary)}\n.cc-miniMeterTrack{overflow:hidden;background:var(--dsw-alias-bg-module-platform);border-radius:999px;width:64px;height:4px}\n.cc-miniMeterFill{display:block;background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%}\n.cc-miniMeterValue{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums}\n.cc-accountSetup,.cc-loginStatus{flex-direction:column;gap:8px;display:flex;padding-left:16px}\n.cc-loginStatus{flex-direction:row;flex-wrap:wrap;align-items:center;gap:4px 12px}\n.cc-loginStatus>p{margin:0;font-size:12px;line-height:18px}\n.cc-accountDetails{container-type:inline-size;border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:14px;display:flex;padding-top:12px}\n.cc-inlineForm,.cc-confirmBar{flex-direction:column;gap:8px;display:flex}\n.cc-inlineActions{align-items:center;gap:8px;display:flex}\n.cc-confirmBar{border:.5px solid var(--dsw-alias-state-error-primary);border-radius:12px;padding:12px 14px}\n.cc-confirmText{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:22px}\n.cc-dangerButton{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}\n.cc-dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}\n.cc-addButton{box-sizing:border-box;align-items:center;justify-content:center;gap:6px;display:flex;width:100%;height:44px;border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;background:0 0;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;cursor:pointer}\n.cc-addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.cc-addButton:disabled{cursor:default;opacity:.4}\n.cc-addButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-addGlyph{position:relative;width:12px;height:12px}\n.cc-addGlyph::before,.cc-addGlyph::after{content:'';position:absolute;background:currentColor;border-radius:1px}\n.cc-addGlyph::before{left:0;right:0;top:5.25px;height:1.5px}\n.cc-addGlyph::after{top:0;bottom:0;left:5.25px;width:1.5px}\n.cc-addPanel{flex-direction:column;gap:12px;display:flex;padding:14px 16px;border-radius:12px;background:var(--dsw-alias-bg-module-platform)}\n.cc-panelTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}\n.cc-accountReport{flex-direction:column;gap:14px;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:14px;font-weight:500;line-height:22px}\n.cc-usageAccount{max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-usagePlan{flex:none;white-space:nowrap;border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:999px;corner-shape:round;padding:0 7px;font-size:12px;font-weight:500;line-height:17px}\n.cc-usagePlanStatus{flex:none;margin:0;white-space:nowrap;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.cc-usageHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n/* Two fixed grids, not one auto-fit track: auto-fit wrapped the four activity\n * tiles 3 + 1 at the details' width. The activity row folds to 2 × 2 in a\n * narrow details panel. */\n.cc-usageStats{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;display:grid}\n.cc-usageStatsActivity{grid-template-columns:repeat(4,minmax(0,1fr))}\n.cc-usageStatsBalance{grid-template-columns:repeat(3,minmax(0,1fr))}\n@container (max-width:460px){.cc-usageStatsActivity{grid-template-columns:repeat(2,minmax(0,1fr))}}\n.cc-usageStat{min-width:0;flex-direction:column;gap:2px;display:flex;padding:10px 12px;border-radius:12px;background:var(--dsw-alias-bg-module-platform)}\n.cc-usageStatLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-usageStatValue{color:var(--dsw-alias-label-primary);font-size:16px;font-weight:500;line-height:24px;font-variant-numeric:tabular-nums}\n.cc-usageStatSub{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.cc-usageWindows{flex-direction:column;gap:14px;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;line-height:18px}\n.cc-usageWindowValue{color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px;font-variant-numeric:tabular-nums}\n.cc-usageExceeded{color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.cc-usageBar{overflow:hidden;background:var(--dsw-alias-bg-module-platform);border-radius:999px;height:4px}\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-state-error-primary)}\n.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n.cc-usageMeta{align-items:center;gap:8px;display:flex}\n.cc-usageMetaSpacer{flex:1}\n.cc-usageUpdated{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n.cc-usagePartial{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}\n.cc-usageBlocked{border:.5px solid var(--dsw-alias-state-error-primary);border-radius:12px;padding:12px 14px;display:flex;flex-direction:column;gap:4px}\n.cc-usageBlockedTitle{color:var(--dsw-alias-state-error-primary);margin:0;font-size:14px;font-weight:500;line-height:22px}\n.cc-usageBlockedHint{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}\n.cc-usageBlockedDetail{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px;word-break:break-word}\n.cc-version{margin:32px 0 0;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-versionLink{color:var(--dsw-alias-state-warn-label,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.cc-providerCard{flex-direction:column;display:flex}\n.cc-footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}\n.cc-failed{display:inline-block;max-width:260px;min-width:0;color:var(--dsw-alias-state-error-primary);margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px}\n.cc-loginLink{color:var(--dsw-alias-link,var(--dsw-alias-brand-primary));text-decoration:none;font-size:12px;line-height:18px}\n.cc-loginLink:hover{text-decoration:underline;text-underline-position:under}\n.cc-loginDone{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary))}\n.cc-loginError{color:var(--dsw-alias-state-error-primary)}\n/* The floating save bar: a centered capsule pinned to the bottom of the\n * settings scrollport. The dock is a zero-height sticky strip at the end of the\n * page, so the bar overlays the scrolling content instead of taking a row of\n * its own; while shown, the section reserves room at its end so the last line\n * can scroll clear. Hidden, it sinks and fades, and visibility (switched after\n * the transition) takes its buttons out of the tab order. Its surface is an\n * elevated layer (bg-layer-1 over the settings panel's layer-2) with the\n * platform's prominent elevation and no stroke, and its corners are concentric\n * (a 44px capsule around 36px buttons inset by 4px) so the gap around each\n * button is even. */\n.cc-sectionWithBar{padding-bottom:80px}\n.cc-saveBarDock{position:sticky;bottom:0;z-index:2;height:0;pointer-events:none}\n.cc-saveBar{--cc-saveBar-tone:var(--dsw-alias-state-warn-primary,#d97706);position:absolute;left:50%;bottom:20px;box-sizing:border-box;width:max-content;max-width:calc(100% - 24px);align-items:center;gap:10px;display:flex;height:44px;padding:4px 4px 4px 16px;border:0;border-radius:22px;corner-shape:round;background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-prominent,0 12px 32px -8px rgba(0,0,0,.24),0 2px 8px rgba(0,0,0,.08));opacity:0;visibility:hidden;transform:translate(-50%,12px);transition:opacity .16s ease,transform .16s ease,visibility 0s linear .16s}\n.cc-saveBarShown{opacity:1;visibility:visible;transform:translate(-50%,0);pointer-events:auto;transition:opacity .2s ease,transform .24s cubic-bezier(.2,.9,.3,1.1),visibility 0s}\n.cc-saveBar-error{--cc-saveBar-tone:var(--dsw-alias-state-error-primary)}\n.cc-saveBar-success{--cc-saveBar-tone:var(--dsw-alias-state-success-primary,#16a34a);padding-right:18px}\n.cc-saveBarIcon{flex-shrink:0;align-items:center;justify-content:center;display:inline-flex;width:16px;height:16px;color:var(--cc-saveBar-tone)}\n.cc-saveBarPulse{width:8px;height:8px;border-radius:50%;corner-shape:round;background:var(--cc-saveBar-tone)}\n.cc-saveBarText{min-width:0;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}\n.cc-saveBar-error .cc-saveBarText{color:var(--dsw-alias-state-error-primary)}\n.cc-saveBarActions{flex-shrink:0;align-items:center;gap:4px;display:flex;margin-left:8px}\n.cc-saveBarButton{box-sizing:border-box;height:36px;padding:0 16px;border:0;border-radius:18px;corner-shape:round;font:inherit;font-size:14px;line-height:22px;white-space:nowrap;cursor:pointer}\n.cc-saveBarButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-saveBarButton:disabled{cursor:default;opacity:.4}\n.cc-saveBarGhost{background:0 0;color:var(--dsw-alias-label-primary)}\n.cc-saveBarGhost:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.cc-saveBarPrimary{background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-brand-primary));color:var(--dsw-alias-label-primary-foreground,#fff)}\n.cc-saveBarPrimary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover,var(--dsw-alias-button-primary-fill,var(--dsw-alias-brand-primary)))}\n@media (prefers-reduced-motion:reduce){.cc-chevron,.cc-toggle::after,.cc-usageBarFill,.cc-saveBar,.cc-saveBarShown{transition:none}}\n`\n","/**\n * Stylesheet for the Command Code plans & quota panel (the sidebar footer card\n * and the dashboard it opens).\n *\n * Returned as a string, not injected here, so importing this module has no DOM\n * side effect: `./index.ts` installs it once under {@link PANEL_CSS_ID} and\n * removes it when the fiber unwinds.\n *\n * These rules are GLOBAL CSS, so containment is a contract (issue #48): every\n * selector is qualified by one of our own `ccp-` classes except the sidebar\n * anchor below, which carries its justification in place. `tests/styles.test.ts`\n * audits both stylesheets against the real foreign class stems. Colours are\n * harness theme aliases with neutral fallbacks; the `ccp-` prefix keeps these\n * clear of the settings page's `cc-` set.\n *\n * @module dsh-commandcode-provider/client/panel-styles\n */\n\n/**\n * Stylesheet id — the `data-plugin-css` value that makes injection idempotent.\n *\n * The prefix must match this package's real name and the settings-page sheet's\n * (`PAGE_CSS_ID`); the two ids must also stay DISTINCT, since they key two\n * separate style tags and a shared id would make the second injection a no-op.\n */\nexport const PANEL_CSS_ID = '@mars-sea/dsh-commandcode-provider/CommandCodePanel.module.css'\n\n/** The panel stylesheet. */\nexport const PANEL_CSS = `\n/* ------------------------------------------------- sidebar footer card */\n/* The shell renders this list ABOVE the Settings seat, so the card is the\n sidebar's bottom-most content, and supplies no chrome: the entry IS the\n button. Deliberately quiet — a surface beside Settings should read as part of\n the column — with one hover step and a hairline border.\n\n The shell's container is a flex ROW whose occupants each declare a full-width\n line and shrink-proof flex, so as a row it would overflow the column: this\n card cannot shrink and the neighbouring chip would absorb the overflow and\n collapse to nothing. The first rule is that fix, and THE ANCHOR IS\n LOAD-BEARING (issue #48): \"footerActions\" is not a stem this shell owns alone\n — dsh-client-ui-user-questions renders the ask-user-question dialog's button\n row as Mbwy4a_footerActions, and the unanchored rule stacked THAT row's\n side-by-side buttons on every page. \"footArea\" is declared by\n dsh-client-ui-sidebar alone (audited across every client bundle of the\n 0.1.6-alpha.1 engine, and against our own cc-/ccp- names, which collide with\n no engine class). The DESCENDANT combinator survives a wrapper element\n appearing between the two, so a restructured shell degrades to its own row\n rather than losing the fix. tests/styles.test.ts pins both halves. */\n[class*=\"_footArea\"] [class*=\"_footerActions\"]{flex-direction:column}\n.ccp-foot{box-sizing:border-box;flex:0 0 auto;width:100%;min-width:0;font:inherit;color:var(--dsw-alias-label-secondary);text-align:left;cursor:pointer;background:0 0;border:1px solid transparent;border-radius:10px;flex-direction:column;gap:6px;margin:0 0 4px;padding:8px;display:flex}\n.ccp-foot:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}\n.ccp-foot:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}\n.ccp-footTop{align-items:center;gap:8px;min-width:0;display:flex}\n.ccp-footName{white-space:nowrap;text-overflow:ellipsis;color:var(--dsw-alias-label-primary);min-width:0;overflow:hidden;font-size:13px;font-weight:500;line-height:20px}\n/* One block per quota window: a head line carrying the window's own spend and\n limit, then the FULL-WIDTH bar under it. Stacking the two lets the card show\n the dollar figures — the reason this surface exists — without squeezing the\n bar into what is left beside them. Mirrors the dashboard's window block. */\n.ccp-footRow{flex-direction:column;gap:4px;min-width:0;display:flex}\n.ccp-footHead{align-items:baseline;gap:8px;min-width:0;display:flex}\n.ccp-footLabel{flex:1;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}\n.ccp-footAmount{flex:none;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:16px;font-variant-numeric:tabular-nums;white-space:nowrap}\n/* The card's markup must stay PHRASING content — it renders inside the shell's\n own button — so these bars are spans, which makes display:block load-bearing:\n an inline box ignores width outright, so the fill would collapse to 0x0 and\n the bar would show no usage. */\n.ccp-footBar{display:block;background:var(--dsw-alias-bg-layer-2);border-radius:999px;height:5px;overflow:hidden}\n.ccp-footFill{display:block;background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}\n.ccp-footFillWarn{background:var(--dsw-alias-state-error-primary)}\n.ccp-footPct{flex:none;width:34px;color:var(--dsw-alias-label-secondary);text-align:right;font-size:12px;line-height:16px;font-variant-numeric:tabular-nums}\n\n/* The 56px rail: one icon button on the shell's own 36px rail cell, so the\n collapsed column keeps a single 18px glyph like its siblings. */\n.ccp-railButton{box-sizing:border-box;width:36px;height:36px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:1px solid transparent;border-radius:8px;flex:none;justify-content:center;align-items:center;margin:0 0 4px;padding:0;display:inline-flex}\n.ccp-railButton:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}\n.ccp-railButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}\n\n/* The ring glyph, sized entirely by its own width/height attribute, so the\n footer row, the rail button and the dashboard can each ask for their own. */\n.ccp-glyph{flex:none;justify-content:center;align-items:center;display:inline-flex;color:var(--dsw-alias-brand-primary)}\n\n/* ------------------------------------------------------------ dashboard */\n.ccp-main{background:var(--dsw-alias-bg-layer-1);width:100%;height:100%;overflow:auto;display:block}\n.ccp-mainInner{max-width:760px;margin:0 auto;padding:24px 20px 40px;flex-direction:column;gap:14px;display:flex;color:var(--dsw-alias-label-primary)}\n.ccp-header{align-items:center;gap:10px;display:flex;flex-wrap:wrap}\n.ccp-headerText{flex-direction:column;gap:2px;display:flex;min-width:0}\n.ccp-title{margin:0;font-size:18px;font-weight:600;line-height:1.4}\n.ccp-subtitle{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n.ccp-spacer{flex:1}\n.ccp-meta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;font-variant-numeric:tabular-nums}\n/* 关闭图标沿用原语义与按钮尺寸,线性 SVG 随宿主文字颜色变化。 */\n.ccp-close{min-width:28px;justify-content:center;padding-left:0;padding-right:0}\n.ccp-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n\n.ccp-notice{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:12px 14px;flex-direction:column;gap:4px;display:flex}\n.ccp-noticeError{border-color:var(--dsw-alias-state-error-primary)}\n.ccp-noticeTitle{margin:0;font-size:13px;font-weight:600;line-height:1.5}\n.ccp-noticeError .ccp-noticeTitle{color:var(--dsw-alias-state-error-primary)}\n.ccp-noticeHint{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}\n.ccp-noticeDetail{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;word-break:break-word}\n\n.ccp-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:14px;padding:16px 18px;flex-direction:column;gap:16px;display:flex}\n.ccp-cardHead{align-items:center;gap:10px;display:flex;flex-wrap:wrap}\n.ccp-avatar{flex:none;width:28px;height:28px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-module-platform);border-radius:50%;justify-content:center;align-items:center;font-size:12px;font-weight:600;line-height:1;display:inline-flex}\n.ccp-cardIdentity{flex-direction:column;gap:1px;min-width:0;display:flex}\n.ccp-cardTitle{font-size:13px;font-weight:600;line-height:1.4}\n.ccp-cardOwner{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:220px}\n.ccp-block{flex-direction:column;gap:8px;display:flex}\n.ccp-blockTitle{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:600;line-height:1.5;text-transform:uppercase;letter-spacing:.04em}\n.ccp-planRow{align-items:center;gap:8px;display:flex;flex-wrap:wrap}\n.ccp-fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n.ccp-planName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:1.5}\n\n/* The monthly credits and the usage totals share one grid. */\n.ccp-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}\n.ccp-tile{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;min-width:0}\n.ccp-tileLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n.ccp-tileValue{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4;font-variant-numeric:tabular-nums}\n.ccp-tileSub{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n\n/* Quota bars: the monthly bar and the two windows. */\n.ccp-windows{flex-direction:column;gap:14px;display:flex}\n.ccp-window{flex-direction:column;gap:6px;display:flex}\n.ccp-windowHead{align-items:baseline;gap:8px;display:flex}\n.ccp-windowLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:1.5}\n.ccp-windowValue{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;font-variant-numeric:tabular-nums;white-space:nowrap}\n.ccp-windowPct{color:var(--dsw-alias-label-primary);min-width:38px;text-align:right;font-size:12px;font-weight:600;line-height:1.5;font-variant-numeric:tabular-nums}\n.ccp-warnTag{white-space:nowrap;background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary));border-radius:999px;padding:0 8px;font-size:12px;font-weight:600;line-height:17px}\n.ccp-bar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:8px}\n.ccp-barFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}\n.ccp-barFillWarn{background:var(--dsw-alias-state-error-primary)}\n.ccp-windowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n\n.ccp-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:12px;font-weight:600;line-height:17px}\n.ccp-badgeError{background:transparent;color:var(--dsw-alias-state-error-primary)}\n.ccp-badgeWarn{background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary))}\n.ccp-badgeMuted{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:12px;font-weight:500;line-height:17px;max-width:220px;overflow:hidden;text-overflow:ellipsis}\n\n/* Account switch: plain buttons, like the settings page's usage carousel. */\n.ccp-tabs{flex-wrap:wrap;gap:6px;display:flex}\n.ccp-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.ccp-tab:hover:not(.ccp-tabActive){color:var(--dsw-alias-label-primary)}\n.ccp-tabActive{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}\n\n@media (prefers-reduced-motion:reduce){.ccp-footFill,.ccp-barFill{transition:none}}\n/* 分析页使用独立宽度与私有选择器;数字总览和明细不影响原额度面板。 */\n.ccp-mainInnerAnalysis{max-width:1040px}\n.ccp-analysis{font-size:14px;line-height:1.6;min-width:0;color:var(--dsw-alias-label-primary)}\n.ccp-analysisFilters{display:flex;gap:12px;align-items:end;flex-wrap:wrap;margin:10px 0 18px}\n.ccp-analysisField{display:flex;flex-direction:column;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary);min-width:0}\n.ccp-analysisFilters .ccp-analysisField{min-width:136px}\n.ccp-analysisFilters .ccp-analysisScopeField{flex:0 1 180px}\n/* 明确边框盒高度与行高,避免原生下拉、日期输入和按钮按各自外观计算尺寸。 */\n.ccp-analysisInput{box-sizing:border-box;width:100%;min-width:0;height:40px;padding:8px 11px;font:inherit;font-size:14px;line-height:20px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:7px}\n/* 原生选择行为保留;SVG 的位置与文字留白独立控制,点击箭头仍交给下拉框。 */\n.ccp-analysisSelectShell{position:relative;display:block;width:100%;min-width:0}\n.ccp-analysisSelect{appearance:none;-webkit-appearance:none;padding-inline-end:40px;text-overflow:ellipsis;cursor:pointer}\n.ccp-analysisSelectShell > .ccp-analysisChevron{position:absolute;inset-inline-end:12px;top:50%;transform:translateY(-50%) rotate(90deg);pointer-events:none}\n.ccp-analysisSelect:disabled + .ccp-analysisChevron{opacity:.65}\n.ccp-analysisInput::placeholder{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary))}\n.ccp-analysisApply{box-sizing:border-box;height:40px;font:inherit;font-size:14px;font-weight:500;line-height:20px;white-space:nowrap;padding:8px 18px;border:1px solid var(--dsw-alias-label-primary);border-radius:7px;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1);cursor:pointer}\n.ccp-analysisApply:disabled{opacity:.5;cursor:wait}\n.ccp-analysisInput:disabled{opacity:.65}\n.ccp-analysisInput:focus-visible,.ccp-analysisApply:focus-visible,.ccp-analysisTab:focus-visible,.ccp-analysisPanel:focus-visible,.ccp-analysisModelSummary:focus-visible,.ccp-analysisScenarioSummary:focus-visible,.ccp-analysisDisclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}\n/* 模型列表会裁切圆角,内收焦点框以保持第一行和最后一行也清晰可见。 */\n.ccp-analysisModelSummary:focus-visible,.ccp-analysisScenarioSummary:focus-visible,.ccp-analysisAggregate > .ccp-analysisDisclosure:focus-visible{outline-offset:-3px}\n.ccp-analysisScope{display:flex;justify-content:space-between;gap:6px 18px;flex-wrap:wrap;color:var(--dsw-alias-label-secondary);font-size:12px;margin-bottom:12px}\n.ccp-analysisOverview{display:grid;grid-template-columns:1.25fr repeat(3,1fr);padding:22px 0;border-top:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2);font-variant-numeric:tabular-nums}\n.ccp-analysisMetric{display:flex;flex-direction:column;gap:4px;min-width:0}\n.ccp-analysisLabel{font-size:12px;color:var(--dsw-alias-label-secondary);font-weight:400}\n.ccp-analysisValue{font-size:16px;line-height:1.4;font-weight:500;overflow-wrap:anywhere}\n.ccp-analysisSub{display:block;color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:400;overflow-wrap:anywhere}\n.ccp-analysisOverview .ccp-analysisMetric{padding:0 24px;border-left:1px solid var(--dsw-alias-border-l2)}\n.ccp-analysisOverview .ccp-analysisMetric:first-child{padding-left:0;border-left:0}\n.ccp-analysisOverview .ccp-analysisMetric:last-child{padding-right:0}\n.ccp-analysisOverview .ccp-analysisValue{font-size:26px;font-weight:600;letter-spacing:-.025em;margin:3px 0}\n.ccp-analysisNote{font-size:12px;color:var(--dsw-alias-label-secondary);margin:8px 0 0}\n.ccp-analysisMessage{margin:10px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;background:var(--dsw-alias-bg-layer-2);font-size:14px}\n.ccp-analysisWarning{border-left:3px solid var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary))}\n.ccp-analysisError{border-left:3px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}\n.ccp-analysisTabs{display:flex;gap:24px;border-bottom:1px solid var(--dsw-alias-border-l2);margin:24px 0 0}\n.ccp-analysisTab{position:relative;border:0;background:transparent;font:inherit;font-size:14px;color:var(--dsw-alias-label-secondary);padding:10px 0 12px;cursor:pointer}\n.ccp-analysisTab[aria-selected=\"true\"]{color:var(--dsw-alias-label-primary);font-weight:600}\n.ccp-analysisTab[aria-selected=\"true\"]:after{content:\"\";position:absolute;bottom:-1px;left:0;right:0;height:2px;background:var(--dsw-alias-brand-primary);border-radius:2px}\n.ccp-analysisPanel{padding-top:18px;min-width:0}\n.ccp-analysisPanel[hidden]{display:none}\n.ccp-analysisSectionHead{display:flex;align-items:baseline;justify-content:space-between;gap:8px;flex-wrap:wrap;margin-bottom:12px}\n.ccp-analysisHeading{font-size:14px;font-weight:600;margin:0}\n.ccp-analysisSectionHead .ccp-analysisNote{margin:0}\n.ccp-analysisModels{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;overflow:hidden}\n.ccp-analysisModelRow{border-top:1px solid var(--dsw-alias-border-l2)}\n.ccp-analysisModelRow:first-child{border-top:0}\n.ccp-analysisModelSummary,.ccp-analysisScenarioSummary{position:relative;display:grid;grid-template-columns:minmax(180px,1.65fr) repeat(4,minmax(90px,1fr)) 16px;gap:16px;align-items:center;padding:18px 16px;cursor:pointer;list-style:none;font-variant-numeric:tabular-nums}\n.ccp-analysisScenarioSummary{grid-template-columns:minmax(180px,1.65fr) repeat(2,minmax(90px,1fr)) minmax(90px,.8fr) 16px}\n.ccp-analysisModelSummary::-webkit-details-marker,.ccp-analysisScenarioSummary::-webkit-details-marker,.ccp-analysisDisclosure::-webkit-details-marker{display:none}\n.ccp-analysisModelSummary:hover,.ccp-analysisScenarioSummary:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2))}\n.ccp-analysisIdentity{display:flex;flex-direction:column;gap:5px;min-width:0}\n.ccp-analysisModelName{font-size:14px;font-weight:600;overflow-wrap:anywhere}\n.ccp-analysisChevron{flex:none;color:var(--dsw-alias-label-secondary)}\n.ccp-analysisModelRow[open] > .ccp-analysisModelSummary > .ccp-analysisChevron,.ccp-analysisModelRow[open] > .ccp-analysisScenarioSummary > .ccp-analysisChevron,.ccp-analysisAggregate[open] > .ccp-analysisDisclosure > .ccp-analysisChevron,.ccp-analysisRules[open] > .ccp-analysisDisclosure > .ccp-analysisChevron{transform:rotate(90deg)}\n.ccp-analysisDetails{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px;padding:18px 16px 22px;background:var(--dsw-alias-bg-layer-2);border-top:1px solid var(--dsw-alias-border-l2)}\n.ccp-analysisDetailTitle{font-size:12px;font-weight:600;margin:0 0 10px}\n.ccp-analysisFacts{margin:0;display:flex;flex-direction:column;gap:8px}\n.ccp-analysisFact{display:flex;align-items:baseline;justify-content:space-between;gap:12px;min-width:0}\n.ccp-analysisFactValue{font-size:14px;margin:0;text-align:right;font-variant-numeric:tabular-nums;overflow-wrap:anywhere;min-width:0}\n.ccp-analysisFact .ccp-analysisLabel{flex-shrink:0}\n.ccp-analysisAggregate{margin-top:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;overflow:hidden}\n.ccp-analysisDisclosure{display:flex;gap:8px;align-items:center;cursor:pointer;list-style:none;font-size:12px;color:var(--dsw-alias-label-secondary);padding:11px 14px}\n.ccp-analysisMonthly{margin:16px 0 0;display:flex;flex-wrap:wrap;gap:4px 12px;align-items:baseline;font-size:12px;color:var(--dsw-alias-label-secondary)}\n.ccp-analysisMonthlyValue{font-size:14px;font-weight:500;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums}\n.ccp-analysisMonthly .ccp-analysisNote{width:100%;margin:0}\n.ccp-analysisAssumption{font-size:14px;line-height:1.6;color:var(--dsw-alias-label-secondary);margin:0 0 16px}\n.ccp-analysisSearch{max-width:360px;margin-bottom:16px}\n.ccp-analysisCapability{font-size:12px;color:var(--dsw-alias-label-secondary)}\n.ccp-analysisScenarioDetails{grid-template-columns:minmax(0,1fr) minmax(0,2fr)}\n.ccp-analysisScenarioDetails .ccp-analysisFactValue{max-width:75%}\n.ccp-analysisEmpty{font-size:14px;color:var(--dsw-alias-label-secondary);text-align:center;padding:32px 16px;margin:0;border:1px dashed var(--dsw-alias-border-l2);border-radius:8px}\n.ccp-analysisRules{margin-top:22px;border-top:1px solid var(--dsw-alias-border-l2)}\n.ccp-analysisRules .ccp-analysisDisclosure{padding:14px 0}\n.ccp-analysisRulesBody{color:var(--dsw-alias-label-secondary);font-size:14px;padding-bottom:4px}\n.ccp-analysisRulesBody p{margin:0 0 12px}\n@media (max-width:860px){\n.ccp-analysisOverview .ccp-analysisMetric{padding:0 16px}\n.ccp-analysisOverview .ccp-analysisValue{font-size:22px}\n.ccp-analysisModelSummary{grid-template-columns:repeat(4,minmax(0,1fr)) 16px;gap:12px 16px}\n.ccp-analysisScenarioSummary{grid-template-columns:repeat(3,minmax(0,1fr)) 16px;gap:12px 16px}\n.ccp-analysisModelSummary > .ccp-analysisIdentity,.ccp-analysisScenarioSummary > .ccp-analysisIdentity{grid-column:1/-2}\n.ccp-analysisModelSummary > .ccp-analysisChevron{grid-column:5;grid-row:1}\n.ccp-analysisScenarioSummary > .ccp-analysisChevron{grid-column:4;grid-row:1}\n.ccp-analysisDetails{grid-template-columns:repeat(2,minmax(0,1fr))}\n}\n@media (max-width:640px){\n.ccp-mainInnerAnalysis{padding:20px 16px 32px}\n.ccp-analysisFilters{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}\n.ccp-analysisFilters .ccp-analysisField{min-width:0}\n.ccp-analysisApply{grid-column:1/-1}\n.ccp-analysisOverview{grid-template-columns:repeat(2,minmax(0,1fr));gap:20px 0;padding:20px 0}\n.ccp-analysisOverview .ccp-analysisMetric{padding:0 12px}\n.ccp-analysisOverview .ccp-analysisMetric:nth-child(odd){border-left:0;padding-left:0}\n.ccp-analysisOverview .ccp-analysisValue{font-size:22px}\n.ccp-analysisModelSummary,.ccp-analysisScenarioSummary{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;padding:16px}\n.ccp-analysisModelSummary > .ccp-analysisIdentity,.ccp-analysisScenarioSummary > .ccp-analysisIdentity{grid-column:1/-1;padding-right:24px}\n.ccp-analysisModelSummary > .ccp-analysisChevron,.ccp-analysisScenarioSummary > .ccp-analysisChevron{position:absolute;top:19px;right:16px;grid-column:auto;grid-row:auto}\n.ccp-analysisDetails{gap:20px;grid-template-columns:1fr}\n.ccp-analysisFactValue{max-width:65%}\n.ccp-analysisSearch{max-width:none}\n}\n`\n","/** 手动读取历史,旧宿主可降级;查询切换和卸载后不接受过期结果。 */\nimport { parseAnalyticsQuery, parseAnalyticsReport, type AnalyticsQuery, type AnalyticsReport } from '../analytics-wire.ts'\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nexport interface AnalyticsRemote { analytics?(query: AnalyticsQuery): Promise<RemoteResult<AnalyticsReport>> }\nexport interface AnalyticsState { status: 'idle' | 'loading' | 'ready' | 'error'; report?: AnalyticsReport; error?: string }\nexport class AnalyticsController {\n private current: AnalyticsState = { status: 'idle' }\n private listeners = new Set<() => void>()\n private generation = 0\n private disposed = false\n private query: AnalyticsQuery = { mode: 'recent', limit: 20 }\n constructor(private remote: AnalyticsRemote) {}\n state() { return this.current }\n subscribe(listener: () => void) { this.listeners.add(listener); return () => { this.listeners.delete(listener) } }\n dispose() { this.disposed = true; this.generation++; this.listeners.clear() }\n reload() { this.generation++; this.set({ status: 'idle' }) }\n refresh(query = this.query) {\n if (this.disposed) return\n const requested = parseAnalyticsQuery(query)\n this.query = requested\n const generation = ++this.generation\n this.set({ status: 'loading' })\n const call = this.remote.analytics\n if (!call) { this.set({ status: 'error', error: '宿主不支持模型分析,请更新插件' }); return }\n void Promise.resolve().then(() => call(requested)).then(result => {\n if (this.disposed || generation !== this.generation) return\n if (!result.ok) { this.set({ status: 'error', error: result.error.message === '宿主不支持模型分析,请更新插件' ? result.error.message : '模型分析读取失败,请稍后刷新或检查宿主日志' }); return }\n this.set({ status: 'ready', report: parseAnalyticsReport(result.value) })\n }).catch(() => {\n if (!this.disposed && generation === this.generation) this.set({ status: 'error', error: '模型分析读取失败,请稍后刷新或检查宿主日志' })\n })\n }\n private set(state: AnalyticsState) { this.current = state; for (const listener of this.listeners) listener() }\n}\n","/**\n * Browser half of the dsh-commandcode-provider bundle: the \"Command Code\"\n * settings page (`settings.section`, id `commandcode`), the Models-page\n * provider card (`settings.models.provider-card`, key `llm-commandcode`, see\n * `./card.tsx`), the quota/model-analysis panel's `main` cell + gated\n * `sidebar.footer.action` card, and the composer\n * `conversation.composer.dock` cost entry.\n *\n * The API key is written through the credentials domain (the\n * `COMMANDCODE_API_KEY` reference the plugin resolves via\n * `ctx.remote.credentials`), never as a settings value, and every other fact\n * through the `llm-commandcode` namespace — so a saved key or endpoint reaches\n * the very next request and the key literal cannot land in a settings document.\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { createSnapshotStore } from './snapshot-store.ts'\nimport { readableErrorText } from './error-text.ts'\n// Type-only: the client-service augmentations (`slots`/`remote`/`locale` on\n// Context) and the `settings.section` SlotMap entry.\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 { createSettingsScope, type SettingsRemoteNamespace, type SettingsScopeContext } from './settings-scope.ts'\nimport { CommandCodeSettingsController, COMMANDCODE_NS, type SettingsPageState } from './settings.ts'\nimport type { SettingsPageApi } from './settings.ts'\nimport { CommandCodeUsageController, type UsagePageState, type UsageRemote } from './usage.ts'\nimport { CommandCodePricesController, type SessionCostPricesState } from './prices.ts'\nimport { CommandCodeLoginController, type LoginPageState, type LoginRemote } from './login.ts'\nimport { USAGE_REMOTE_CONTRIBUTION, MODELS_REMOTE_CONTRIBUTION, PRICES_REMOTE_CONTRIBUTION } from '../usage-wire.ts'\nimport { LOGIN_REMOTE_CONTRIBUTION } from '../login-wire.ts'\nimport { ENROLLMENT_REMOTE_CONTRIBUTION } from '../enrollment-wire.ts'\nimport { AccountEnrollmentController, type EnrollmentRemote } from './enrollment.ts'\nimport type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { CommandCodeSettingsPage } from './section.tsx'\nimport { CommandCodeProviderCard } from './card.tsx'\nimport { CommandCodePanel, CommandCodeFooterEntry } from './panel-view.tsx'\nimport type { PanelInjected } from './panel-view.tsx'\nimport { CommandCodeSessionCost } from './session-cost-view.tsx'\nimport type { SessionCostInjected } from './session-cost-view.tsx'\nimport { startPanelAutoRefresh } from './panel.ts'\nimport { PAGE_CSS, PAGE_CSS_ID } from './page-styles.ts'\nimport { PANEL_CSS, PANEL_CSS_ID } from './panel-styles.ts'\n// Type-only: pulls in the SlotMap merge for the composer dock\n// (`./session-cost-slots.ts`). The sidebar-foot / center-column merge rides the\n// `./panel-view.tsx` value import above, which imports `./panel-slots.ts`.\nimport type {} from './session-cost-slots.ts'\nimport { zh, en } from './locales.ts'\nimport { PANEL_COPY_EN, PANEL_COPY_ZH, PANEL_LOCALE_NS } from './panel-copy.ts'\nimport { ANALYTICS_REMOTE_CONTRIBUTION } from '../analytics-wire.ts'\nimport { AnalyticsController } from './analytics.ts'\nimport type { AnalyticsQuery } from '../analytics-wire.ts'\n\n\n\n/** Install one stylesheet by id and return a disposer for its owning effect. */\nfunction injectCss(id: string, css: string): () => void {\n if (typeof document === 'undefined') return () => {}\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 = css\n document.head.appendChild(tag)\n return () => tag.remove()\n}\n\n/**\n * Plans & quota panel id. It is the layout's `MainPanelId`: one string shared\n * by the `sidebar.footer.action` card and the `main` slot cell, so the card\n * selects this panel and nothing else. `dsh-client-ui-layout` is not a\n * dependency of this bundle, so its brand is applied at the call site instead\n * of importing the package.\n */\nconst PANEL_ID = 'commandcode-panel'\n\n/**\n * The composer figure's entry id in `conversation.composer.dock`. Its own id,\n * never the shipped `stats` cell's: reusing that id would REPLACE the tokens /\n * cache-hit / throughput readout rather than inject into it, and that readout\n * is the harness's to format.\n */\nconst SESSION_COST_ID = 'commandcode-session-cost'\n\n/**\n * The one shot of the `layout` service this plugin needs, declared\n * structurally: importing the package would make the browser resolve a client\n * module this bundle never calls. Read through the reflective\n * `ctx.get('layout')`, never a bare `ctx.layout` property — `layout` is not in\n * the exported inject list, and cordis throws `cannot get property … without\n * inject` for an undeclared service. (The footer card's own gate below IS a\n * static `ctx.inject(['layout'])`, but it is scoped to that one registration.)\n */\ninterface LayoutSelectionSeam {\n /** `null` shows the Conversation again; a string selects that registered `main` key. */\n selectPanel(id: string | null): void\n}\n\n/**\n * Client plugin body. Gates on `slots`, `locale` and `remote` — never on\n * `settingsScope`, whose wrapper service the 0.1.7 settings rewrite removed\n * (the scope below speaks the `remote.settings` wire directly), because\n * gating on a service 0.1.7 does not provide would park EVERY surface below\n * into silence. `settingsScope` must never reappear in the exported inject\n * list at the bottom of this file.\n */\nexport function apply(ctx: Context): void {\n injectCss(PAGE_CSS_ID, PAGE_CSS)\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; `slots.inject` waits for the declaration, so registration\n // order relative to it does not matter).\n ctx.effect(() => ctx.locale.register('settings.commandcode', { zh, en }), 'dsh-commandcode-provider: page copy')\n\n // The panel's copy is a namespace of its own: the panel is not part of the\n // settings page, but it follows the SAME active language — declaring\n // `PANEL_LOCALE_NS` on both panel registrations is what binds their `t` seat.\n ctx.effect(\n () => ctx.locale.register(PANEL_LOCALE_NS, { zh: PANEL_COPY_ZH, en: PANEL_COPY_EN }),\n 'dsh-commandcode-provider: panel copy',\n )\n\n // Credentials reach the browser as a Typert Remote namespace. This inject is\n // the activation gate for every surface below, so a profile whose Host\n // serves no credentials namespace simply never mounts the page.\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. */\nfunction applyClientSurfaces(\n ctx: Context,\n api: SettingsPageApi,\n): void {\n // This plugin's own binding of the `llm-commandcode` namespace over\n // `remote.settings` (see `./settings-scope.ts`).\n //\n // The namespace object is captured from an INJECT-SCOPED context, never read\n // off `ctx.remote`: `remote.settings` is a Cordis service NESTED under\n // `remote`, and cordis answers a read through a context that does not declare\n // it with `Error: cannot get property \"remote.settings\" without inject` —\n // which lands inside the scope's own `try`/`catch`, so nothing is logged and\n // the page renders read-only with every control disabled (the 0.1.7\n // settings-page report, CHANGELOG 0.11.9; the full incident is in\n // AGENTS.md). The resolver hands the scope the very object the inject\n // resolved, and `refresh()` re-reads once it lands; a profile whose Host\n // serves no settings namespace simply never resolves it, where the page\n // keeps rendering its degraded state instead of crashing.\n let settingsNamespace: SettingsRemoteNamespace | undefined\n const scope = createSettingsScope<Record<string, unknown>>(\n ctx as unknown as SettingsScopeContext,\n COMMANDCODE_NS,\n () => settingsNamespace,\n )\n ctx.effect(() => () => { void scope.dispose() }, 'dsh-commandcode-provider: settings scope')\n ctx.inject(['remote.settings'], (settingsCtx) => {\n settingsNamespace = (settingsCtx.remote as unknown as {\n settings: SettingsRemoteNamespace\n }).settings\n // The first read raced this inject and answered \"not mounted\"; re-read now\n // that the namespace is here (and again whenever it re-mounts).\n scope.refresh()\n settingsCtx.effect(() => () => {\n settingsNamespace = undefined\n }, 'dsh-commandcode-provider: settings namespace')\n })\n // The model catalog for the settings page's model editors is served by the\n // `commandcode/models` Remote mounted below, which happens after this\n // controller is constructed — so it reads the catalog through this mutable\n // seam. Unset until the mount lands; the controller degrades to the\n // 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 )\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 () => {\n const remote = ctx.remote as unknown as {\n $on(\n event: 'credentials/reference-updated' | 'credentials/record-updated',\n listener: (ref: string) => void,\n ): () => void\n }\n const unregisterReference = remote.$on('credentials/reference-updated', () => {\n controller.refreshCredentials()\n })\n const unregisterRecord = remote.$on('credentials/record-updated', () => {\n controller.refreshCredentials()\n })\n return () => {\n unregisterReference()\n unregisterRecord()\n }\n },\n 'dsh-commandcode-provider: credential invalidations',\n )\n\n // One mount carries every endpoint this plugin serves (report, catalog, price\n // table, login), keeping the Client's bookkeeping 1:1 with the Host's single\n // registry registration. Cordis only serves services a fiber declares in\n // `inject`, and the namespace service exists only after the mount — so the\n // `remote.commandcode` inject is registered DYNAMICALLY once the mount\n // lands; a static one would deadlock the plugin, the mounter waiting for its\n // own mount. A Host half that predates the Remote fails the calls instead,\n // and the surfaces render their error branches.\n let usageNamespace: (typeof ctx.remote)['commandcode'] | undefined\n let usageMountError: string | undefined\n // `pricesController` and `refreshUsage` are declared here and assigned below,\n // because the mount effect's inject callback calls them while cordis runs it\n // synchronously — before their own `const` would be initialized. A read in\n // that temporal dead zone THROWS, which `?.` would not save.\n let pricesController: CommandCodePricesController | undefined\n let refreshUsage: (() => void) | undefined\n let analyticsController: AnalyticsController | undefined\n const contribution: TypertRemoteContribution = {\n package: USAGE_REMOTE_CONTRIBUTION.package,\n descriptors: [\n ...USAGE_REMOTE_CONTRIBUTION.descriptors,\n ...MODELS_REMOTE_CONTRIBUTION.descriptors,\n ...PRICES_REMOTE_CONTRIBUTION.descriptors,\n ...ANALYTICS_REMOTE_CONTRIBUTION.descriptors,\n ...LOGIN_REMOTE_CONTRIBUTION.descriptors,\n ...ENROLLMENT_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 model editors,\n // and the price table the composer's cost readout needs — `ensure()` is\n // idempotent, so asking earlier could only fail (the namespace did not\n // exist yet).\n controller.refreshCatalog()\n pricesController?.reload()\n analyticsController?.reload()\n // ...and the usage report. A surface can (and on a boot with the quota\n // card on, always does) ask for it BEFORE this mount lands: the answer\n // then is the synthetic \"remote is not mounted\" failure, which the\n // controller stores as `status: 'error'` — and its `shouldRefresh` only\n // fires from `idle`, so nothing would ever retry it (`usage.ts`). The\n // namespace is live here, so re-read now and replace that stale answer.\n refreshUsage?.()\n namespaceCtx.effect(() => () => {\n usageNamespace = undefined\n analyticsController?.reload()\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 = readableErrorText(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 prices: async () => {\n const namespace = usageNamespace\n if (namespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode/prices remote is not mounted' } }\n }\n const call = namespace.prices\n // A Host half older than the price table mounts no such descriptor, so\n // the namespace member is genuinely missing. Report it as a permanent\n // failure the readout understands rather than throwing.\n if (typeof call !== 'function') {\n return { ok: false, error: { message: 'the Host serves no commandcode/prices endpoint', permanent: true } }\n }\n return call.call(namespace)\n },\n }\n modelsRemote = () => usageRemote.models()\n const usageController = new CommandCodeUsageController(usageRemote)\n refreshUsage = () => void usageController.refresh()\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 composer's session-cost readout prices from a static table, so its\n // controller is a one-shot cache rather than a poll.\n pricesController = new CommandCodePricesController(usageRemote)\n ctx.effect(() => () => pricesController?.dispose(), 'dsh-commandcode-provider: price table')\n const pricesStore = createSnapshotStore<SessionCostPricesState>(pricesController.state())\n pricesController.subscribe(() => pricesStore.set(pricesController.state()))\n\n analyticsController = new AnalyticsController({ analytics: async query => {\n const namespace = usageNamespace\n if (typeof namespace?.analytics !== 'function') return { ok: false, error: { message: '宿主不支持模型分析,请更新插件' } }\n return namespace.analytics(query)\n } })\n const analyticsStore = createSnapshotStore(analyticsController.state())\n analyticsController.subscribe(() => analyticsStore.set(analyticsController!.state()))\n ctx.effect(() => () => analyticsController?.dispose(), 'commandcode analytics controller')\n const panelMode = createSnapshotStore<'quota' | 'analysis'>('quota')\n const openAnalytics = () => {\n panelMode.set('analysis')\n const layout = ctx.get('layout') as LayoutSelectionSeam | undefined\n layout?.selectPanel(PANEL_ID)\n }\n\n // The login panel: same namespace, three endpoints. The key NEVER crosses to\n // 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 (targetRef?: string) => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginBegin(targetRef)\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, so 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 refreshUsageOn = (ok: boolean): boolean => {\n const outcome = controller.state().accountResult\n if (ok || outcome?.config === 'confirmed' || outcome?.credential === 'confirmed') void usageController.refresh()\n return ok\n }\n const injected = () => ({\n createEnrollment: () => new AccountEnrollmentController(() => {\n if (!usageNamespace?.enrollmentBegin) throw new Error('宿主不支持账号开通,请更新插件')\n return usageNamespace as EnrollmentRemote\n }, () => { scope.refresh(); controller.refreshCredentials(); void usageController.refresh() }),\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 // 部分完成也可能改变凭据或连接配置,用本次确认结果刷新用量。\n save: () => void controller.save().then(outcome => {\n if (outcome?.config === 'confirmed' || outcome?.credential === 'confirmed') void usageController.refresh()\n }),\n discard: () => controller.discard(),\n refreshCredentials: () => void controller.refreshCredentials(),\n refreshUsage: () => void usageController.refresh(),\n ...(typeof (ctx.get('layout') as LayoutSelectionSeam | undefined)?.selectPanel === 'function' ? { openAnalytics } : {}),\n beginLogin: (targetRef?: string) => void loginController.begin(targetRef),\n cancelLogin: () => void loginController.cancel(),\n // Account operations commit immediately. The ones that change which keys\n // exist refetch the usage report so the account rows follow.\n renameAccount: (ref: string, label: string) => controller.renameAccount(ref, label),\n removeAccount: (ref: string) => controller.removeAccount(ref).then((ok) => {\n // 配置可能已移除、凭据清理仍失败;用量页也应立即跟随新的账户列表。\n if (ok || !controller.state().accounts.some((account) => account.ref === ref)) void usageController.refresh()\n return ok\n }),\n retryCredentialCleanup: (ref: string) => controller.retryCredentialCleanup(ref).then(refreshUsageOn),\n setAccountKey: (target: string, key: string) => controller.setAccountKey(target, key).then(refreshUsageOn),\n clearAccountKey: (target: string) => controller.clearAccountKey(target).then(refreshUsageOn),\n setActiveAccount: (id: string) => controller.setActiveAccount(id).then(refreshUsageOn),\n setAccountModels: (target: string, ids: string[]) => controller.setAccountModels(target, ids),\n editVisibleModels: (ids: string[]) => controller.editVisibleModels(ids),\n clearVisibleModels: () => controller.clearVisibleModels(),\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: a keyed slot the Models section dispatches\n // with `entryKey = settingsNs` on every provider row of an adapter family, so\n // the panel mounts beside the official editor on every Command Code row —\n // including the first-run setup posture, exactly where a user without a key\n // lands. While the official 编辑 toggle is open, the card hides the official\n // editor shell (for this namespace `layoutOf` returns \"unknown\", so that shell\n // carries only a config hint over a disabled apply) and shows the real\n // controls; see card.tsx. The registration carries its own inject face\n // because the declaring entry is ui-settings-models', not ours; the `t` seat\n // comes from the registration's own `locale` namespace.\n //\n // On a build without this slot the declaration never exists and `slots.inject`\n // never fires — the registration silently does not happen. Do not \"harden\"\n // that into an error.\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(outcome => {\n if (outcome?.config === 'confirmed' || outcome?.credential === 'confirmed') void usageController.refresh()\n }),\n discard: () => controller.discard(),\n refreshCredentials: () => void controller.refreshCredentials(),\n beginLogin: () => void loginController.begin(),\n cancelLogin: () => void loginController.cancel(),\n }),\n }, CommandCodeProviderCard))\n\n // The plans & quota panel: a footer card pinned at the bottom of the sidebar,\n // on top of the Settings seat, that opens a dashboard in the center column.\n //\n // Two registrations, ONE navigation entry: `sidebar.footer.action` is the\n // list the sidebar shell renders in its foot area directly above the Settings\n // seat (`footArea` = `footerActions` then `settingsArea`), which is what puts\n // this card at the bottom of the column rather than at the top with the\n // global panel icons of `sidebar.panellist`. The layout's keyed `main` slot\n // holds the panel the card opens — `selectPanel(id)` resolves the id against\n // that registry and throws when no cell occupies it, so BOTH registrations\n // are required, and BOTH need the `inject` face below (an entry without one\n // receives none of the panel's data; see the `hooks` → `useX` rule in\n // panel-view.tsx).\n //\n // Unlike a `sidebar.panellist` row, the shell renders NO chrome around a\n // footer action: our component IS the button, it owns the label (so a title\n // carrying live quota needs no re-registration — that dance exists only\n // because the shell caches a panellist entry's label), and it selects the\n // panel itself through the `open` action below.\n //\n // Both registrations declare the panel's own `locale` namespace\n // (`panel.commandcode`, registered in `apply` above): that is what binds the\n // `t` seat the components feed into `buildPanelView`, so the panel follows\n // the harness's active language and a switch re-renders it.\n //\n // The footer card is gated on the `layout` SERVICE (below), not only on its\n // slot: a profile whose `main` declaration exists but whose layout never\n // mounted would otherwise register a card that renders and does nothing —\n // a dead button. The dashboard cell needs no such gate; registering against\n // a declaration that never arrives is a no-op by construction.\n //\n // Shape notes:\n // * The stylesheet gets its own `ctx.effect` rather than riding an `inject`\n // callback's return value, so the tag's lifetime is the plugin fiber's and\n // is unaffected by a slot declaration collapsing and re-declaring.\n // * Each registration is guarded so a failure in one surface cannot abort\n // `applyClientSurfaces` and take the OTHER surfaces down with it —\n // `slots.inject` rethrows a callback failure synchronously once the\n // declaration exists. The renderer contains a *render* crash by abdicating\n // the entry with no visible error, so a failure that leaves nothing on\n // screen must at least be loud in the console.\n const panelFace = (): PanelInjected => ({\n hooks: { commandCodeUsage: usageStore, commandCodeSettings: store, commandCodeAnalytics: analyticsStore, commandCodePanelMode: panelMode },\n selectPanelMode: (mode) => panelMode.set(mode),\n refreshAnalytics: (query?: AnalyticsQuery) => analyticsController?.refresh(query),\n refresh: () => { pricesController?.ensure(); void usageController.refresh() },\n // The Host resolves every credential source, including CLI auth and\n // literals. A browser credential-reference lookup cannot determine\n // availability.\n startAutoRefresh: () => startPanelAutoRefresh(usageController, () => true),\n // `layout` is read reflectively AT CLICK TIME, never captured at setup:\n // ui-layout is not a dependency of this bundle (its types are not imported\n // and its client module is never resolved), and it is not in the exported\n // inject list. The footer registration below is gated on the same seam, so\n // by the time this runs the method exists; the guard stays as the last line\n // of defence against a layout that renames it.\n open: () => {\n panelMode.set('quota')\n const layout = ctx.get('layout') as LayoutSelectionSeam | undefined\n layout?.selectPanel(PANEL_ID)\n },\n // The dashboard's way out (issue #41). It occupies the center column in\n // place of the Conversation, and `open()` above is the ONLY other panel\n // selection this plugin makes — so without an exit the panel is a one-way\n // door: clicking the sidebar card just re-selects it. `selectPanel(null)`\n // is layout's \"show the Conversation\" selection and leaves the current\n // Session untouched.\n close: () => {\n const layout = ctx.get('layout') as LayoutSelectionSeam | undefined\n layout?.selectPanel(null)\n },\n })\n\n ctx.effect(() => injectCss(PANEL_CSS_ID, PANEL_CSS), 'dsh-commandcode-provider: panel styles')\n\n try {\n ctx.slots.inject('main', () => ctx.slots.register(\n { name: 'main', key: PANEL_ID, locale: PANEL_LOCALE_NS, inject: panelFace },\n CommandCodePanel,\n ))\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] could not register the plans & quota panel:', error)\n }\n\n // The footer card is registered only where the layout can actually open the\n // panel behind it: `ctx.inject(['layout'], …)` runs its body when that service\n // is live and re-runs it if the service is replaced, mirroring how the Remote\n // namespace is mounted — so a profile without ui-layout (the TUI, a headless\n // client) never registers the card at all.\n ctx.inject(['layout'], (layoutCtx) => {\n try {\n layoutCtx.slots.inject('sidebar.footer.action', () => layoutCtx.slots.register(\n // `order` is the only control over position inside a list slot, and the\n // renderer sorts ascending. ui-cordis's footer chip registers at the\n // default 0, so 1 sorts after it — but any sibling passing an order ≥ 1\n // lands between this card and Settings, so \"directly above Settings\" is\n // a preference, not a guarantee.\n { name: 'sidebar.footer.action', id: PANEL_ID, order: 1, locale: PANEL_LOCALE_NS, inject: panelFace },\n CommandCodeFooterEntry,\n ))\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] could not register the sidebar footer card:', error)\n }\n })\n\n // The composer's session-cost figure: an entry in the dock below the input\n // that renders NO surface of its own. The cost is injected into the harness's\n // own token-usage UI — the amount as the last item of the shipped pill's text\n // run, the breakdown as rows inside the usage dialog that pill opens (see\n // `./session-cost-display.ts`).\n //\n // The entry exists for its SEATS, not for a surface: `useProjection` is a\n // standard prop the composer hands every dock occupant, so this registration\n // is the only way to read the session's token accounting. The token buckets\n // and the model selection arrive from the composer itself as standard dock\n // props, so the face carries only the price-table hook.\n //\n // No `locale` namespace and no `t` seat: the figure is English by\n // construction, from `./session-cost.ts`.\n const sessionCostFace = (): SessionCostInjected => ({\n hooks: { commandCodePrices: pricesStore },\n })\n\n try {\n ctx.slots.inject('conversation.composer.dock', () => ctx.slots.register(\n // No `order`: the entry renders nothing, so its position among the dock's\n // rows cannot matter — the sort only ever decides what a reader sees.\n { name: 'conversation.composer.dock', id: SESSION_COST_ID, inject: sessionCostFace },\n CommandCodeSessionCost,\n ))\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] could not register the composer session-cost readout:', error)\n }\n}\n\nexport const inject: readonly string[] = [\n 'slots',\n 'locale',\n 'remote',\n]\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["record","numberField","booleanField","IDLE","record","stringField","reject","pkg.version","(pkg as { repository?: unknown }).repository","useState","useMemo","Menu","Button","useSyncExternalStore","useCallback","useRef","HIDDEN_STYLE","useState","useRef","money","count","useState","useId","useState","Button","useRef"],"sources":["../src/client/snapshot-store.ts","../src/client/error-text.ts","../src/client/settings-scope.ts","../src/timeout-limits.ts","../src/model-visibility.ts","../src/client/settings-write.ts","../src/client/settings.ts","../src/display-format.ts","../src/client/usage.ts","../src/client/prices.ts","../src/client/login-page.ts","../src/client/login.ts","../src/wire-shared.ts","../src/usage-wire.ts","../src/login-wire.ts","../src/enrollment-wire.ts","../src/client/enrollment.ts","../src/client/locales.ts","../src/plan-tiers.ts","../src/client/model-select.ts","../package.json","../src/client/version.ts","../src/client/update.ts","../src/client/section.tsx","../src/client/login-row.tsx","../src/client/card.tsx","../src/client/analytics-copy.ts","../src/client/panel-copy.ts","../src/client/panel.ts","../src/analytics-wire.ts","../src/client/analytics-view.tsx","../src/client/panel-view.tsx","../src/cost-facts.ts","../src/client/session-cost.ts","../src/client/session-cost-display.ts","../src/client/session-cost-view.tsx","../src/client/page-styles.ts","../src/client/panel-styles.ts","../src/client/analytics.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, and small enough to stay that way: the harness's\n * `@deepseek-ai/dsh-client-store` is a seeded platform module, but pulling it in\n * would add a fourth `require()` target (and a client-only peer) to the bundle\n * for the ~30 lines used here, and its `set()` carries engine semantics\n * (dev-mode deep freeze, forced replacement) these callers do not want.\n */\n\n/** 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 * Turn a caught value into readable text for the settings page's error UI.\n *\n * @module dsh-commandcode-provider/client/error-text\n */\n\n/**\n * `error instanceof Error ? error.message : String(error)` degrades to the\n * literal string `[object Object]` for a plain object with no `Error`\n * prototype — which is exactly what a Remote call across the webview/host\n * boundary can hand back: `dsh-typert-protocol` serializes a rejection for\n * the wire, and a structurally-cloned value loses its prototype chain even\n * when the host threw a real `Error` (issue #74). Reading a `message` string\n * off the plain object first recovers the original text in that case; only a\n * value with neither an `Error` prototype nor a usable `message` field falls\n * through to a JSON dump.\n */\nexport function readableErrorText(error: unknown): string {\n if (error instanceof Error) return error.message\n if (typeof error === 'string') return error\n if (error !== null && typeof error === 'object') {\n const message = (error as { message?: unknown }).message\n if (typeof message === 'string' && message !== '') return message\n try {\n return JSON.stringify(error)\n } catch {\n return Object.prototype.toString.call(error)\n }\n }\n return String(error)\n}\n","/**\n * Browser settings scope over the `remote.settings` Typert namespace.\n *\n * The harness's own `settingsScope` client wrapper was REMOVED by the 0.1.7\n * settings rewrite and has no replacement, so this module IS the client half:\n * it speaks the `describe()` / `mutate(namespace, ops, revision)` wire directly\n * and implements the `SettingsScope<T>` face the settings-page controller\n * consumes. `view.writable` is the Host's own authorization fact — the client\n * never infers write permission from localhost, URL shape or origin.\n *\n * **Capture the namespace from an inject-scoped context, never read it off\n * `ctx.remote`.** React-free so `tests/settings-scope.test.ts` can drive the\n * lifecycle over a fake remote.\n *\n * @module dsh-commandcode-provider/client/settings-scope\n */\n\nimport type { SettingsScope, SettingsScopeSnapshot } from './settings.ts'\nimport { createSnapshotStore, type SnapshotStore } from './snapshot-store.ts'\nimport { readableErrorText } from './error-text.ts'\n\n/** Result envelope of one current Typert Remote call. */\ntype Envelope<T> = { ok: true; value: T } | { ok: false; error?: { message?: string } | undefined }\n\n/** One path-addressed form edit — the `SettingsPathOp` wire shape. */\nexport interface SettingsPathOp {\n op: 'set' | 'unset'\n path: readonly string[]\n value?: unknown\n}\n\n/** 本地确认结果,不改宿主远端载体;恢复快照不能冒充本次写入成功。 */\nexport type SettingsMutationResult = 'accepted' | 'conflict' | 'failed' | 'cancelled'\n\n/** One entry's row inside a `settings.describe()` view — `SettingsNamespaceView`. */\ninterface SettingsNamespaceRow {\n ns?: unknown\n value?: unknown\n base?: unknown\n user?: unknown\n revision?: unknown\n}\n\n/** The `settings.describe()` view: the directory plus the Host's write posture. */\ninterface SettingsView {\n namespaces?: SettingsNamespaceRow[] | undefined\n writable?: boolean | undefined\n}\n\n/** The `remote.settings` namespace this scope calls. Structural: never imported. */\nexport interface SettingsRemoteNamespace {\n describe(): Promise<Envelope<SettingsView>>\n /** A write answers with the fresh ROW for its namespace, not the directory. */\n mutate(\n namespace: string,\n ops: readonly SettingsPathOp[],\n revision?: number,\n ): Promise<Envelope<SettingsNamespaceRow>>\n}\n\n/**\n * Reads the `remote.settings` namespace object, or `undefined` while it is not\n * mounted.\n *\n * This is a SEAM rather than a property on {@link SettingsScopeContext}\n * because the namespace has to be captured inside a context that declares it\n * (`ctx.inject(['remote.settings'], (settingsCtx) => …)`). Reading it off our\n * own `ctx.remote` throws `cannot get property \"remote.settings\" without\n * inject` inside this module's `try`/`catch` — silently, with no describe ever\n * sent and the scope stuck on its initial `writable: false` snapshot. Do not\n * \"simplify\" this seam away (AGENTS.md has the full incident).\n */\nexport type SettingsRemoteResolver = () => SettingsRemoteNamespace | undefined\n\n/**\n * The client `Context` slice this module consumes, typed structurally so the\n * browser bundle never imports a version-specific module value and node tests\n * can hand in a plain object. Only `remote` itself (a declared service) is read\n * here — never `remote.<namespace>`, which requires its own inject.\n */\nexport interface SettingsScopeContext {\n remote: {\n $on?: ((event: string, listener: () => void) => (() => void) | undefined) | undefined\n }\n /** Connection lifecycle; older clients and tests may omit it. */\n on?: ((event: string, listener: () => void) => unknown) | undefined\n}\n\n/** Mirror snapshot: one in-flight-or-idle describe read and its held view. */\ninterface MirrorState {\n status: 'idle' | 'loading' | 'ready'\n view: SettingsView | null\n error: string | null\n}\n\n/**\n * Backoff before re-reading a directory whose FIRST read failed, in millis.\n *\n * Only a failure with NOTHING held retries. With no view the scope keeps its\n * initial `{ status: 'loading', writable: false }` snapshot and the settings\n * page renders fully disabled, while the forwarded invalidation signals need a\n * live Host to fire and the namespace only re-mounts on a reload. A failure\n * with a held view retries nothing — the page already shows the last good\n * document (`tests/settings-scope.test.ts` pins both).\n */\nexport const SETTINGS_DESCRIBE_RETRY_MS: readonly number[] = [1000, 2000, 4000]\n\n/** Timer seam for the bounded describe retry; tests drive it without waiting. */\nexport interface SettingsRetryTimer {\n set(callback: () => void, ms: number): unknown\n clear(handle: unknown): void\n}\n\n/** The production timer: a browser/node timeout, no polling. */\nconst REAL_SETTINGS_TIMER: SettingsRetryTimer = {\n set(callback, ms) {\n const handle = setTimeout(callback, ms)\n ;(handle as { unref?: () => void }).unref?.()\n return handle\n },\n clear(handle) { clearTimeout(handle as ReturnType<typeof setTimeout>) },\n}\n\n/** Shallow equality over the snapshot fields, so an unchanged derive never churns subscribers. */\nfunction sameSnapshot(a: SettingsScopeSnapshot<never>, b: SettingsScopeSnapshot<never>): boolean {\n return a.status === b.status\n && Object.is(a.value, b.value)\n && Object.is(a.base, b.base)\n && Object.is(a.user, b.user)\n && Object.is(a.revision, b.revision)\n && a.writable === b.writable\n && a.mode === b.mode\n}\n\n/** Accept a decoded row value only when it is the object a settings section is. */\nfunction decodeRow(value: unknown): Record<string, unknown> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n return value as Record<string, unknown>\n}\n\n/**\n * One shared mirror of the Host `settings.describe()` view.\n *\n * The run loop is the harness's own: serialize behind `inFlight`, fold a\n * concurrent invalidation into exactly one rerun, and hold the previous view\n * across a failed read (status stays `ready` with an `error`, or returns to\n * `idle` when nothing was ever held).\n */\nclass SettingsDescribeMirror {\n private readonly store: SnapshotStore<MirrorState>\n private inFlight: Promise<void> | undefined\n private rerun = false\n private generation = 0\n /** Pending retry handle and how many of {@link SETTINGS_DESCRIBE_RETRY_MS} are spent. */\n private retryHandle: unknown\n private retries = 0\n private disposed = false\n\n constructor(\n private readonly resolveRemote: SettingsRemoteResolver,\n private readonly timer: SettingsRetryTimer = REAL_SETTINGS_TIMER,\n ) {\n this.store = createSnapshotStore<MirrorState>({\n status: 'idle',\n view: null,\n error: null,\n })\n }\n\n getSnapshot(): MirrorState {\n return this.store.getSnapshot()\n }\n\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** The cheap idempotent entry: kick a first read. */\n ensure(): void {\n void this.load()\n }\n\n /**\n * Refresh from the Host. A call during an in-flight read marks one rerun\n * after it settles instead of racing a second wire read.\n * @returns settlement after this call's freshness is reflected.\n */\n load(): Promise<void> {\n if (this.disposed) return Promise.resolve()\n // A live read supersedes a scheduled retry: the retry exists only to\n // revive a mirror that nothing else would ever re-read.\n this.clearRetry()\n if (this.inFlight !== undefined) {\n this.rerun = true\n return this.inFlight\n }\n const run = Promise.resolve().then(() => this.run())\n this.inFlight = run\n return run\n }\n\n /**\n * Fold one write answer's namespace ROW into the held view without a wire\n * read, and invalidate any read still in flight: a read begun before the\n * write committed must not publish the pre-write document over it. With no\n * held document the answer is not published as a partial document — the\n * next read (or the failed-write recovery) picks it up.\n * @param row - The namespace view a settings write answered with.\n */\n acceptView(row: SettingsNamespaceRow): void {\n const before = this.store.getSnapshot()\n this.generation += 1\n if (this.inFlight !== undefined) this.rerun = true\n if (before.view === null) return\n const held = before.view\n const namespaces = held.namespaces?.some((candidate) => candidate.ns === row.ns)\n ? held.namespaces.map((candidate) => (candidate.ns === row.ns ? row : candidate))\n : [...(held.namespaces ?? []), row]\n this.store.set({ ...before, view: { ...held, namespaces } })\n }\n\n private async run(): Promise<void> {\n try {\n for (;;) {\n const before = this.store.getSnapshot()\n if (before.status === 'idle') this.store.set({ ...before, status: 'loading' })\n this.rerun = false\n const generation = ++this.generation\n let outcome: { view: SettingsView } | { failure: string }\n try {\n const namespace = this.resolveRemote()\n if (namespace === undefined) throw new Error('the settings remote namespace is not mounted')\n const response = await namespace.describe()\n if (response.ok) {\n const value: unknown = response.value\n // The mirror holds a VIEW or nothing: an empty/malformed answer\n // must not be published as `ready` with an undefined view, or the\n // derive below would read through it. (Upstream guards the same way\n // by testing the held view for `undefined`.)\n outcome = typeof value === 'object' && value !== null\n ? { view: value as SettingsView }\n : { failure: 'settings describe answered no view' }\n } else {\n outcome = { failure: response.error?.message ?? 'settings describe failed' }\n }\n } catch (error: unknown) {\n outcome = { failure: readableErrorText(error) }\n }\n if (generation !== this.generation) continue\n if ('view' in outcome) {\n this.retries = 0\n this.store.set({ status: 'ready', view: outcome.view, error: null })\n } else {\n const held = this.store.getSnapshot()\n this.store.set({\n status: held.view === null ? 'idle' : 'ready',\n view: held.view,\n error: outcome.failure,\n })\n // Nothing held → nothing can heal this but a retry (see\n // SETTINGS_DESCRIBE_RETRY_MS); a held view needs none.\n if (held.view === null) this.scheduleRetry()\n }\n if (!this.rerun) break\n }\n } finally {\n this.inFlight = undefined\n }\n }\n\n /**\n * Schedule the next retry of a failed FIRST read ({@link SETTINGS_DESCRIBE_RETRY_MS}).\n * Bounded: once the ladder is spent the scope keeps its degraded snapshot,\n * exactly as before, until an invalidation or a namespace re-mount arrives.\n */\n private scheduleRetry(): void {\n if (this.disposed || this.retries >= SETTINGS_DESCRIBE_RETRY_MS.length) return\n const delay = SETTINGS_DESCRIBE_RETRY_MS[this.retries]!\n this.retries += 1\n this.retryHandle = this.timer.set(() => {\n this.retryHandle = undefined\n void this.load()\n }, delay)\n }\n\n /** Cancel a pending retry (a live read is starting, or the scope is going away). */\n private clearRetry(): void {\n if (this.retryHandle !== undefined) this.timer.clear(this.retryHandle)\n this.retryHandle = undefined\n }\n\n /** Stop the mirror: no further reads, and no retry may fire after disposal. */\n dispose(): void {\n this.disposed = true\n this.clearRetry()\n }\n}\n\n/**\n * One namespace's derived scope over the shared mirror, plus its serialized\n * Host writes — the face `CommandCodeSettingsController` consumes\n * (`getSnapshot` / `subscribe` / `set` / `unset`).\n */\nclass RemoteSettingsScope<T> implements SettingsScope<T> {\n private readonly resolveRemote: SettingsRemoteResolver\n private readonly store: SnapshotStore<SettingsScopeSnapshot<T>>\n private readonly mirror: SettingsDescribeMirror\n private readonly namespace: string\n private tail: Promise<void> = Promise.resolve()\n private writeGeneration = 0\n private disposed = false\n private unsubscribe: (() => void) | undefined\n /** Revision answered by a superseded write still ahead of the mirror. */\n private pendingRevision: number | undefined\n\n constructor(\n resolveRemote: SettingsRemoteResolver,\n mirror: SettingsDescribeMirror,\n namespace: string,\n ) {\n this.resolveRemote = resolveRemote\n this.mirror = mirror\n this.namespace = namespace\n this.store = createSnapshotStore<SettingsScopeSnapshot<T>>({\n status: 'loading',\n value: undefined,\n base: undefined,\n user: undefined,\n revision: undefined,\n writable: false,\n mode: 'host',\n })\n this.unsubscribe = mirror.subscribe(() => { this.derive() })\n this.derive()\n }\n\n getSnapshot(): SettingsScopeSnapshot<T> {\n return this.store.getSnapshot()\n }\n\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** Queue one field write (the single-path `set` op form). */\n async set(field: string, value: unknown): Promise<void> {\n await this.mutate([{ op: 'set', path: [field], value }])\n }\n\n /** Queue one field clear (the single-path `unset` op form). */\n async unset(field: string): Promise<void> {\n await this.mutate([{ op: 'unset', path: [field] }])\n }\n\n /**\n * Queue one atomic namespace mutation behind the single-flight fence.\n * A rejected write (e.g. `SETTINGS_CONFLICT`) re-reads the Host so the\n * snapshot reports what actually landed; an accepted one folds its answer\n * in directly — unless a newer write already superseded it, in which case\n * that answer's revision becomes the next write's fence.\n */\n mutate(ops: readonly SettingsPathOp[], expectedRevision?: number): Promise<SettingsMutationResult> {\n const ownedOps = structuredClone(ops)\n const generation = ++this.writeGeneration\n return this.enqueue(async () => {\n const revision = expectedRevision ?? this.pendingRevision ?? this.getSnapshot().revision\n const response = await this.mutateRemote(ownedOps, revision)\n if (!response.ok) {\n await this.recover(generation)\n return response.error?.message?.includes('SETTINGS_CONFLICT') ? 'conflict' : 'failed'\n }\n const row = response.value\n if (row?.ns !== this.namespace || decodeRow(row.value) === undefined || typeof row.revision !== 'number') {\n await this.recover(generation)\n return 'failed'\n }\n if (this.disposed) return 'accepted'\n if (generation === this.writeGeneration) {\n this.pendingRevision = undefined\n this.mirror.acceptView(row)\n } else {\n this.pendingRevision = typeof row.revision === 'number' ? row.revision : undefined\n }\n return 'accepted'\n })\n }\n\n private async mutateRemote(\n ops: readonly SettingsPathOp[],\n revision: number | undefined,\n ): Promise<Envelope<SettingsNamespaceRow>> {\n try {\n const namespace = this.resolveRemote()\n if (namespace === undefined) {\n return { ok: false, error: { message: 'the settings remote namespace is not mounted' } }\n }\n return await namespace.mutate(this.namespace, ops, revision)\n } catch (error: unknown) {\n return { ok: false, error: { message: readableErrorText(error) } }\n }\n }\n\n /** Reload Host state for the latest failed write; superseded failures leave recovery to it. */\n private async recover(generation: number): Promise<void> {\n if (this.disposed || generation !== this.writeGeneration) return\n this.pendingRevision = undefined\n await this.mirror.load()\n }\n\n /** Derive this namespace's snapshot from the mirror's held view. */\n private derive(): void {\n if (this.disposed) return\n const mirrored = this.mirror.getSnapshot()\n // `undefined` as well as `null`: the held view is only ever the wire's\n // answer, and a malformed one never reaches the store (see `run`).\n if (mirrored.view === null || mirrored.view === undefined) return\n const writable = mirrored.view.writable === true\n const row = mirrored.view.namespaces?.find((candidate) => candidate.ns === this.namespace)\n if (row === undefined) {\n this.publish({ status: 'unavailable', writable })\n return\n }\n const decoded = decodeRow(row.value)\n if (decoded === undefined) return\n this.publish({\n status: 'ready',\n writable,\n value: decoded as T,\n base: row.base,\n user: row.user,\n revision: typeof row.revision === 'number' ? row.revision : undefined,\n })\n }\n\n /** Publish `next` over the current snapshot, skipping the write when nothing changed. */\n private publish(next: {\n status: SettingsScopeSnapshot<T>['status']\n writable: boolean\n value?: T\n base?: unknown\n user?: unknown\n revision?: number | undefined\n }): void {\n const current = this.store.getSnapshot()\n const candidate: SettingsScopeSnapshot<T> = {\n status: next.status,\n value: 'value' in next ? next.value : current.value,\n base: 'base' in next ? next.base : current.base,\n user: 'user' in next ? next.user : current.user,\n revision: 'revision' in next ? next.revision : current.revision,\n writable: next.writable,\n mode: current.mode,\n }\n if (sameSnapshot(candidate as SettingsScopeSnapshot<never>, current as SettingsScopeSnapshot<never>)) return\n this.store.set(candidate)\n }\n\n /** Queue operations one at a time; disposal makes the queue inert. */\n private enqueue(operation: () => Promise<SettingsMutationResult>): Promise<SettingsMutationResult> {\n if (this.disposed) return Promise.resolve('cancelled')\n const task = this.tail.then(async () => {\n if (this.disposed) return 'cancelled' as const\n return operation()\n })\n this.tail = task.then(() => {}, () => {})\n return task\n }\n\n /** Stop queued operations, stop deriving, and wait for the current wire call to settle. */\n async dispose(): Promise<void> {\n this.disposed = true\n this.writeGeneration += 1\n this.unsubscribe?.()\n await this.tail\n }\n}\n\n/** The scope plus the handles the plugin entry wires into its fiber lifecycle. */\nexport interface ManagedSettingsScope<T> extends SettingsScope<T> {\n mutate(ops: readonly SettingsPathOp[], expectedRevision?: number): Promise<SettingsMutationResult>\n /** Re-read the Host — used when the `remote.settings` namespace mounts after boot. */\n refresh(): void\n /** Stop deriving, drop the forwarded-event subscriptions, and settle in-flight work. */\n dispose(): Promise<void>\n}\n\n/**\n * Build the plugin's settings scope for one namespace.\n *\n * Subscribes the two signals that can move the Host view — the forwarded\n * `settings/document-updated` invalidation and (when the client exposes it)\n * `connection/reset` — kicks the first describe read, and derives the namespace\n * row on every mirror change.\n *\n * `resolveRemote` must be the INJECT-CAPTURED namespace (see\n * {@link SettingsRemoteResolver}), and the caller that owns that inject calls\n * {@link ManagedSettingsScope.refresh} once the namespace lands — that is what\n * turns the first, namespace-less read into a served one. A profile that never\n * mounts the namespace leaves the page in its degraded (`unavailable`,\n * read-only) state instead of throwing.\n *\n * @param namespace - Settings namespace (profile entry id) this scope binds.\n */\nexport function createSettingsScope<T>(\n context: SettingsScopeContext,\n namespace: string,\n resolveRemote: SettingsRemoteResolver,\n timer: SettingsRetryTimer = REAL_SETTINGS_TIMER,\n): ManagedSettingsScope<T> {\n const mirror = new SettingsDescribeMirror(resolveRemote, timer)\n const scope = new RemoteSettingsScope<T>(resolveRemote, mirror, namespace)\n const disposers: Array<() => void> = []\n if (typeof context.remote.$on === 'function') {\n const off = context.remote.$on('settings/document-updated', () => { mirror.ensure() })\n if (typeof off === 'function') disposers.push(off)\n }\n if (typeof context.on === 'function') {\n const off = context.on('connection/reset', () => { void mirror.load() })\n if (typeof off === 'function') disposers.push(off as () => void)\n }\n mirror.ensure()\n return {\n getSnapshot: () => scope.getSnapshot(),\n subscribe: (listener) => scope.subscribe(listener),\n set: (field, value) => scope.set(field, value),\n unset: (field) => scope.unset(field),\n mutate: (ops, revision) => scope.mutate(ops, revision),\n refresh: () => { void mirror.load() },\n dispose: async () => {\n for (const dispose of disposers.splice(0)) dispose()\n // Before the scope: a pending describe retry would otherwise re-read a\n // directory nobody is rendering any more.\n mirror.dispose()\n await scope.dispose()\n },\n }\n}\n","/** 两端共用可编辑超时范围,存储仍是整数毫秒;提示不能借用重试退避上限。 */\nexport const MIN_TIMEOUT_SECONDS = 0.001\nexport const MAX_TIMEOUT_SECONDS = 3600\n","/** 网页、终端与模型目录共用的选择规则;显式开关优先于白名单。 */\nexport function modelIsVisible(id: string, allowlist: readonly string[], overrides: unknown): boolean {\n const flag = overrides !== null && typeof overrides === 'object' && !Array.isArray(overrides)\n ? (overrides as Record<string, unknown>)[id] : undefined\n return typeof flag === 'boolean' ? flag : allowlist.length === 0 || allowlist.includes(id)\n}\n\n/** 只接收布尔事实,手工配置中的其他值不能成为可见性开关。 */\nexport function readVisibility(raw: unknown): Record<string, boolean> {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) return {}\n return Object.fromEntries(Object.entries(raw).filter(([id, value]) => id !== '' && typeof value === 'boolean'))\n}\n","/** 设置写入过程:同一控制器的意图按顺序执行,配置确认与凭据确认分别保留。\n * 生产使用现有远端设置/凭据,测试替换这些依赖;不提供跨服务事务。 */\nimport { readVisibility } from '../model-visibility.ts'\nimport type { SettingsPageApi, SettingsScope, SettingsScopeSnapshot } from './settings.ts'\nimport type { SettingsMutationResult, SettingsPathOp } from './settings-scope.ts'\n\nexport const DEFAULT_API_KEY_REF = 'COMMANDCODE_API_KEY'\nexport interface StoredRule { models: string[]; account: string }\n\n/** 与宿主路由的第一条匹配规则一致,重复模型只归属于先出现的账号。 */\nexport function accountModelMap(rules: readonly StoredRule[]): Map<string, string[]> {\n const claimed = new Set<string>()\n const map = new Map<string, string[]>()\n for (const rule of rules) {\n const list = map.get(rule.account) ?? []\n for (const model of rule.models) {\n if (claimed.has(model)) continue\n claimed.add(model)\n list.push(model)\n }\n map.set(rule.account, list)\n }\n return map\n}\n\nexport interface SettingsWriteResult {\n config: 'none' | 'confirmed' | 'conflict' | 'unconfirmed'\n credential: 'none' | 'not-issued' | 'confirmed' | 'unconfirmed'\n issue: 'target-changed' | 'closed' | 'cleanup-pending' | undefined\n refreshFailed: boolean\n /** 实际发出调用的原引用,仅用于核对;从不包含密钥内容。 */\n credentialRef: string | undefined\n}\n\nexport type SettingsWriteIntent =\n | { kind: 'save'; ops: readonly SettingsPathOp[]; visibleModels?: readonly string[]; key?: string }\n | { kind: 'rename'; ref: string; label: string }\n | { kind: 'remove' | 'cleanup'; ref: string }\n | { kind: 'key'; target: string; value?: string }\n | { kind: 'active'; id: string }\n | { kind: 'models'; target: string; models: readonly string[] }\n\ntype Snapshot = SettingsScopeSnapshot<Record<string, unknown>>\ntype CredentialInfo = { configured: boolean; writable: boolean }\ntype FieldBaseline = { value: unknown; base: unknown; user: unknown; overridden: boolean }\ninterface Command {\n intent: SettingsWriteIntent\n ops: readonly SettingsPathOp[]\n baseline: Map<string, FieldBaseline>\n defaultRef: string | undefined\n}\ninterface QueuedWrite { command: Command; resolve(result: SettingsWriteResult): void }\n\nconst record = (value: unknown): Record<string, unknown> => value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\nconst result = (): SettingsWriteResult => ({ config: 'none', credential: 'none', issue: undefined, refreshFailed: false, credentialRef: undefined })\nconst closedResult = (): SettingsWriteResult => ({ ...result(), issue: 'closed' })\nconst fieldBaseline = (snapshot: Snapshot, field: string): FieldBaseline => ({\n value: snapshot.value?.[field], base: record(snapshot.base)[field], user: record(snapshot.user)[field],\n overridden: Object.hasOwn(record(snapshot.user), field),\n})\n\n/** 不用显示文本比较配置;数组顺序与显式覆盖/继承也是写入事实。 */\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((value, i) => sameValue(value, b[i]))\n if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false\n const left = record(a), right = record(b)\n const keys = Object.keys(left)\n return keys.length === Object.keys(right).length && keys.every(key => Object.hasOwn(right, key) && sameValue(left[key], right[key]))\n}\n\nexport function writeCompleted(outcome: SettingsWriteResult): boolean {\n return outcome.issue === undefined && outcome.config !== 'conflict' && outcome.config !== 'unconfirmed'\n && outcome.credential !== 'not-issued' && outcome.credential !== 'unconfirmed'\n}\n\nexport class SettingsWriter {\n private readonly pending: QueuedWrite[] = []\n private running = false\n private closed = false\n private readonly facts = new Map<string, CredentialInfo>()\n /** 每个引用独立的读写世代,防止旧描述覆盖随后确认的凭据修改。 */\n private readonly factVersions = new Map<string, number>()\n private refreshGeneration = 0\n private refreshFailed = false\n\n constructor(\n private readonly scope: SettingsScope<Record<string, unknown>>,\n private readonly credentials: SettingsPageApi['credentials'],\n private readonly onFactsChanged: () => void,\n ) {}\n\n credential(ref: string): CredentialInfo | undefined { return this.facts.get(ref) }\n factsRefreshFailed(): boolean { return this.refreshFailed }\n\n /** 在入队时捕获意图与目标;执行者不能重新读取页面草稿。 */\n submit(intent: SettingsWriteIntent): Promise<SettingsWriteResult> {\n if (this.closed) return Promise.resolve(closedResult())\n const owned = structuredClone(intent)\n const snapshot = this.scope.getSnapshot()\n const ops = owned.kind === 'save' ? [...owned.ops] : []\n if (owned.kind === 'save' && owned.visibleModels !== undefined) {\n const list = [...owned.visibleModels]\n const keys = new Set<string>()\n for (const layer of [snapshot.base, snapshot.user, snapshot.value]) {\n for (const id of Object.keys(readVisibility(record(layer).modelVisibility))) keys.add(id)\n }\n ops.push({ op: 'set', path: ['visibleModels'], value: list },\n { op: 'set', path: ['modelVisibility'], value: Object.fromEntries([...keys].map(id => [id, list.length === 0 || list.includes(id)])) })\n }\n const baseline = new Map(ops.map(op => [op.path[0]!, structuredClone(fieldBaseline(snapshot, op.path[0]!))]))\n const defaultRef = (owned.kind === 'save' && owned.key !== undefined) || (owned.kind === 'key' && owned.target === 'default')\n ? this.defaultRef() : undefined\n return new Promise(resolve => {\n this.pending.push({ command: { intent: owned, ops, baseline, defaultRef }, resolve })\n if (!this.running) void this.drain()\n })\n }\n\n /** 销毁不等待远端;未发出的任务立即结束,已发调用只能自然收束。 */\n dispose(): void {\n this.closed = true\n for (const task of this.pending.splice(0)) task.resolve(closedResult())\n this.facts.clear()\n this.factVersions.clear()\n }\n\n private async drain(): Promise<void> {\n this.running = true\n try {\n for (;;) {\n const task = this.pending.shift()\n if (task === undefined) break\n let outcome: SettingsWriteResult\n try { outcome = this.closed ? closedResult() : await this.execute(task.command) }\n catch { outcome = { ...result(), config: 'unconfirmed' } }\n task.resolve(outcome)\n }\n } finally { this.running = false }\n }\n\n private defaultRef(): string {\n const ref = this.scope.getSnapshot().value?.apiKeyEnv\n return typeof ref === 'string' && ref !== '' ? ref : DEFAULT_API_KEY_REF\n }\n private value(field: string): unknown { return this.scope.getSnapshot().value?.[field] }\n private accounts(): Record<string, unknown>[] {\n const raw = this.value('accounts')\n return Array.isArray(raw) ? raw.filter(item => item !== null && typeof item === 'object' && !Array.isArray(item)) as Record<string, unknown>[] : []\n }\n private rules(): StoredRule[] {\n const raw = this.value('modelAccountRules')\n if (!Array.isArray(raw)) return []\n return raw.flatMap(item => {\n const rule = record(item)\n const models = Array.isArray(rule.models) ? rule.models.filter((id): id is string => typeof id === 'string' && id !== '') : []\n return models.length ? [{ models, account: typeof rule.account === 'string' && rule.account !== '' ? rule.account : 'default' }] : []\n })\n }\n private cleanupRefs(): string[] {\n const raw = this.value('credentialCleanupRefs')\n return Array.isArray(raw) ? [...new Set(raw.filter((ref): ref is string => typeof ref === 'string' && ref !== ''))] : []\n }\n private bump(ref: string): number {\n const next = (this.factVersions.get(ref) ?? 0) + 1\n this.factVersions.set(ref, next)\n return next\n }\n\n /** 只刷新事实;此入口永远不重放凭据修改。缺少条目不能解释为不存在。 */\n async refreshCredentials(extra: readonly string[] = []): Promise<boolean> {\n if (this.closed) return false\n const refs = [...new Set([this.defaultRef(), ...this.accounts().flatMap(account => typeof account.apiKeyEnv === 'string' ? [account.apiKeyEnv] : []), ...extra])]\n const generation = ++this.refreshGeneration\n const versions = new Map(refs.map(ref => [ref, this.bump(ref)]))\n let success = false\n try {\n const response = await this.credentials.describe(refs)\n if (this.closed) return false\n success = response.ok && refs.every(ref => typeof response.value?.[ref]?.configured === 'boolean')\n success = success && refs.every(ref => this.factVersions.get(ref) === versions.get(ref))\n if (success) for (const ref of refs) {\n if (this.factVersions.get(ref) !== versions.get(ref)) continue\n const view = response.value![ref]!\n this.facts.set(ref, { configured: view.configured, writable: view.writable ?? true })\n }\n } catch { /* 未读到新事实时保留最后已确认结果,不猜测不存在。 */ }\n if (!this.closed && generation === this.refreshGeneration) {\n this.refreshFailed = !success\n this.onFactsChanged()\n }\n return success\n }\n\n private async commit(ops: readonly SettingsPathOp[], baseline?: ReadonlyMap<string, FieldBaseline>): Promise<SettingsMutationResult> {\n if (this.closed) return 'cancelled'\n const snapshot = this.scope.getSnapshot()\n if (!snapshot.writable || this.scope.mutate === undefined) return 'failed'\n if (baseline && [...baseline].some(([field, before]) => !sameValue(before, fieldBaseline(snapshot, field)))) return 'conflict'\n try { return await this.scope.mutate(ops, snapshot.revision) }\n catch { return 'failed' }\n }\n\n private async configure(outcome: SettingsWriteResult, ops: readonly SettingsPathOp[], baseline?: ReadonlyMap<string, FieldBaseline>): Promise<boolean> {\n if (ops.length === 0) return true\n const confirmation = await this.commit(ops, baseline)\n outcome.config = confirmation === 'accepted' ? 'confirmed' : confirmation === 'conflict' ? 'conflict' : 'unconfirmed'\n if (confirmation === 'cancelled' || this.closed) outcome.issue = 'closed'\n return confirmation === 'accepted' && !this.closed\n }\n\n private async changeCredential(outcome: SettingsWriteResult, ref: string, value: string | undefined, defaultRef?: string): Promise<void> {\n outcome.credential = 'not-issued'\n if (this.closed) { outcome.issue = 'closed'; return }\n if (defaultRef !== undefined && this.defaultRef() !== defaultRef) { outcome.issue = 'target-changed'; return }\n outcome.credentialRef = ref\n this.bump(ref)\n try {\n const response = value === undefined ? await this.credentials.unset(ref) : await this.credentials.set(ref, value)\n outcome.credential = response.ok ? 'confirmed' : 'unconfirmed'\n } catch { outcome.credential = 'unconfirmed' }\n if (this.closed) { outcome.issue = 'closed'; return }\n this.bump(ref)\n // 远端写入确认说明引用已修改;后续读回不提供密钥内容校验。\n if (outcome.credential === 'confirmed') {\n this.facts.set(ref, { configured: value !== undefined, writable: this.facts.get(ref)?.writable ?? true })\n this.onFactsChanged()\n }\n if (defaultRef !== undefined && this.defaultRef() !== defaultRef) outcome.issue = 'target-changed'\n outcome.refreshFailed = !(await this.refreshCredentials([ref]))\n if (defaultRef !== undefined && this.defaultRef() !== defaultRef) outcome.issue = 'target-changed'\n if (this.closed) outcome.issue = 'closed'\n }\n\n private async execute(command: Command): Promise<SettingsWriteResult> {\n const outcome = result()\n const intent = command.intent\n if (!this.scope.getSnapshot().writable) return {\n ...outcome,\n config: intent.kind === 'key' || (intent.kind === 'save' && command.ops.length === 0) ? 'none' : 'unconfirmed',\n credential: intent.kind === 'key' || (intent.kind === 'save' && intent.key !== undefined) ? 'not-issued' : 'none',\n }\n if (intent.kind === 'save') {\n if (intent.key !== undefined) outcome.credential = 'not-issued'\n if (!(await this.configure(outcome, command.ops, command.baseline))) return outcome\n if (intent.key !== undefined) await this.changeCredential(outcome, command.defaultRef!, intent.key, command.defaultRef)\n } else if (intent.kind === 'key') {\n if (intent.value !== undefined && intent.value.trim() === '') return { ...outcome, credential: 'not-issued' }\n await this.changeCredential(outcome, command.defaultRef ?? intent.target, intent.value, command.defaultRef)\n } else if (intent.kind === 'rename') {\n if (intent.label === '') return { ...outcome, config: 'unconfirmed' }\n await this.configure(outcome, [{ op: 'set', path: ['accounts'], value: this.accounts().map(account => account.apiKeyEnv === intent.ref ? { ...account, label: intent.label } : { ...account }) }])\n } else if (intent.kind === 'active') {\n // 恢复自动轮换与恢复继承不同;基础层有固定账号时必须显式覆盖为空。\n const base = record(this.scope.getSnapshot().base).activeAccount\n const op: SettingsPathOp = intent.id !== '' || (typeof base === 'string' && base !== '')\n ? { op: 'set', path: ['activeAccount'], value: intent.id } : { op: 'unset', path: ['activeAccount'] }\n await this.configure(outcome, [op])\n } else if (intent.kind === 'models') {\n const chosen = [...new Set(intent.models.filter(id => id !== ''))]\n const taken = new Set(chosen)\n const map = accountModelMap(this.rules())\n for (const [account, models] of map) if (account !== intent.target) map.set(account, models.filter(id => !taken.has(id)))\n map.set(intent.target, chosen)\n const rules = [...map].flatMap(([account, models]) => models.length ? [{ account, models }] : [])\n await this.configure(outcome, [{ op: 'set', path: ['modelAccountRules'], value: rules }])\n } else {\n if (intent.kind === 'remove') {\n if (!this.accounts().some(account => account.apiKeyEnv === intent.ref) && !this.cleanupRefs().includes(intent.ref)) return { ...outcome, config: 'unconfirmed' }\n const snapshot = this.scope.getSnapshot()\n const ops: SettingsPathOp[] = [\n { op: 'set', path: ['accounts'], value: this.accounts().filter(account => account.apiKeyEnv !== intent.ref).map(account => ({ ...account })) },\n { op: 'set', path: ['modelAccountRules'], value: this.rules().filter(rule => rule.account !== intent.ref) },\n { op: 'set', path: ['credentialCleanupRefs'], value: [...new Set([...this.cleanupRefs(), intent.ref])] },\n ]\n if (this.value('activeAccount') === intent.ref) ops.push(record(snapshot.base).activeAccount === intent.ref\n ? { op: 'set', path: ['activeAccount'], value: '' } : { op: 'unset', path: ['activeAccount'] })\n if (!(await this.configure(outcome, ops))) return outcome\n }\n await this.cleanRemoved(outcome, intent.ref)\n }\n return outcome\n }\n\n private async cleanRemoved(outcome: SettingsWriteResult, ref: string): Promise<void> {\n if (!this.cleanupRefs().includes(ref)) {\n if (outcome.config !== 'confirmed') outcome.config = 'unconfirmed'\n outcome.issue = 'cleanup-pending'\n return\n }\n if (this.closed) { outcome.issue = 'closed'; return }\n if (!(await this.refreshCredentials([ref]))) { outcome.credential = 'not-issued'; outcome.refreshFailed = true; return }\n if (this.closed) { outcome.issue = 'closed'; return }\n const inherited = record(this.scope.getSnapshot().base).accounts\n const referenced = ref === this.defaultRef() || this.accounts().some(account => account.apiKeyEnv === ref)\n || (Array.isArray(inherited) && inherited.some(account => record(account).apiKeyEnv === ref))\n || this.rules().some(rule => rule.account === ref) || this.value('activeAccount') === ref\n if (!referenced && this.facts.get(ref)?.configured === true) {\n await this.changeCredential(outcome, ref, undefined)\n if (!writeCompleted(outcome) || outcome.refreshFailed) {\n if (outcome.issue === undefined && outcome.credential === 'confirmed') outcome.issue = 'cleanup-pending'\n return\n }\n }\n if (this.closed) { outcome.issue = 'closed'; return }\n // 最后一步失败不能抹掉前面已经确认的账号移除/凭据清理事实。\n const cleanup = result()\n if (!(await this.configure(cleanup, [{ op: 'set', path: ['credentialCleanupRefs'], value: this.cleanupRefs().filter(entry => entry !== ref) }]))) {\n if (outcome.config === 'none') outcome.config = cleanup.config\n outcome.issue = cleanup.issue ?? 'cleanup-pending'\n } else if (outcome.config === 'none') outcome.config = cleanup.config\n }\n}\n","/** 设置页面控制器只负责输入校验、草稿版本与页面投影。\n * 保存及即时账号操作由同一个设置写入过程持有;设置与凭据分别确认。 */\n\nimport { MIN_TIMEOUT_SECONDS, MAX_TIMEOUT_SECONDS } from '../timeout-limits.ts'\nimport { modelIsVisible, readVisibility } from '../model-visibility.ts'\nimport type { SettingsMutationResult, SettingsPathOp } from './settings-scope.ts'\nimport { SettingsWriter, DEFAULT_API_KEY_REF, accountModelMap, writeCompleted, type StoredRule, type SettingsWriteIntent, type SettingsWriteResult } from './settings-write.ts'\nexport { DEFAULT_API_KEY_REF, accountModelMap } from './settings-write.ts'\n\n/** The settings namespace the plugin registers (host half, src/index.ts). */\nexport const COMMANDCODE_NS = 'llm-commandcode'\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'\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 mutate?(ops: readonly SettingsPathOp[], expectedRevision?: number): Promise<SettingsMutationResult>\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 model editors (Host-side). Optional: a transport\n * without the Remote mount leaves the editors on the empty-catalog state.\n */\n models?(): Promise<RemoteResult<{ models: CatalogModelOption[] }>>\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 /** `format`, `tooSmall`/`tooLarge`; undefined when valid. */\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/**\n * One extra account row. Account management commits immediately (no page\n * save), so a row carries only Host facts — never a staged draft.\n */\nexport interface AccountItemState {\n /** Stable id — the account's credential reference (also its slot id). */\n id: string\n ref: string\n /** Stored label (falls back to the reference). */\n label: string\n configured: boolean\n credentialKnown: boolean\n writable: boolean\n}\n\n/** The immediate account operations, named for the failure copy. */\nexport type AccountOperation = 'rename' | 'remove' | 'key' | 'active' | 'models'\n\n/** One selectable catalog model in the settings page's model editors. */\nexport interface CatalogModelOption {\n id: string\n name: string\n /**\n * Minimum plan-tier key (a Host `KNOWN_PLANS` value), or undefined for\n * models outside the snapshot / older Hosts. Drives the tier headings in\n * the editor dropdowns; absent tiers render unheaded.\n */\n tier?: string\n /**\n * Per-model MONTHLY allowance in USD, already resolved Host-side against the\n * account pool's highest plan (Go, GOAT and Pro publish one). Undefined for\n * plans without an allowance, for models the page has no row for, and for\n * older Hosts — the row then shows no allowance instead of a guess.\n */\n allowance?: number\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 /** 没有描述或写入确认时状态未知,不能显示为未配置。 */\n apiKeyKnown: 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 /**\n * The default API key draft (write-only; starts blank, never echoes the\n * stored key). Only the Models-page card stages it for its own save; the\n * settings page writes keys immediately through `setAccountKey()`.\n */\n apiKey: StagedField\n apiBase: StagedField\n requestTimeoutMs: StagedField\n streamIdleTimeoutMs: StagedField\n /**\n * transportMaxRetries draft: how many transport failures one request absorbs\n * before the failure surfaces (issue #39's second report — the retry policy's\n * 1000-attempt, 15-minute cadence turned a 10-second TCP connect timeout into\n * an ~8-minute stall). Unset means the Host default, so it stages like the\n * timeout fields above rather than as a toggle with an implicit default.\n */\n transportMaxRetries: StagedField\n /** Opt-in durable offload of images after this model has answered. */\n offloadSeenImagesForCache: StagedField\n /** filterModelsByPlan draft; `''` = \"inherit the default\" (on). */\n filterModelsByPlan: StagedField\n /** webSearch draft; `''` = \"inherit the default\" (on — this route serves dsh's web_search). */\n webSearch: StagedField\n /** showSidebarQuota draft; `''` = \"inherit the default\" (off — the card is opt-in). */\n showSidebarQuota: StagedField\n /** zdr draft; `''` = \"inherit the default\" (off — ZDR is opt-in). */\n zdr: StagedField\n /**\n * Whether the STORED document turns the sidebar quota card on\n * (`showSidebarQuota === true`). Deliberately NOT the staged draft above: the\n * page has an explicit Save, and a card that appeared from an unsaved draft\n * would outlive a discarded edit (staging lives as long as the client does)\n * until the next page load.\n */\n sidebarQuota: boolean\n /** The stored pinned account: a slot id; `''` = \"auto — first usable account\". */\n activeAccount: string\n /** Extra accounts (multi-account rotation), in rotation order. */\n accounts: AccountItemState[]\n /**\n * Each account's dedicated models, keyed by slot id, derived from the stored\n * `modelAccountRules` with the runtime's first-match-wins semantics, so a\n * model sits under exactly the one account that would serve it.\n */\n accountModels: Record<string, string[]>\n /** Whether an immediate account operation is in flight. */\n accountBusy: boolean\n /** The last immediate account operation that failed (cleared by the next one). */\n accountFailed: AccountOperation | undefined\n /** 已移除账户的待清理凭据引用,来自持久化配置,刷新后仍能重试。 */\n pendingCredentialCleanup: string[]\n /** 宿主开通尚未完成的引用,不展示可操作的账号行。 */\n accountEnrollmentRefs: string[]\n /** Effective visible-model allowlist: staged draft or stored value. Empty = show all. */\n visibleModels: string[]\n /** 区分不受限制与终端显式隐藏全部;不能用空数组推断显示全部。 */\n visibleModelsAll: boolean\n /** The catalog the model editors offer (Host-side, empty until loaded). */\n catalogModels: CatalogModelOption[]\n /** Whether the catalog fetch failed (editors fall 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 /** Monotonic counter bumped once per accepted save (the component flashes on it). */\n savedCount: number\n /** 本次写入各阶段的确认事实,不用整体失败推断回滚。 */\n saveResult: SettingsWriteResult | undefined\n accountResult: SettingsWriteResult | undefined\n credentialRefreshFailed: boolean\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, like the Host schema's `z.number()`.\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 * The second-based bounds the timeout fields are EDITED in.\n *\n * The stored unit stays milliseconds — that is the Host schema\n * (`z.number().min(1).max(MAX_TIMER_DELAY_MS)` in src/index.ts, dsh-timeout's\n * 2^31-1 timer ceiling), and switching it would break every existing profile —\n * so this is presentation only: the field formats ms ÷ 1000 on the way in and\n * multiplies by 1000 on the way out. 3600 rather than the Host's ceiling (~24.8\n * days), because a header wait longer than an hour is a hung process, not a\n * budget, and the input is the place to refuse it. A hand-written profile can\n * still carry a larger value; `secondsField` displays that true number rather\n * than silently clamping, it just cannot be re-typed here.\n */\nexport { MIN_TIMEOUT_SECONDS, MAX_TIMEOUT_SECONDS } from '../timeout-limits.ts'\n\n/**\n * 秒制输入保留毫秒精度,兼容已有 1500ms、1ms 等配置。\n *\n * Milliseconds are the wrong unit to show: the defaults are 300000 and the\n * ceiling is 2147483647, so the page asked users to do arithmetic to answer\n * \"how long is a reasonable wait\". `format` divides, `parse` multiplies, and\n * the stored value never leaves milliseconds.\n *\n * 最多三位小数;不接受更多位数后悄悄取整,避免页面与存储不一致。\n */\nfunction secondsField(field: string, bounds: { min: number; max: number }): FieldSpec {\n return {\n field,\n format: (value) => (typeof value === 'number' ? String(value / 1000) : ''),\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return { kind: 'clear' }\n const parsed = Number(trimmed)\n if (!Number.isFinite(parsed) || !/^-?(?:\\d+(?:\\.\\d{1,3})?|\\.\\d{1,3})$/.test(trimmed)) return { kind: 'invalid', reason: 'format' }\n if (parsed < bounds.min) return { kind: 'invalid', reason: 'tooSmall' }\n if (parsed > bounds.max) return { kind: 'invalid', reason: 'tooLarge' }\n return { kind: 'set', value: Math.round(parsed * 1000) }\n },\n }\n}\n\n/** The fields this page edits inside the `llm-commandcode` namespace. */\nconst SECTION_FIELDS: FieldSpec[] = [\n textField('apiBase'),\n secondsField('requestTimeoutMs', { min: MIN_TIMEOUT_SECONDS, max: MAX_TIMEOUT_SECONDS }),\n secondsField('streamIdleTimeoutMs', { min: MIN_TIMEOUT_SECONDS, max: MAX_TIMEOUT_SECONDS }),\n // A COUNT of retries, not a millisecond wait: it shares the Host schema's\n // 0..50 bounds (`MAX_TRANSPORT_MAX_RETRIES` in src/transport-retry.ts, applied\n // to `transportMaxRetries` in src/index.ts) rather than the timer ceiling\n // above, so a draft can never be saved in a shape the Host rejects. The Host\n // stays the final gate, and the client bundle cannot import that node-side\n // module — `tests/transport-retry.test.ts` pins the schema's bound against\n // the constant so this mirrored literal cannot drift unnoticed.\n numberField('transportMaxRetries', { min: 0, max: 50 }),\n booleanField('offloadSeenImagesForCache'),\n booleanField('filterModelsByPlan'),\n booleanField('webSearch'),\n booleanField('showSidebarQuota'),\n booleanField('zdr'),\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/** 共享控制器跨普通切页保存草稿,插件销毁才关闭写入过程。 */\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 credentialRef = DEFAULT_API_KEY_REF\n private readonly writer: SettingsWriter\n private saveResult: SettingsWriteResult | undefined\n private accountResult: SettingsWriteResult | undefined\n /** Staged visible-model allowlist (undefined = no draft). */\n private visibleModelsDraft: string[] | undefined = undefined\n private catalogModels: CatalogModelOption[] = []\n private catalogFailed = false\n private saving = false\n private failed = false\n private savedCount = 0\n private accountPending = 0\n private accountFailed: AccountOperation | undefined = undefined\n\n constructor(\n scope: SettingsScope<Record<string, unknown>>,\n api: SettingsPageApi,\n ) {\n this.scope = scope\n this.api = api\n this.writer = new SettingsWriter(scope, api.credentials, () => this.publish())\n this.disposers.push(scope.subscribe(() => {\n this.recomputeCredentialRef()\n void this.writer.refreshCredentials()\n this.publish()\n }))\n this.recomputeCredentialRef()\n void this.writer.refreshCredentials()\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 this.writer.dispose()\n this.staged.clear()\n this.visibleModelsDraft = undefined\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 the profile Config gets a page that\n * addresses the renamed ref instead of silently writing the default —\n * 与模型卡共享同一设置引用。\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 }\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.writer.credential(this.credentialRef)\n const accounts = this.effectiveAccounts()\n const active = this.sectionValue('activeAccount')\n return {\n available: snapshot.status === 'ready',\n writable: snapshot.writable,\n apiKeyConfigured: credential?.configured ?? false,\n apiKeyKnown: credential !== undefined,\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 apiBase: this.field('apiBase'),\n requestTimeoutMs: this.field('requestTimeoutMs'),\n streamIdleTimeoutMs: this.field('streamIdleTimeoutMs'),\n transportMaxRetries: this.field('transportMaxRetries'),\n offloadSeenImagesForCache: this.field('offloadSeenImagesForCache'),\n filterModelsByPlan: this.field('filterModelsByPlan'),\n webSearch: this.field('webSearch'),\n showSidebarQuota: this.field('showSidebarQuota'),\n zdr: this.field('zdr'),\n sidebarQuota: this.sectionValue('showSidebarQuota') === true,\n activeAccount: typeof active === 'string' ? active : '',\n accounts,\n accountModels: Object.fromEntries(accountModelMap(this.storedRules())),\n accountBusy: this.accountPending > 0,\n accountFailed: this.accountFailed,\n pendingCredentialCleanup: this.cleanupRefs().filter((ref) => !this.enrollmentRefs(true).includes(ref)),\n accountEnrollmentRefs: this.enrollmentRefs(false),\n visibleModels: this.effectiveVisibleModels(),\n visibleModelsAll: this.visibleModelsDraft === undefined ? this.storedShowsAll() : this.visibleModelsDraft.length === 0,\n catalogModels: this.catalogModels,\n catalogFailed: this.catalogFailed,\n dirty: plan.length > 0 || this.visibleModelsDirty(),\n invalid: plan.some((item) => item.change === undefined),\n saving: this.saving,\n failed: this.failed,\n savedCount: this.savedCount,\n saveResult: this.saveResult,\n accountResult: this.accountResult,\n credentialRefreshFailed: this.writer.factsRefreshFailed(),\n }\n }\n\n // --- Staged form ---\n\n private enrollmentRefs(includeNamed: boolean): string[] {\n const records = this.sectionValue('accountEnrollmentTasks')\n if (!Array.isArray(records)) return []\n return records.flatMap((item: unknown) => {\n if (typeof item !== 'object' || item === null) return []\n const record = item as Record<string, unknown>\n return typeof record.ref === 'string' && (includeNamed || record.phase !== 'naming') ? [record.ref] : []\n })\n }\n\n /** Stage one field's draft text. */\n edit(field: string, text: string): void {\n if (field !== 'apiKey') this.spec(field)\n this.staged.set(field, { text, clear: false })\n this.failed = false\n this.saveResult = undefined\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.saveResult = undefined\n this.publish()\n }\n\n /** Discard every staged edit. */\n discard(): void {\n if (this.staged.size === 0 && this.visibleModelsDraft === undefined && !this.failed) return\n this.staged.clear()\n this.visibleModelsDraft = undefined\n this.failed = false\n this.saveResult = undefined\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 async refreshCredentials(): Promise<void> {\n if (!(await this.writer.refreshCredentials()) || this.disposed) return\n if (this.saveResult) this.saveResult = { ...this.saveResult, refreshFailed: false }\n if (this.accountResult) this.accountResult = { ...this.accountResult, refreshFailed: false }\n this.publish()\n }\n\n /** 冻结点击时的草稿;只清理本次已确认且期间未被替换的对象。 */\n async save(): Promise<SettingsWriteResult | undefined> {\n if (this.disposed || this.saving) return\n const submitted = new Map(this.staged)\n const submittedVisible = this.visibleModelsDraft\n const plan = this.plan()\n const visibleDirty = this.visibleModelsDirty()\n if ((plan.length === 0 && !visibleDirty) || plan.some(item => item.change === undefined)) return\n const ops = plan.flatMap(item => typeof item.change === 'object' ? [item.change] : [])\n const key = plan.find(item => item.field === 'apiKey')?.change\n this.saving = true\n this.failed = false\n this.saveResult = undefined\n // 入队先于通知订阅者,避免通知回调发起的后续操作插队。\n const completion = this.writer.submit({ kind: 'save', ops,\n ...(visibleDirty ? { visibleModels: submittedVisible ?? [] } : {}),\n ...(typeof key === 'string' ? { key } : {}),\n })\n this.publish()\n const outcome = await completion\n if (this.disposed) return outcome\n this.saving = false\n this.saveResult = outcome\n this.failed = !writeCompleted(outcome)\n if (!this.failed) this.savedCount += 1\n for (const [field, draft] of submitted) {\n const confirmed = field === 'apiKey'\n ? outcome.credential === 'confirmed' && outcome.issue === undefined\n : outcome.config === 'confirmed' || writeCompleted(outcome)\n if (confirmed && this.staged.get(field) === draft) this.staged.delete(field)\n }\n if ((outcome.config === 'confirmed' || writeCompleted(outcome)) && this.visibleModelsDraft === submittedVisible) this.visibleModelsDraft = undefined\n this.publish()\n return outcome\n }\n\n /** Stage the visible-model allowlist (multi-select). */\n editVisibleModels(models: string[]): void {\n this.visibleModelsDraft = [...models]\n this.failed = false\n this.saveResult = undefined\n this.publish()\n }\n\n /** Stage \"show all models\" (clears the allowlist). */\n clearVisibleModels(): void {\n this.visibleModelsDraft = []\n this.failed = false\n this.saveResult = undefined\n this.publish()\n }\n\n // --- Immediate account management ---\n\n renameAccount(ref: string, label: string): Promise<boolean> {\n return this.runAccountOp('rename', { kind: 'rename', ref, label: label.trim() })\n }\n\n /** 配置移除确认后才清理凭据,失败记录留在宿主清理队列。 */\n removeAccount(ref: string): Promise<boolean> {\n return this.runAccountOp('remove', { kind: 'remove', ref })\n }\n\n retryCredentialCleanup(ref: string): Promise<boolean> {\n return this.runAccountOp('remove', { kind: 'cleanup', ref })\n }\n\n private cleanupRefs(): string[] {\n const raw = this.sectionValue('credentialCleanupRefs')\n return Array.isArray(raw) ? [...new Set(raw.filter((ref): ref is string => typeof ref === 'string' && ref !== ''))] : []\n }\n\n setAccountKey(target: string, key: string): Promise<boolean> {\n return this.runAccountOp('key', { kind: 'key', target, value: key.trim() })\n }\n\n clearAccountKey(target: string): Promise<boolean> {\n return this.runAccountOp('key', { kind: 'key', target })\n }\n\n setActiveAccount(id: string): Promise<boolean> {\n return this.runAccountOp('active', { kind: 'active', id })\n }\n\n setAccountModels(target: string, models: readonly string[]): Promise<boolean> {\n return this.runAccountOp('models', { kind: 'models', target, models })\n }\n\n /** 即时入口与保存共享写入过程,只在这里维护页面忙碌投影。 */\n private async runAccountOp(op: AccountOperation, intent: SettingsWriteIntent): Promise<boolean> {\n this.accountPending += 1\n this.accountFailed = undefined\n this.accountResult = undefined\n const completion = this.writer.submit(intent)\n this.publish()\n const outcome = await completion\n this.accountPending -= 1\n if (this.disposed) return false\n const ok = writeCompleted(outcome)\n this.accountResult = outcome\n this.accountFailed = ok ? undefined : op\n this.publish()\n return ok\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 private plan(): Array<{ field: string; change: SettingsPathOp | string | undefined }> {\n const plan: Array<{ field: string; change: SettingsPathOp | string | undefined }> = []\n for (const [field, staged] of this.staged) {\n if (field === 'apiKey') {\n const value = staged.text.trim()\n if (value !== '') plan.push({ field, change: value })\n continue\n }\n const spec = this.spec(field)\n if (staged.clear) {\n if (this.stored(field)) plan.push({ field, change: { op: 'unset', path: [field] } })\n continue\n }\n if (staged.text === spec.format(this.sectionValue(field))) continue\n const parsed = spec.parse(staged.text)\n const change: SettingsPathOp | undefined = parsed.kind === 'invalid' ? undefined\n : parsed.kind === 'clear' ? { op: 'unset', path: [field] } : { op: 'set', path: [field], value: parsed.value }\n plan.push({ field, change })\n }\n return plan\n }\n\n /**\n * Fetch the model catalog through the Host Remote. Runs once at construction;\n * call again (e.g. from the client entry once the Remote mount lands) to\n * (re)try — a later success clears a prior failure flag, so the editors\n * recover 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 // Defensive per-entry shaping: the Remote result is untrusted at the\n // boundary, and an older Host predates the tier field.\n const shaped: CatalogModelOption[] = []\n for (const model of response.value.models) {\n if (typeof model !== 'object' || model === null) continue\n const entry = model as unknown as Record<string, unknown>\n if (typeof entry.id !== 'string' || typeof entry.name !== 'string') continue\n shaped.push({\n id: entry.id,\n name: entry.name,\n ...(typeof entry.tier === 'string' ? { tier: entry.tier } : {}),\n ...(typeof entry.allowance === 'number' && Number.isFinite(entry.allowance)\n ? { allowance: entry.allowance }\n : {}),\n })\n }\n this.catalogModels = shaped\n this.catalogFailed = false\n } else {\n this.catalogFailed = true\n }\n }, () => {\n this.catalogFailed = true\n }).then(() => this.publish())\n }\n\n // --- Stored accounts and rules ---\n\n /** The raw `accounts` array of the stored section, verbatim. */\n private rawStoredAccounts(): Array<Record<string, unknown>> {\n const raw = this.scope.getSnapshot().value?.accounts\n if (!Array.isArray(raw)) return []\n return raw.filter(\n (entry): entry is Record<string, unknown> =>\n typeof entry === 'object' && entry !== null && !Array.isArray(entry),\n )\n }\n\n /**\n * The stored extra accounts this page can address: the rows carrying a\n * credential reference. Entries it cannot name (a composition entry with a\n * literal `apiKey`, or an unknown shape) are never dropped — every list\n * write starts from {@link rawStoredAccounts} and copies them verbatim,\n * because the settings layer replaces the whole array.\n */\n private storedExtras(): Array<{ label: string; ref: string }> {\n const out: Array<{ label: string; ref: string }> = []\n const seen = new Set<string>()\n for (const record of this.rawStoredAccounts()) {\n const ref = record.apiKeyEnv\n if (typeof ref !== 'string' || ref === '' || seen.has(ref)) continue\n seen.add(ref)\n const label = record.label\n out.push({ label: typeof label === 'string' && label !== '' ? label : ref, ref })\n }\n return out\n }\n\n private effectiveAccounts(): AccountItemState[] {\n return this.storedExtras().map((extra) => ({\n id: extra.ref,\n ref: extra.ref,\n label: extra.label,\n configured: this.writer.credential(extra.ref)?.configured ?? false,\n credentialKnown: this.writer.credential(extra.ref) !== undefined,\n writable: this.writer.credential(extra.ref)?.writable ?? true,\n }))\n }\n\n /** The stored routing rules from the settings section (`modelAccountRules`). */\n private storedRules(): StoredRule[] {\n const raw = this.scope.getSnapshot().value?.modelAccountRules\n if (!Array.isArray(raw)) return []\n const out: StoredRule[] = []\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 models = Array.isArray(record.models)\n ? record.models.filter((m): m is string => typeof m === 'string' && m !== '')\n : []\n if (models.length === 0) continue\n out.push({\n models,\n account: typeof record.account === 'string' && record.account !== '' ? record.account : 'default',\n })\n }\n return out\n }\n\n /** 原始白名单;空列表延续现有的显示全部语义。 */\n private storedAllowlist(): string[] {\n const raw = this.scope.getSnapshot().value?.visibleModels\n if (!Array.isArray(raw)) return []\n return raw.filter((m): m is string => typeof m === 'string' && m !== '')\n }\n\n private storedShowsAll(): boolean {\n return this.storedAllowlist().length === 0\n && !Object.values(readVisibility(this.scope.getSnapshot().value?.modelVisibility)).includes(false)\n }\n\n /** 目录、白名单与显式显示的旧模型一起投影,目录失败不删除旧选择。 */\n private storedVisibleModels(): string[] {\n const list = this.storedAllowlist()\n const flags = readVisibility(this.scope.getSnapshot().value?.modelVisibility)\n const ids = [...new Set([...list, ...this.catalogModels.map((model) => model.id), ...Object.keys(flags)])]\n return ids.filter((id) => modelIsVisible(id, list, flags))\n }\n\n private effectiveVisibleModels(): string[] {\n if (this.visibleModelsDraft === undefined) return this.storedVisibleModels()\n return this.visibleModelsDraft.length === 0\n ? this.catalogModels.map((model) => model.id)\n : this.visibleModelsDraft\n }\n\n private visibleModelsDirty(): boolean {\n if (this.visibleModelsDraft === undefined) return false\n if (this.visibleModelsDraft.length === 0) return !this.storedShowsAll()\n return this.storedShowsAll() || !sameModels(this.visibleModelsDraft, this.storedVisibleModels())\n }\n\n private publish(): void {\n if (this.disposed) return\n for (const listener of this.listeners) listener()\n }\n}\n","/** Shared, dependency-free formatting for Host commands and browser surfaces. */\n\nexport function formatMoney(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\nexport function formatMoneyExact(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\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/** The input is already in percent units; callers add the percent sign. */\nexport function formatSuccessRate(value: number): string {\n return String(Number(value.toFixed(2)))\n}\n\n/** One window's fill ratio in [0, 1]; zero 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/** Local date-time, with the empty state chosen by the caller. */\nexport function formatResetAt(ms: number): string {\n return ms <= 0 ? '' : new Date(ms).toLocaleString()\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 * @module dsh-commandcode-provider/client/usage\n */\n\nimport type { CommandCodeAccountsReport, CommandCodeCatalog, CommandCodePriceTable } from '../usage-wire.ts'\nimport type { CommandCodeLoginStatus } from '../login-wire.ts'\nimport type { EnrollmentRemote } from './enrollment.ts'\nimport type { AnalyticsRemote } from './analytics.ts'\nimport type { AnalyticsQuery, AnalyticsReport } from '../analytics-wire.ts'\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nimport { readableErrorText } from './error-text.ts'\nexport { formatMoney, formatMoneyExact, formatTokensCompact, formatSuccessRate, windowRatio, formatResetAt } from '../display-format.ts'\n\n/**\n * Merge the plugin's Remote endpoints into the harness's typed client Remote\n * surface, so `ctx.remote.commandcode.*()` is typed once each contribution is\n * mounted. The `commandcode` namespace member is declared exactly once here\n * (interface merging forbids duplicate members) and therefore carries the usage\n * report, the model catalog, the price table AND the login endpoints.\n */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/report': () => Promise<RemoteResult<CommandCodeAccountsReport>>\n 'commandcode/models': () => Promise<RemoteResult<CommandCodeCatalog>>\n 'commandcode/prices': () => Promise<RemoteResult<CommandCodePriceTable>>\n 'commandcode/analytics': (query: AnalyticsQuery) => Promise<RemoteResult<AnalyticsReport>>\n }\n interface TypertRemoteNamespaceMap {\n commandcode: Partial<EnrollmentRemote> & AnalyticsRemote & {\n report: () => Promise<RemoteResult<CommandCodeAccountsReport>>\n models: () => Promise<RemoteResult<CommandCodeCatalog>>\n /**\n * Optional because the Host half and this browser bundle can be a\n * cross-version pair: a Host older than the price table mounts no\n * `commandcode/prices` descriptor, so the member is genuinely absent at\n * runtime. The price controller reads a missing method as \"no table\"\n * (see `./prices.ts`) instead of throwing.\n */\n prices?: () => Promise<RemoteResult<CommandCodePriceTable>>\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 * Optional for the same cross-version reason as the namespace member above;\n * `CommandCodePricesController` reads the absence as a permanent \"no prices\"\n * state.\n */\n prices?(): Promise<\n | { ok: true; value: CommandCodePriceTable }\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: readableErrorText(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/** Host facts drive the usage card, including keys invisible to browser credentials. */\nexport function usageCardState(usage: UsagePageState) {\n const accounts = usage.report?.accounts ?? []\n return {\n loading: usage.status === 'loading',\n shouldRefresh: usage.status === 'idle',\n noKey: accounts.length > 0 && !accounts.some(account => account.configured),\n }\n}\n","/**\n * Browser controller for the model price table the composer's session-cost\n * figure depends on.\n *\n * The rates are vendored Host-side (`src/model-prices.ts`) and cross the\n * `commandcode/prices` Remote, so the browser never carries its own copy that\n * could drift from the snapshot, and a price update reaches an open page\n * without rebuilding the client bundle.\n *\n * @module dsh-commandcode-provider/client/prices\n */\n\nimport type { CommandCodePriceTable } from '../usage-wire.ts'\nimport { readableErrorText } from './error-text.ts'\n\n/** The narrow slice of the mounted Remote this controller calls. */\nexport interface PricesRemote {\n /**\n * Optional because the Host and the browser bundle can be a cross-version\n * pair: a Host half older than this feature serves no `commandcode/prices`\n * endpoint, and the controller must read that as \"no price table\" instead of\n * calling an undefined method.\n */\n prices?(): Promise<\n | { ok: true; value: CommandCodePriceTable }\n | { ok: false; error: { message: string; permanent?: boolean } }\n >\n}\n\n/** The price table's fetch lifecycle. */\nexport type PricesStatus =\n /** Never requested. */\n | 'idle'\n /** A fetch is in flight. */\n | 'loading'\n /** The table is loaded and cached for the page's lifetime. */\n | 'ready'\n /** The last fetch failed; `ensure()` may try again. */\n | 'error'\n\n/** The readout's price-table state face. */\nexport interface SessionCostPricesState {\n status: PricesStatus\n /** The cached table (only ever set once). */\n table: CommandCodePriceTable | undefined\n /** The last failure's message. */\n error: string | undefined\n}\n\nconst IDLE: SessionCostPricesState = { status: 'idle', table: undefined, error: undefined }\n\n/**\n * Timer seam for the bounded retry backoff, so a node test can drive the\n * schedule without waiting on it.\n */\nexport interface PriceRetryTimer {\n set(callback: () => void, ms: number): unknown\n clear(handle: unknown): void\n}\nconst RETRY_TIMER: PriceRetryTimer = {\n set(callback, ms) { const handle = setTimeout(callback, ms); handle.unref?.(); return handle },\n clear(handle) { clearTimeout(handle as ReturnType<typeof setTimeout>) },\n}\n\n/**\n * Cache over the `commandcode/prices` Remote, with a bounded transient-retry\n * budget (three retries at 1/2/4 s — bounded, not a poll). Public API mirrors\n * {@link CommandCodeUsageController}: `state()`, `subscribe` and `ensure()`;\n * `reload()` additionally drops the cache and restarts the budget when the\n * Host namespace rebinds. A MANUAL `ensure()` still fetches after the budget\n * is spent, and a PERMANENT failure — the Host serving no such endpoint — is\n * terminal for the binding until `reload()`.\n */\nexport class CommandCodePricesController {\n private readonly remote: PricesRemote\n private readonly listeners = new Set<() => void>()\n private current: SessionCostPricesState = IDLE\n private generation = 0\n private inFlight = false\n private disposed = false\n\n private retryHandle: unknown\n private attempts = 0\n private permanent = false\n private readonly timer: PriceRetryTimer\n\n constructor(remote: PricesRemote, timer: PriceRetryTimer = RETRY_TIMER) {\n this.timer = timer\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.clearRetry()\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 state face. */\n state(): SessionCostPricesState {\n return this.current\n }\n\n /**\n * Fetch the table unless it is already loaded, permanent, or in flight — and\n * unless a bounded retry already owns the next attempt. Only the client\n * entry calls this (on rebind and on a manual refresh), so a mounted readout\n * renders the current state instead of triggering a fetch of its own.\n */\n ensure(): void {\n if (this.disposed || this.permanent || this.inFlight || this.current.status === 'ready') return\n this.clearRetry()\n const call = this.remote.prices\n // An older Host half serves no price endpoint. That is a permanent\n // condition for this page, so it lands in the error state (the readout\n // stays hidden) rather than retrying on every mount.\n if (typeof call !== 'function') {\n this.permanent = true\n this.publish({ status: 'error', table: undefined, error: 'the Host serves no commandcode/prices endpoint' })\n return\n }\n const generation = this.generation\n this.inFlight = true\n this.attempts += 1\n this.publish({ status: 'loading', table: this.current.table, error: undefined })\n let request: ReturnType<NonNullable<PricesRemote['prices']>>\n try { request = call.call(this.remote) } catch (error) { request = Promise.reject(error) }\n void request.then((result) => {\n if (this.disposed || generation !== this.generation) return\n this.inFlight = false\n if (result.ok) {\n this.publish({ status: 'ready', table: result.value, error: undefined })\n return\n }\n this.permanent = result.error.permanent === true\n this.publish({ status: 'error', table: undefined, error: result.error.message })\n this.scheduleRetry()\n }, (error: unknown) => {\n if (this.disposed || generation !== this.generation) return\n this.inFlight = false\n this.publish({\n status: 'error',\n table: undefined,\n error: readableErrorText(error),\n })\n this.scheduleRetry()\n })\n }\n\n /** Rebinding a Host invalidates cached prices and restarts the bounded retry budget. */\n reload(): void {\n if (this.disposed) return\n this.generation += 1\n this.inFlight = false\n this.clearRetry()\n this.permanent = false\n this.attempts = 0\n this.current = IDLE\n this.ensure()\n }\n\n private clearRetry(): void {\n if (this.retryHandle !== undefined) this.timer.clear(this.retryHandle)\n this.retryHandle = undefined\n }\n\n private scheduleRetry(): void {\n if (this.disposed || this.permanent || this.attempts >= 4) return\n this.retryHandle = this.timer.set(() => { this.retryHandle = undefined; this.ensure() }, 1000 * 2 ** (this.attempts - 1))\n }\n\n private publish(next: SessionCostPricesState): void {\n this.current = next\n for (const listener of this.listeners) listener()\n }\n}\n","/** 收到宿主授权地址后才打开页面;浏览器拦截不应中断登录,界面始终保留手动链接。 */\nexport function openLoginPage(authUrl: string): void {\n if (typeof window === 'undefined') return\n try {\n // 授权页不持有设置页引用,也不接收设置页来源地址。\n // 使用 noopener 时成功打开也可能返回 null,因此不据此判断弹窗是否被拦截。\n window.open(authUrl, '_blank', 'noopener,noreferrer')\n } catch { /* 自动打开失败时仍可通过手动链接完成授权。 */ }\n}\n","/**\n * Browser controller for the settings page's login panel: `begin` asks the\n * Host to bind the callback server and returns the Studio URL, the controller\n * polls `loginStatus` while the attempt is live, and `cancel` tears it down.\n * The key itself never crosses to the browser — the Host validates and stores\n * it through the credentials seam.\n *\n * Transport-level failures (no mounted Remote, an older Host without the login\n * endpoints) land in the dedicated `unavailable` phase so the page can point\n * back at manual paste. Deliberately JSX-free, mirroring `./settings.ts` and\n * `./usage.ts`.\n *\n * @module dsh-commandcode-provider/client/login\n */\n\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nimport { readableErrorText } from './error-text.ts'\nimport { openLoginPage } from './login-page.ts'\nimport type { CommandCodeLoginFailureReason, CommandCodeLoginStatus } from '../login-wire.ts'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsCommandCodeKey } from './locales.ts'\n\n/** The endpoint-level Remote surface this controller calls. */\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/loginBegin': (targetRef?: string) => 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(targetRef?: string): 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 saved extra account receiving this attempt, or undefined for default. */\n targetRef?: string\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/** Keep one account's login status out of every other account's row. */\nexport function loginStateForTarget(\n state: LoginPageState,\n targetRef: string | undefined,\n): { visible: LoginPageState; busyElsewhere: boolean } {\n if (state.targetRef === targetRef) return { visible: state, busyElsewhere: false }\n return {\n visible: { ...state, phase: 'idle', authUrl: undefined },\n busyElsewhere: state.phase === 'starting' || state.phase === 'waiting',\n }\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 targetRef: string | undefined\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 private openedPage = false\n\n constructor(remote: () => LoginRemote | undefined, pollMs = POLL_INTERVAL_MS, private readonly openPage = openLoginPage) {\n this.remote = remote\n this.pollMs = pollMs\n }\n\n /** Subscribe to state projections. */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n state(): LoginPageState {\n return {\n phase: this.phase,\n ...(this.targetRef === undefined ? {} : { targetRef: this.targetRef }),\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(targetRef?: string): Promise<void> {\n if (this.disposed || this.phase === 'starting' || this.phase === 'waiting') return\n const generation = ++this.generation\n this.openedPage = false\n this.targetRef = targetRef\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(targetRef)\n } catch (error: unknown) {\n // A transport throw (gateway hiccup) reads the same as a rejected call.\n result = { ok: false, error: { message: readableErrorText(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 /** Poll until the attempt leaves `waiting` or a newer loop supersedes us. */\n private async poll(generation: number): Promise<void> {\n // `currentPhase` is a getter, read (not the field) so control-flow\n // narrowing across `await` 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 // 在宿主返回地址后打开,每次尝试仅执行一次,状态轮询不重复开页。\n if (status.authUrl && !this.openedPage) {\n this.openedPage = true\n this.openPage(status.authUrl)\n }\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// Hint copy for the login panel / card row, JSX-free so node tests drive it.\n\n/**\n * The per-reason copy for a failed attempt. Shared by the settings page's login\n * panel and the Models-page card's login row — the same reason can surface from\n * either.\n */\nexport function loginFailureCopy(\n reason: CommandCodeLoginFailureReason | undefined,\n t: Translate<SettingsCommandCodeKey>,\n): 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/** One login panel row's computed hint: text, class stem, and optional title. */\nexport interface LoginHint {\n text: string\n className: string\n /** Tooltip shown when the row carries secondary failure detail. */\n title: string | undefined\n}\n\n/**\n * The hint text + class for one login panel state, shared by the settings\n * page's login panel and the Models-page card's login row so both surfaces\n * can never drift apart. Pure: no timers, no state.\n */\nexport function loginHint(\n state: LoginPageState,\n t: Translate<SettingsCommandCodeKey>,\n): LoginHint {\n if (state.phase === 'starting' || state.phase === 'waiting') {\n return {\n text: t(state.phase === 'starting' ? 'loginStarting' : 'loginWaiting'),\n className: 'cc-hint',\n title: undefined,\n }\n }\n if (state.phase === 'success') {\n const keyName = state.keyName !== undefined && state.keyName !== '' ? ` · ${state.keyName}` : ''\n return {\n text: `${t('loginSuccess')} ${state.userName ?? ''}${keyName}`.trim(),\n className: 'cc-loginDone',\n title: undefined,\n }\n }\n if (state.phase === 'failed') {\n return {\n text: loginFailureCopy(state.reason, t),\n className: 'cc-loginError',\n title: state.message,\n }\n }\n if (state.phase === 'unavailable') {\n return {\n text: `${t('loginUnavailable')} ${state.message ?? ''}`.trim(),\n className: 'cc-loginError',\n title: undefined,\n }\n }\n return { text: t('loginHintIdle'), className: 'cc-hint', title: undefined }\n}\n","/**\n * Shared boundary-validation and Remote-descriptor plumbing for the plugin's\n * hand-rolled Typert wire contracts (`commandcode/report`, `commandcode/models`,\n * `commandcode/prices`, `commandcode/login*`).\n *\n * Every Remote this plugin serves crosses the Typert Gateway with a strict\n * result schema: the Host half registers a descriptor against a Cordis service\n * (`src/usage-remote.ts`) and the browser half mounts the matching contribution\n * on `ctx.remote` (`src/client/index.ts`). This module is dependency-free so\n * the client bundle can inline it, and it holds the schema helpers and\n * descriptor boilerplate the wire files used to duplicate.\n *\n * @module dsh-commandcode-provider/wire-shared\n */\nimport type { InvocationDescriptor, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\n\n/** The npm package identity every contribution and descriptor claims. */\nexport const REMOTE_PACKAGE = '@mars-sea/dsh-commandcode-provider'\n\n/** The Cordis service key the Gateway resolves every Command Code Remote from. */\nexport const REMOTE_SERVICE = 'commandcodeUsage'\n\n/** The wire namespace all Command Code endpoints share. */\nexport const REMOTE_NAMESPACE = 'commandcode'\n\n/** The read/validate helpers one boundary codec needs. */\nexport interface BoundaryValidator {\n /** Reject one boundary value with a field-naming error. */\n reject(field: string): never\n /** Narrow an unknown value to a plain record, or reject. */\n record(value: unknown, field: string): Record<string, unknown>\n /** Read one required string field (`field` is the dotted error label). */\n stringField(source: Record<string, unknown>, key: string, field: string): string\n /** Read one required finite number field (`field` is the dotted error label). */\n numberField(source: Record<string, unknown>, key: string, field: string): number\n /** Read one required boolean field (`field` is the dotted error label). */\n booleanField(source: Record<string, unknown>, key: string, field: string): boolean\n}\n\n/**\n * Build the validator helpers one endpoint uses. `prefix` names the endpoint\n * in the rejection message (e.g. `commandcode/report result:`), so each wire\n * file keeps its own diagnostic phrasing while sharing the helper bodies.\n *\n * The helpers return the reject call directly in the failure branch: since\n * `reject` is typed `never`, the ternary's union collapses to the success type\n * without relying on TypeScript's control-flow analysis of a never-returning\n * call (which only recognizes function declarations, not the destructured\n * arrow `reject` callers receive from this factory). Callers that need the\n * narrowing in an `if` must therefore assign inside the positive branch.\n */\nexport function makeBoundaryValidator(prefix: string): BoundaryValidator {\n const reject = (field: string): never => {\n throw new TypeError(`${prefix} invalid ${field}`)\n }\n const record = (value: unknown, field: string): Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : reject(field)\n const stringField = (source: Record<string, unknown>, key: string, field: string): string =>\n typeof source[key] === 'string' ? source[key] as string : reject(field)\n const numberField = (source: Record<string, unknown>, key: string, field: string): number =>\n typeof source[key] === 'number' && Number.isFinite(source[key] as number)\n ? source[key] as number\n : reject(field)\n const booleanField = (source: Record<string, unknown>, key: string, field: string): boolean =>\n typeof source[key] === 'boolean' ? source[key] as boolean : reject(field)\n return { reject, record, stringField, numberField, booleanField }\n}\n\n/**\n * One strict result codec: `mode: 'strict'` carries the LAZY schema factory\n * (`create()`) the registry requires and the Gateway validates with\n * (`codec.create().parse`). There is NO `schema` member — issue #49.\n */\ninterface StrictCodec<Output> {\n readonly mode: 'strict'\n readonly typeSymbol: string\n readonly create: () => TypertSchema<Output>\n}\n\n/** Use the same strict-codec shape for invocation parameters and results. */\nexport function makeStrictCodec<Output>(typeSymbol: string, schema: TypertSchema<Output>): StrictCodec<Output> {\n return { mode: 'strict', typeSymbol, create: () => schema }\n}\n\n/**\n * Build one strict invocation descriptor. Every Command Code Remote shares the\n * `commandcode` namespace, the `commandcodeUsage` service, and a strict result\n * — only the endpoint, method, result type symbol, and schema differ.\n */\nexport function makeRemoteDescriptor<Output>(\n endpoint: string,\n method: string,\n typeSymbol: string,\n schema: TypertSchema<Output>,\n): InvocationDescriptor {\n return {\n id: `${REMOTE_PACKAGE}#${endpoint}`,\n service: REMOTE_SERVICE,\n namespace: REMOTE_NAMESPACE,\n method,\n invocation: { kind: 'direct' },\n parameters: [],\n result: makeStrictCodec(typeSymbol, schema),\n }\n}\n","/**\n * Wire contracts for the Command Code Remotes the browser half mounts: the\n * account-usage report (`commandcode/report`), the model catalog\n * (`commandcode/models`) and the price table (`commandcode/prices`).\n *\n * The browser never holds the API key, so every one of these is produced\n * Host-side: the Host half registers a strict invocation descriptor against a\n * Cordis service (`src/usage-remote.ts`) and the browser half mounts the\n * matching contribution on `ctx.remote` (`src/client/index.ts`). This module\n * is the single source both halves share — the hand-rolled result validators\n * and the exact descriptor objects, so neither half can drift. It is\n * dependency-free because the client bundle inlines it.\n *\n * @module dsh-commandcode-provider/usage-wire\n */\n\nimport type { CommandCodeCredits, CommandCodeUsageReport, UsageBlockReason } from './adapter.ts'\n\nexport type { CommandCodeUsageReport, UsageBlockReason }\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\nimport {\n makeBoundaryValidator,\n makeRemoteDescriptor,\n REMOTE_PACKAGE,\n} from './wire-shared.ts'\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 = REMOTE_PACKAGE\n\n/** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */\nexport const USAGE_REPORT_ENDPOINT = 'commandcode/report'\n\n/**\n * The shared read/validate helpers for the usage report endpoint, prefixed\n * so rejection messages name the offending boundary.\n */\nconst { reject, record, stringField, numberField, booleanField } =\n makeBoundaryValidator('commandcode/report result:')\n\n/**\n * Parse one quota window, or undefined when the frame carries no such window.\n *\n * The distinction is load-bearing at this boundary: an ABSENT window means the\n * billing endpoint reported none (an unlimited plan), while a present block with\n * `cap: 0` means uncapped spend that was really reported. Collapsing the two\n * would draw a zeroed quota row for an account that has no such limit.\n */\nfunction windowLimit(\n value: unknown,\n field: string,\n): { used: number; cap: number; exceeded: boolean; resetAt: number } | undefined {\n if (value === undefined) return undefined\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 === 'invalid-response' || blocked === 'network') {\n report.blocked = blocked\n } else {\n reject('blocked')\n }\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 const parsed: CommandCodeCredits = {\n monthlyCredits: numberField(credits, 'monthlyCredits', 'credits.monthlyCredits'),\n purchasedCredits: numberField(credits, 'purchasedCredits', 'credits.purchasedCredits'),\n freeCredits: numberField(credits, 'freeCredits', 'credits.freeCredits'),\n }\n // OPTIONAL on the wire: an explicit `false` means the endpoint omitted the\n // balance, which cannot be told from a real zero — the panel keeps the\n // figure off the dashboard rather than drawing a consumed quota. An absent\n // flag (an older Host) stays unset and reads as \"assume reported\", so a\n // real balance is not lost cross-version. A PRESENT value must still be a\n // boolean, so a malformed frame is rejected here rather than coerced.\n if (credits.monthlyReported !== undefined) {\n parsed.monthlyReported = booleanField(credits, 'monthlyReported', 'credits.monthlyReported')\n }\n for (const flag of ['purchasedReported', 'freeReported'] as const) {\n if (credits[flag] !== undefined) parsed[flag] = booleanField(credits, flag, `credits.${flag}`)\n }\n // Absent means the endpoint reported no such window: the parsers return\n // undefined for an absent block, and an optional member is only set when\n // it was really there.\n const fiveHour = windowLimit(credits.fiveHour, 'credits.fiveHour')\n const weekly = windowLimit(credits.weekly, 'credits.weekly')\n if (fiveHour !== undefined) parsed.fiveHour = fiveHour\n if (weekly !== undefined) parsed.weekly = weekly\n report.credits = parsed\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)) {\n return { accounts: accounts.map(parseAccountUsage) }\n }\n return reject('accounts')\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 makeRemoteDescriptor<CommandCodeAccountsReport>(\n USAGE_REPORT_ENDPOINT,\n 'report',\n `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`,\n usageReportSchema,\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 // Every Host contribution must carry its reflection model. This hand-written\n // Remote deliberately has no generated reflection exports, so use the\n // official empty-model form rather than a cast that would leave registry\n // 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 model editors offer. */\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 * Minimum plan-tier key for this model (a `KNOWN_PLANS` value: `go`,\n * `goat`, `pro`, `provider`, `max`), or undefined for models outside the\n * snapshot. The settings page groups the model-editor dropdowns under\n * tier headings from this — the browser cannot import the Host's\n * capability snapshot, so the Host stamps it per entry.\n */\n tier?: string\n /**\n * Per-model MONTHLY allowance in USD: how much of the plan's monthly credit\n * pool this one model may draw, already resolved by the Host against the\n * account pool's highest plan (the pricing page publishes an allowance for\n * Go, GOAT and Pro). Undefined when that plan has no published allowance\n * (Go, Provider, Max, Ultra) or when billing could not be read — the browser\n * shows nothing rather than guessing a neighbouring tier's figure.\n *\n * Deliberately a plain number and not the `{ go, goat, pro }` map: the bracket is\n * a Host decision that already depends on facts the browser does not hold, and\n * shipping both figures would invite a second, divergent rule here. Note this\n * is dollars per MONTH, unlike every rate in `CommandCodePriceTable`.\n */\n allowance?: number\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/**\n * The shared read/validate helpers for the model-catalog endpoint — a\n * separate instance so catalog boundary errors name `commandcode/models`,\n * not the report endpoint.\n */\nconst {\n record: catalogRecord,\n stringField: catalogString,\n numberField: catalogNumber,\n} = makeBoundaryValidator('commandcode/models result:')\n\n/** Parse one untrusted boundary value into a {@link CommandCodeCatalogModel}. */\nfunction parseCatalogModel(value: unknown): CommandCodeCatalogModel {\n const source = catalogRecord(value, 'model')\n const model: CommandCodeCatalogModel = {\n id: catalogString(source, 'id', 'model.id'),\n name: catalogString(source, 'name', 'model.name'),\n }\n // Tier is optional on the wire (older Hosts predate it); a present\n // non-string is a contract violation, not a silent drop.\n if (source.tier !== undefined) {\n model.tier = catalogString(source, 'tier', 'model.tier')\n }\n // Same rule for the allowance: an older Host simply omits it, but a Host that\n // sends a non-number has broken the contract.\n if (source.allowance !== undefined) {\n model.allowance = catalogNumber(source, 'allowance', 'model.allowance')\n }\n return model\n}\n\n/** Parse the wire result into a {@link CommandCodeCatalog}. */\nfunction parseCatalog(value: unknown): CommandCodeCatalog {\n const source = catalogRecord(value, 'result')\n const models = source.models\n if (Array.isArray(models)) {\n return { models: models.map(parseCatalogModel) }\n }\n throw new TypeError('commandcode/models result: invalid models')\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 makeRemoteDescriptor<CommandCodeCatalog>(\n MODELS_ENDPOINT,\n 'models',\n `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`,\n modelsSchema,\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// ---------------------------------------------------------------------------\n// Model price table Remote (`commandcode/prices`)\n// ---------------------------------------------------------------------------\n\n/**\n * One model's per-token rates, in USD per 1,000,000 tokens — the unit the\n * official pricing page publishes in.\n */\nexport interface CommandCodeModelRates {\n /** Uncached (billed) input tokens. */\n inputCost: number\n /** Completion tokens. */\n outputCost: number\n /** Input tokens served from the provider's cache. */\n cacheReadCost: number\n /**\n * Input tokens written into the provider's cache. Present for a minority of\n * models — the page publishes no cache-write rate for the rest, whose\n * cache-write tokens are therefore UNPRICED. Do not substitute a multiple of\n * the input rate for a missing value.\n */\n cacheWriteCost?: number\n}\n\n/** One whole-request context band; maxContext is inclusive, absent on the last band. */\nexport interface CommandCodeContextTier extends CommandCodeModelRates {\n maxContext?: number\n}\n\n/** One model's rates plus the peak-hour override for time-of-day models. */\nexport interface CommandCodeModelPrice extends CommandCodeModelRates {\n /**\n * Lookup key: the catalog model id when a catalog model maps to this row,\n * otherwise the pricing page's own slug. A session reports catalog ids, so\n * this is the primary key the browser looks up by.\n */\n id: string\n /** The pricing page's slug for this row — the secondary lookup key. */\n slug: string\n /**\n * Rates charged inside the peak windows. The row's own top-level rates are\n * the off-peak rates, so a row WITH this block is time-of-day priced and a\n * row without it is flat-priced.\n */\n peak?: CommandCodeModelRates\n contextTiers?: CommandCodeContextTier[]\n /**\n * Whether the model costs nothing on every plan right now (a free deal or a\n * `:free` catalog variant). Served explicitly at zero rates so a surface can\n * say \"free\" rather than showing nothing.\n */\n free?: boolean\n}\n\n/** The price-table Remote result: every known model's rates. */\nexport interface CommandCodePriceTable {\n /**\n * Every priced model, keyed by {@link CommandCodeModelPrice.id} (catalog id\n * first, pricing slug as the fallback) and carrying its slug as a second\n * lookup key. A model absent from this list has no known price and must\n * render no cost at all rather than a guess.\n */\n models: CommandCodeModelPrice[]\n /**\n * Peak-pricing windows as `[startHour, endHour)` in UTC, end-exclusive,\n * applying Monday–Friday only. Shipped with the table so the browser prices\n * against the Host snapshot's schedule instead of restating it.\n */\n peakHours: Array<[number, number]>\n}\n\n/** Canonical `<namespace>/<method>` endpoint of the price-table Remote. */\nexport const PRICES_ENDPOINT = 'commandcode/prices'\n\n/**\n * The shared read/validate helpers for the price-table endpoint — its own\n * instance so price boundary errors name `commandcode/prices`.\n */\nconst {\n reject: priceReject,\n record: priceRecord,\n stringField: priceString,\n numberField: priceNumber,\n booleanField: priceBoolean,\n} = makeBoundaryValidator('commandcode/prices result:')\n\n/** Parse one rate block (`rates`, or a model's `peak` override). */\nfunction parseRates(source: Record<string, unknown>, field: string): CommandCodeModelRates {\n const rates: CommandCodeModelRates = {\n inputCost: priceNumber(source, 'inputCost', `${field}.inputCost`),\n outputCost: priceNumber(source, 'outputCost', `${field}.outputCost`),\n cacheReadCost: priceNumber(source, 'cacheReadCost', `${field}.cacheReadCost`),\n }\n // Optional on the wire: a present non-number is a contract violation rather\n // than a silent zero (only a minority of models publish a cache-write rate).\n if (source.cacheWriteCost !== undefined) {\n rates.cacheWriteCost = priceNumber(source, 'cacheWriteCost', `${field}.cacheWriteCost`)\n }\n return rates\n}\n\n/** Parse one untrusted boundary value into a {@link CommandCodeModelPrice}. */\nfunction parseModelPrice(value: unknown): CommandCodeModelPrice {\n const source = priceRecord(value, 'model')\n const price: CommandCodeModelPrice = {\n id: priceString(source, 'id', 'model.id'),\n slug: priceString(source, 'slug', 'model.slug'),\n ...parseRates(source, 'model'),\n }\n if (source.peak !== undefined) price.peak = parseRates(priceRecord(source.peak, 'model.peak'), 'model.peak')\n if (source.contextTiers !== undefined) {\n if (!Array.isArray(source.contextTiers) || source.contextTiers.length === 0) priceReject('contextTiers')\n let previous = 0\n price.contextTiers = (source.contextTiers as unknown[]).map((value, index, tiers) => {\n const tier = priceRecord(value, 'contextTier')\n const out: CommandCodeContextTier = parseRates(tier, 'contextTier')\n if (tier.maxContext !== undefined) {\n const max = priceNumber(tier, 'maxContext', 'contextTier.maxContext')\n if (!Number.isSafeInteger(max) || max <= previous || index === tiers.length - 1) priceReject('contextTier.maxContext')\n previous = max\n out.maxContext = max\n } else if (index !== tiers.length - 1) priceReject('contextTier.maxContext')\n return out\n })\n }\n if (source.free !== undefined) price.free = priceBoolean(source, 'free', 'model.free')\n return price\n}\n\n/** Parse the wire result into a {@link CommandCodePriceTable}. */\nfunction parsePriceTable(value: unknown): CommandCodePriceTable {\n const source = priceRecord(value, 'result')\n const models = source.models\n if (!Array.isArray(models)) priceReject('models')\n const peakHours = source.peakHours\n if (!Array.isArray(peakHours)) priceReject('peakHours')\n return {\n models: (models as unknown[]).map(parseModelPrice),\n peakHours: (peakHours as unknown[]).map((window) => {\n if (!Array.isArray(window) || window.length !== 2) priceReject('peakHours[]')\n const [start, end] = window as [unknown, unknown]\n if (typeof start !== 'number' || typeof end !== 'number') priceReject('peakHours[]')\n return [start, end] as [number, number]\n }),\n }\n}\n\n/** The strict result codec for the price-table Remote. */\nexport const pricesSchema: TypertSchema<CommandCodePriceTable> = {\n parse: parsePriceTable,\n}\n\n/**\n * The price-table invocation descriptor, sharing the same `commandcodeUsage`\n * service and `commandcode` namespace as the report and catalog endpoints.\n */\nexport const PRICES_DESCRIPTOR: InvocationDescriptor =\n makeRemoteDescriptor<CommandCodePriceTable>(\n PRICES_ENDPOINT,\n 'prices',\n `${USAGE_REMOTE_PACKAGE}#CommandCodePriceTable`,\n pricesSchema,\n )\n\n/** The Client-face contribution for the price-table endpoint. */\nexport const PRICES_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [PRICES_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 instead of pasting an API key. The loopback server must live\n * in the Host half — it binds a local port and receives the key — so the page\n * drives it through the 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 {\n makeBoundaryValidator,\n makeRemoteDescriptor,\n makeStrictCodec,\n REMOTE_PACKAGE,\n} from './wire-shared.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/** The shared read/validate helpers, prefixed with the login endpoint so\n * rejection messages name the offending boundary. */\nconst { reject, record, stringField } =\n makeBoundaryValidator('commandcode/login result:')\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 const source = record(value, 'status')\n const state = source.state\n if (state === 'idle' || state === 'waiting' || state === 'success' || state === 'failed') {\n const status: CommandCodeLoginStatus = { state }\n if (source.authUrl !== undefined) {\n status.authUrl = stringField(source, 'authUrl', 'authUrl')\n }\n if (source.userName !== undefined) {\n status.userName = stringField(source, 'userName', 'userName')\n }\n if (source.keyName !== undefined) {\n status.keyName = stringField(source, 'keyName', 'keyName')\n }\n if (source.reason !== undefined) {\n const reason = source.reason\n if (typeof reason === 'string' && REASONS.includes(reason as CommandCodeLoginFailureReason)) {\n status.reason = reason as CommandCodeLoginFailureReason\n } else {\n reject('reason')\n }\n }\n if (source.message !== undefined) {\n status.message = stringField(source, 'message', 'message')\n }\n return status\n }\n return reject('state')\n}\n\n/** The strict result codec shared by all three login endpoints. */\nexport const loginStatusSchema: TypertSchema<CommandCodeLoginStatus> = {\n parse: parseLoginStatus,\n}\n\n/** Optional account target; the Host still checks it against saved slots. */\nconst loginTargetSchema: TypertSchema<string | undefined> = {\n parse(value: unknown): string | undefined {\n if (value === undefined || typeof value === 'string') return value\n return reject('targetRef')\n },\n}\n\n/** Build one login invocation descriptor. Only begin accepts an account ref. */\nfunction loginDescriptor(endpoint: string, method: string): InvocationDescriptor {\n const descriptor = makeRemoteDescriptor<CommandCodeLoginStatus>(\n endpoint,\n method,\n `${REMOTE_PACKAGE}#CommandCodeLoginStatus`,\n loginStatusSchema,\n )\n return method === 'loginBegin'\n ? {\n ...descriptor,\n parameters: [{\n name: 'targetRef', wire: 'targetRef', source: 'json',\n codec: makeStrictCodec(`${REMOTE_PACKAGE}#CommandCodeLoginTargetRef`, loginTargetSchema),\n acceptsUndefined: true,\n }],\n }\n : descriptor\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: 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: REMOTE_PACKAGE,\n descriptors: LOGIN_DESCRIPTORS,\n}\n","/** 账号开通的双方使用契约。状态和恢复记录不携带密钥,密钥只出现在手动开通输入。 */\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\nimport { makeBoundaryValidator, makeRemoteDescriptor, makeStrictCodec, REMOTE_PACKAGE } from './wire-shared.ts'\n\nexport interface EnrollmentInput {\n id: string\n pageId: string\n mode: 'browser' | 'manual'\n label: string\n /** 用户未填写名称时,允许使用浏览器登录返回的账号名。 */\n automaticName: boolean\n key?: string\n}\nexport type EnrollmentPhase = 'creating' | 'waiting' | 'writing' | 'naming' | 'finished' | 'cancelling' | 'cancelled' | 'failed' | 'cleanup-needed'\nexport interface EnrollmentState {\n id: string\n ref: string\n phase: EnrollmentPhase\n message: string\n authUrl?: string\n suggestedName?: string\n}\n/** 配置中的恢复日志:先登记,再写凭据;只保留引用与阶段,不保留密钥或连接身份。 */\nexport interface EnrollmentRecord {\n id: string\n ref: string\n phase: 'pending' | 'naming' | 'cleanup'\n label: string\n}\nconst guard = makeBoundaryValidator('commandcode/enrollment')\nconst phases: readonly EnrollmentPhase[] = ['creating', 'waiting', 'writing', 'naming', 'finished', 'cancelling', 'cancelled', 'failed', 'cleanup-needed']\nexport function parseEnrollmentState(value: unknown): EnrollmentState {\n const source = guard.record(value, 'state')\n const phase = source.phase\n if (!phases.includes(phase as EnrollmentPhase)) return guard.reject('phase')\n const state: EnrollmentState = {\n id: guard.stringField(source, 'id', 'id'), ref: guard.stringField(source, 'ref', 'ref'),\n phase: phase as EnrollmentPhase, message: guard.stringField(source, 'message', 'message'),\n }\n for (const field of ['authUrl', 'suggestedName'] as const) {\n if (source[field] !== undefined) state[field] = guard.stringField(source, field, field)\n }\n return state\n}\nexport function parseEnrollmentInput(value: unknown): EnrollmentInput {\n const source = guard.record(value, 'input')\n const id = guard.stringField(source, 'id', 'id')\n if (!/^[a-zA-Z0-9-]{16,80}$/.test(id)) return guard.reject('id')\n if (source.mode !== 'browser' && source.mode !== 'manual') return guard.reject('mode')\n const input: EnrollmentInput = {\n id, pageId: parsePage(source).pageId, mode: source.mode, label: guard.stringField(source, 'label', 'label').trim(),\n automaticName: guard.booleanField(source, 'automaticName', 'automaticName'),\n }\n if (!input.label || input.label.length > 200) return guard.reject('label')\n if (input.mode === 'manual') {\n input.key = guard.stringField(source, 'key', 'key').trim()\n if (!input.key) return guard.reject('key')\n } else if (source.key !== undefined) return guard.reject('key')\n return input\n}\nexport interface EnrollmentPage { pageId: string }\nfunction parsePage(value: unknown): EnrollmentPage {\n const source = guard.record(value, 'page')\n const pageId = guard.stringField(source, 'pageId', 'pageId')\n if (!/^[a-zA-Z0-9-]{16,80}$/.test(pageId)) return guard.reject('pageId')\n return { pageId }\n}\nexport interface EnrollmentAction extends EnrollmentPage { id: string; name?: string }\nconst actionSchema: TypertSchema<EnrollmentAction> = {\n parse(value) {\n const source = guard.record(value, 'action')\n const action: EnrollmentAction = { id: guard.stringField(source, 'id', 'id'), ...parsePage(source) }\n if (!/^[a-zA-Z0-9-]{16,80}$/.test(action.id)) return guard.reject('id')\n if (source.name !== undefined) action.name = guard.stringField(source, 'name', 'name').trim()\n if (action.name !== undefined && (!action.name || action.name.length > 200)) return guard.reject('name')\n return action\n },\n}\nconst stateSchema = { parse: parseEnrollmentState }\nconst listSchema: TypertSchema<EnrollmentState[]> = {\n parse(value) { return Array.isArray(value) ? value.map(parseEnrollmentState) : guard.reject('list') },\n}\nexport const ENROLLMENT_DESCRIPTORS: readonly InvocationDescriptor[] = [\n ...['enrollmentBegin', 'enrollmentStatus', 'enrollmentCancel', 'enrollmentName', 'enrollmentRetry'].map((method) => ({\n ...makeRemoteDescriptor(`commandcode/${method}`, method, `${REMOTE_PACKAGE}#EnrollmentState`, stateSchema),\n parameters: [{ name: 'input', wire: 'input', source: 'json' as const,\n codec: makeStrictCodec(`${REMOTE_PACKAGE}#${method}Input`, method === 'enrollmentBegin' ? { parse: parseEnrollmentInput } : actionSchema) }],\n })),\n { ...makeRemoteDescriptor('commandcode/enrollmentPending', 'enrollmentPending', `${REMOTE_PACKAGE}#EnrollmentStateList`, listSchema),\n parameters: [{ name: 'input', wire: 'input', source: 'json', codec: makeStrictCodec(`${REMOTE_PACKAGE}#EnrollmentPage`, { parse: parsePage }) }] },\n { ...makeRemoteDescriptor('commandcode/enrollmentWatch', 'enrollmentWatch', `${REMOTE_PACKAGE}#EnrollmentReady`, {\n parse(value: unknown) { return value === true ? true : guard.reject('ready') },\n }), mode: 'stream',\n parameters: [{ name: 'input', wire: 'input', source: 'json', codec: makeStrictCodec(`${REMOTE_PACKAGE}#EnrollmentPage`, { parse: parsePage }) }] },\n]\nexport const ENROLLMENT_REMOTE_CONTRIBUTION: TypertRemoteContribution = { package: REMOTE_PACKAGE, descriptors: ENROLLMENT_DESCRIPTORS }\n","/** 每次设置页挂载独立拥有一个开通控制器;共享设置/用量控制器仍保持插件生命周期。 */\nimport type { RemoteResult, RemoteStreamHandle } from '@deepseek-ai/dsh-typert-protocol'\nimport type { EnrollmentAction, EnrollmentInput, EnrollmentPage, EnrollmentState } from '../enrollment-wire.ts'\nimport { createSnapshotStore } from './snapshot-store.ts'\nimport { openLoginPage } from './login-page.ts'\n\nexport interface EnrollmentRemote {\n enrollmentBegin(input: EnrollmentInput): Promise<RemoteResult<EnrollmentState>>\n enrollmentStatus(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentCancel(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentName(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentRetry(input: EnrollmentAction): Promise<RemoteResult<EnrollmentState>>\n enrollmentPending(input: EnrollmentPage): Promise<RemoteResult<EnrollmentState[]>>\n enrollmentWatch(input: EnrollmentPage): RemoteStreamHandle<boolean, never>\n}\ndeclare module '@deepseek-ai/dsh-typert-protocol' {\n interface TypertRemoteMap {\n 'commandcode/enrollmentBegin': EnrollmentRemote['enrollmentBegin']\n 'commandcode/enrollmentStatus': EnrollmentRemote['enrollmentStatus']\n 'commandcode/enrollmentCancel': EnrollmentRemote['enrollmentCancel']\n 'commandcode/enrollmentName': EnrollmentRemote['enrollmentName']\n 'commandcode/enrollmentRetry': EnrollmentRemote['enrollmentRetry']\n 'commandcode/enrollmentPending': EnrollmentRemote['enrollmentPending']\n 'commandcode/enrollmentWatch': EnrollmentRemote['enrollmentWatch']\n }\n}\nexport interface EnrollmentPageState { active: EnrollmentState | undefined; pending: EnrollmentState[]; error: string | undefined }\nconst live = (state: EnrollmentState) => ['creating', 'waiting', 'writing', 'cancelling'].includes(state.phase)\nexport class AccountEnrollmentController {\n readonly store = createSnapshotStore<EnrollmentPageState>({ active: undefined, pending: [], error: undefined })\n private id: string | undefined\n private timer: ReturnType<typeof setTimeout> | undefined\n private disposed = false\n private pageId: string\n private watch: RemoteStreamHandle<boolean, never> | undefined\n private ready: Promise<void> | undefined\n private openedPage = false\n constructor(private readonly remote: () => EnrollmentRemote, private readonly changed: () => void, private readonly pollMs = 750, private readonly newId = () => crypto.randomUUID(), private readonly openPage = openLoginPage) { this.pageId = newId() }\n /** 支持 React 开发模式的挂载检查;每次挂载仍重新读取宿主事实。 */\n activate(): void { if (this.disposed) this.pageId = this.newId(); this.disposed = false; void this.refresh() }\n reset(): void { if (!this.id) this.store.set({ ...this.store.getSnapshot(), active: undefined, error: undefined }) }\n async refresh(): Promise<void> {\n try {\n const result = await this.remote().enrollmentPending({ pageId: this.pageId })\n if (result.ok && !this.disposed) this.store.set({ ...this.store.getSnapshot(), pending: result.value })\n } catch { /* 旧宿主或连接暂不可用,开始开通时再提供明确提示。 */ }\n }\n async begin(input: Omit<EnrollmentInput, 'id' | 'pageId'>): Promise<void> {\n if (this.id || this.disposed) return\n const id = this.newId()\n const pageId = this.pageId\n this.id = id\n this.openedPage = false\n this.store.set({ ...this.store.getSnapshot(), error: undefined, active: { id, ref: '', phase: 'creating', message: '正在创建账号' } })\n try {\n await this.ensureWatch()\n if (this.disposed || this.id !== id || this.pageId !== pageId) return\n const result = await this.remote().enrollmentBegin({ ...input, id, pageId })\n if (this.disposed || this.id !== id) {\n // begin 回复晚到时再取消一次,覆盖传输层乱序或早到的取消失败。\n await this.remote().enrollmentCancel({ id, pageId })\n return\n }\n this.receive(id, result)\n } catch {\n if (this.id === id) this.cancel()\n this.failure('账号开通请求失败,请检查连接后重试')\n }\n }\n /** 页面可立即离开;宿主仍等待写入和补偿收尾。 */\n cancel(): void {\n const id = this.id\n const pageId = this.pageId\n this.id = undefined\n this.stopTimer()\n if (!this.disposed) this.store.set({ ...this.store.getSnapshot(), active: undefined })\n if (id) void Promise.resolve().then(() => this.remote().enrollmentCancel({ id, pageId })).then(() => { this.changed(); void this.refresh() }, () => this.failure('取消请求未确认,重新连接后请检查未完成记录'))\n }\n async name(name?: string): Promise<void> {\n const id = this.id\n if (!id) return\n try { this.receive(id, await this.remote().enrollmentName({ id, pageId: this.pageId, ...(name ? { name } : {}) })) }\n catch { this.failure('名称保存失败,请重试或接受已有名称') }\n }\n async recover(record: EnrollmentState, name?: string): Promise<void> {\n try {\n const result = await this.remote().enrollmentRetry({ id: record.id, pageId: this.pageId, ...(name ? { name } : {}) })\n if (!result.ok) this.failure('收尾未完成,请重试')\n else if (!this.disposed && this.store.getSnapshot().active?.id === record.id) {\n this.store.set({ ...this.store.getSnapshot(), active: result.value, error: undefined })\n }\n this.changed()\n await this.refresh()\n } catch { this.failure('收尾请求失败,请检查连接后重试') }\n }\n dispose(): void { this.disposed = true; this.cancel(); this.watch?.dispose(); this.watch = undefined; this.ready = undefined }\n private ensureWatch(): Promise<void> {\n if (this.ready) return this.ready\n const handle = this.remote().enrollmentWatch({ pageId: this.pageId })\n const iterator = handle[Symbol.asyncIterator]()\n this.watch = handle\n this.ready = iterator.next().then((first) => {\n if (first.done || first.value !== true || this.watch !== handle) throw new Error('页面观察流未建立')\n // 不重连原观察流;载体断开就是该页面过程结束,由宿主补偿。\n void (async () => {\n try { while (!(await iterator.next()).done) { /* 保持调用直到载体结束。 */ } }\n catch { /* 终止统一在 finally 中处理。 */ }\n finally {\n if (this.watch === handle && !this.disposed) {\n this.watch = undefined\n this.ready = undefined\n this.cancel()\n this.failure('开通连接已断开,宿主正在收尾;重连后请检查未完成记录')\n }\n }\n })()\n }).catch((error: unknown) => { handle.dispose(); if (this.watch === handle) { this.watch = undefined; this.ready = undefined }; throw error })\n return this.ready\n }\n private receive(id: string, result: RemoteResult<EnrollmentState>): void {\n if (this.disposed || this.id !== id) return\n if (!result.ok) { this.failure('宿主无法完成账号开通,请检查连接与写入权限'); return }\n const active = result.value\n // 地址可能由后续轮询返回;只接受仍属于当前页面过程的地址,且每次过程只打开一次。\n if (active.phase === 'waiting' && active.authUrl && !this.openedPage) {\n this.openedPage = true\n this.openPage(active.authUrl)\n }\n this.store.set({ ...this.store.getSnapshot(), active, error: undefined })\n if (live(active)) {\n this.stopTimer()\n this.timer = setTimeout(() => { void this.poll(id) }, this.pollMs)\n } else {\n this.changed()\n void this.refresh()\n if (active.phase !== 'naming') this.id = undefined\n }\n }\n private async poll(id: string): Promise<void> {\n if (this.disposed || this.id !== id) return\n try { this.receive(id, await this.remote().enrollmentStatus({ id, pageId: this.pageId })) }\n catch {\n this.failure('开通状态暂不可用,正在等待重新连接')\n if (!this.disposed && this.id === id) this.timer = setTimeout(() => { void this.poll(id) }, this.pollMs)\n }\n }\n private failure(message: string): void { if (!this.disposed) this.store.set({ ...this.store.getSnapshot(), error: message }) }\n private stopTimer(): void { if (this.timer) clearTimeout(this.timer); this.timer = undefined }\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 'settings.commandcode': SettingsCommandCodeKey\n }\n}\n\n/** Dictionary keys of the Command Code settings page. */\nexport type SettingsCommandCodeKey =\n | 'openAnalytics'\n | 'nav'\n | 'title'\n | 'intro'\n | 'apiKey'\n | 'apiKeyHint'\n | 'apiKeySet'\n | 'apiKeyUnset'\n | 'apiKeyLocked'\n | 'apiBase'\n | 'apiBaseHint'\n | 'requestTimeoutMs'\n | 'requestTimeoutMsHint'\n | 'streamIdleTimeoutMs'\n | 'streamIdleTimeoutMsHint'\n | 'transportMaxRetries'\n | 'transportMaxRetriesHint'\n | 'offloadSeenImagesForCache'\n | 'offloadSeenImagesForCacheHint'\n | 'advancedSettings'\n | 'advancedSettingsHint'\n | 'advancedOverriddenOne'\n | 'advancedOverriddenMany'\n | 'advancedInvalid'\n | 'filterModelsByPlan'\n | 'filterModelsByPlanHint'\n | 'webSearch'\n | 'webSearchHint'\n | 'showSidebarQuota'\n | 'showSidebarQuotaHint'\n | 'zdr'\n | 'zdrHint'\n | 'accountsTitle'\n | 'accountsHint'\n | 'accountAdd'\n | 'accountDefault'\n | 'modelSearchPlaceholder'\n | 'modelSearchEmpty'\n | 'modelStale'\n | 'visibleModelsTitle'\n | 'visibleModelsHint'\n | 'visibleModelsPick'\n | 'visibleModelsCount'\n | 'visibleModelsShowAll'\n | 'visibleModelsStaleHint'\n | 'visibleModelsCleanStale'\n | 'overridden'\n | 'reset'\n | 'invalidNumber'\n | 'numberTooSmall'\n | 'numberTooLarge'\n | 'durationTooSmall'\n | 'durationTooLarge'\n | 'durationInvalid'\n | 'readOnly'\n | 'save'\n | 'saving'\n | 'saved'\n | 'saveFailed'\n | 'writeConflict'\n | 'writeConfigUnconfirmed'\n | 'writeConfigSaved'\n | 'writeKeyNotIssued'\n | 'writeKeyUnconfirmed'\n | 'writeKeyConfirmed'\n | 'writeTargetBefore'\n | 'writeTargetAfter'\n | 'writeClosed'\n | 'writeCleanupPending'\n | 'writeRefreshFailed'\n | 'writeRefreshRetry'\n | 'writeStateUnknown'\n | 'unsavedChanges'\n | 'saveInvalid'\n | 'discard'\n | 'cancel'\n | 'show'\n | 'hide'\n | 'usageRefresh'\n | 'usageRefreshing'\n | 'usageLoading'\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 | 'usageMonthlyLeft'\n | 'usageExceeded'\n | 'usageReset'\n | 'usagePartial'\n | 'usageKeyInvalid'\n | 'usageKeyInvalidHint'\n | 'usageServiceUnavailable'\n | 'usageServiceUnavailableHint'\n | 'usageNetworkError'\n | 'usageNetworkHint'\n | 'usageInvalidResponse'\n | 'usageInvalidResponseHint'\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 | 'accountsRotationHint'\n | 'accountModeAuto'\n | 'accountModePinned'\n | 'accountStatusPinned'\n | 'accountActions'\n | 'accountActionPin'\n | 'accountActionUnpin'\n | 'accountActionLogin'\n | 'accountActionKey'\n | 'accountActionRename'\n | 'accountActionClearKey'\n | 'accountActionRemove'\n | 'accountRemoveConfirm'\n | 'accountClearKeyConfirm'\n | 'accountConfirmRemove'\n | 'accountConfirmClear'\n | 'accountApply'\n | 'accountNoKeyHint'\n | 'accountAddHint'\n | 'accountAddLogin'\n | 'accountAddPaste'\n | 'accountAddConfirm'\n | 'accountNamePlaceholder'\n | 'accountNameN'\n | 'accountKeyPlaceholder'\n | 'accountOpFailed'\n | 'accountCleanupPending'\n | 'accountCleanupRetry'\n | 'accountModels'\n | 'accountModelsHint'\n | 'accountModelOwner'\n | 'modelPick'\n | 'modelCount'\n | 'modelAllowance'\n | 'modelAllowanceTitle'\n | 'modelCatalogFailed'\n | 'modelsTitle'\n | 'privacyTitle'\n | 'integrationsTitle'\n\nexport const zh: Record<SettingsCommandCodeKey, string> = {\n openAnalytics: '查看模型用量、成本与性能分析',\n nav: 'Command Code',\n title: 'Command Code',\n intro: '账户操作立即生效;其余设置修改后点击底部「保存」。API 密钥仅保存在本机凭据服务中,不会回显。',\n apiKey: 'API 密钥',\n apiKeyHint: '在 commandcode.ai 控制台创建。留空保存不会覆盖已存储的密钥。',\n apiKeySet: '已配置',\n apiKeyUnset: '未配置',\n apiKeyLocked: '密钥由只读来源提供',\n apiBase: 'API 地址',\n apiBaseHint: '默认 https://api.commandcode.ai,一般无需修改。',\n requestTimeoutMs: '请求超时(秒)',\n requestTimeoutMsHint: '等待响应首个字节的超时;默认 300 秒(与官方 CLI 一致)。Provider API 路由要等上游模型吐出第一个 token 才返回响应头,上游慢时仍可能不够;报超时时可按提示调高。',\n streamIdleTimeoutMs: '流空闲超时(秒)',\n streamIdleTimeoutMsHint: '生成流停滞多久视为断连;默认 300 秒(长思考模型可静默数分钟,默认值刻意放宽)。',\n transportMaxRetries: '网络失败重试次数',\n transportMaxRetriesHint: '连接失败时自动重试几次,默认 5(各次等待 0.5+1+2+4+8 秒,合计约 15 秒)。'\n + '超过后直接报错,不再按指数退避长时间等待;填 0 表示不重试。限流、5xx 等由服务端要求重试的失败不受此项影响。',\n offloadSeenImagesForCache: '已看过的图片不再重复发送',\n offloadSeenImagesForCacheHint: '仅 CLI 传输。模型看过图片并回复后,永久用文字占位替代旧图片,以减少新增图片时的缓存回退。模型如需重看旧图,必须重新读取文件或让用户重新附加。默认关闭。',\n advancedSettings: '高级设置',\n advancedSettingsHint: 'API 地址和网络参数,一般无需修改。',\n advancedOverriddenOne: '已自定义 1 项',\n advancedOverriddenMany: '已自定义 {count} 项',\n advancedInvalid: '高级设置中有未填好的数字,请展开修正后再保存。',\n filterModelsByPlan: '隐藏套餐外模型',\n filterModelsByPlanHint: '只显示套餐内模型;按需余额账户仍显示全部。',\n webSearch: '用 Command Code 承载联网搜索',\n webSearchHint: '使用同一密钥承载 dsh 的 web_search;关闭后恢复原搜索后端。',\n showSidebarQuota: '在侧边栏显示额度卡片',\n showSidebarQuotaHint: '在侧边栏底部显示套餐与额度卡片,点击可打开完整仪表盘。默认关闭,关闭时不会为它后台刷新用量。',\n zdr: '零数据保留(ZDR)',\n zdrHint: '仅使用不留存、不训练的上游;可用模型可能更少且价格通常更高。',\n accountsTitle: '账户',\n accountsHint: '账户操作立即生效,无需保存。可以添加多个账户:当前账户达到用量限额或密钥失效时,请求会自动切换到下一个。',\n accountAdd: '添加账户',\n accountDefault: '默认账户',\n modelSearchPlaceholder: '搜索模型…',\n modelSearchEmpty: '没有匹配的模型。',\n modelStale: '已下架',\n modelAllowance: '${amount}/月',\n modelAllowanceTitle: '该模型每月可用的额度(美元)。套餐内所有模型共用同一个月度额度池,这不是额外赠送的额度。',\n visibleModelsTitle: '模型白名单',\n visibleModelsHint:\n '勾选要保留的模型,模型选择器就只列出这些;一个都不勾选时则显示全部模型。'\n + '这里显示网页与终端合并后的有效选择;保存后两端一致,套餐权限仍独立过滤。',\n visibleModelsPick: '选择要保留的模型…',\n visibleModelsCount: '已选 {count} 个模型',\n visibleModelsShowAll: '显示全部',\n visibleModelsStaleHint: '有 {count} 个已选模型在目录中找不到了(可能已下架),不影响其他模型;可清理或保留。',\n visibleModelsCleanStale: '清理失效({count})',\n overridden: '已覆盖',\n reset: '重置',\n invalidNumber: '无效数字',\n numberTooSmall: '重试次数不能小于 0',\n numberTooLarge: '重试次数不能大于 50',\n durationTooSmall: '不能小于 0.001 秒(1 毫秒)',\n durationTooLarge: '不能大于 3600 秒',\n durationInvalid: '请输入秒数,最多保留三位小数',\n readOnly: '当前配置为只读。',\n save: '保存',\n saving: '保存中',\n saved: '设置已保存',\n saveFailed: '保存失败,请重试。',\n writeConflict: '待提交字段已被其他操作修改,配置未写入;请核对后再保存。',\n writeConfigUnconfirmed: '配置提交未获确认;密钥未写入,请核对宿主状态后重试。',\n writeConfigSaved: '配置已保存。',\n writeKeyNotIssued: '密钥操作尚未发出;请核对后重试。',\n writeKeyUnconfirmed: '密钥操作未获确认;请核对后手动重试。',\n writeKeyConfirmed: '原引用的密钥操作已获确认。',\n writeTargetBefore: '默认密钥引用已变化,本次密钥操作未发出;请核对当前目标。',\n writeTargetAfter: '原引用的密钥操作已发出,默认引用随后变化;请核对两个引用。',\n writeClosed: '客户端已销毁,未发出的操作已停止;已确认的修改保留。',\n writeCleanupPending: '账号修改已确认,清理记录尚未收束,请重试清理。',\n writeRefreshFailed: '密钥状态刷新失败;已获确认的写入仍有效。',\n writeRefreshRetry: '仅刷新密钥状态',\n writeStateUnknown: '密钥状态尚未确认',\n unsavedChanges: '有未保存的更改',\n saveInvalid: '有字段填写不正确,修正后才能保存',\n discard: '放弃',\n cancel: '取消',\n show: '显示',\n hide: '隐藏',\n usageRefresh: '刷新',\n usageRefreshing: '刷新中…',\n usageLoading: '正在获取账户用量…',\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 usageMonthlyLeft: '月额度剩余',\n usageExceeded: '已超限',\n usageReset: '重置于',\n usagePartial: '部分端点数据不可用',\n usageKeyInvalid: 'API 密钥无效或已过期',\n usageKeyInvalidHint: '服务端拒绝了全部请求(401)。请检查该账户配置的密钥,或到 commandcode.ai 控制台重新生成。',\n usageServiceUnavailable: 'Command Code 服务暂时不可用',\n usageServiceUnavailableHint: '服务端返回了错误(5xx),稍后点击刷新重试。',\n usageNetworkError: '无法连接 Command Code 服务',\n usageNetworkHint: '所有请求都没有到达服务端。请检查网络连接或 API 地址设置。',\n usageInvalidResponse: 'Command Code 响应无法读取',\n usageInvalidResponseHint: '已收到响应,但正文读取或解析失败。下方详情可区分读取超时、中断与格式异常;可先点击刷新重试。',\n usageUpdated: '更新于',\n usagePeriodEnd: '账期截止',\n usageActive: '当前使用',\n usageCooldown: '限额冷却中',\n usageInvalidKey: '密钥无效',\n usageUnconfigured: '该账户尚未配置 API 密钥。',\n updateAvailable: '可更新',\n updateHint: '已发布新版本,点击查看发布说明;更新插件后刷新本页,提示会自动消失。',\n loginTitle: '通过官方登录获取密钥',\n loginHintIdle: '也可通过网页授权自动获取并保存密钥。',\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 插件提供,正在等待设置页装配,稍后即可显示完整内容。',\n accountsRotationHint: '账户操作立即生效。当前账户达到用量限额或密钥失效时,请求会按列表顺序自动切换到下一个可用账户。',\n accountModeAuto: '使用方式:自动切换(按列表顺序)',\n accountModePinned: '使用方式:固定使用「{name}」,不可用时仍会自动切换',\n accountStatusPinned: '已固定',\n accountActions: '账户操作',\n accountActionPin: '固定使用此账户',\n accountActionUnpin: '恢复自动切换',\n accountActionLogin: '网页登录获取新密钥',\n accountActionKey: '粘贴新密钥',\n accountActionRename: '重命名',\n accountActionClearKey: '删除密钥',\n accountActionRemove: '移除账户',\n accountRemoveConfirm: '移除「{name}」?它保存的密钥和专用模型设置会一起删除。',\n accountClearKeyConfirm: '删除默认账户保存的密钥?之后会回退到环境变量或官方 CLI 的登录信息。',\n accountConfirmRemove: '移除',\n accountConfirmClear: '删除',\n accountApply: '确定',\n accountNoKeyHint: '还没有密钥:通过网页登录自动获取,或粘贴在 commandcode.ai 控制台创建的 API 密钥。',\n accountAddHint: '网页登录会打开 Command Code 授权页,授权完成后账户自动添加;也可以直接粘贴 API 密钥。',\n accountAddLogin: '网页登录',\n accountAddPaste: '粘贴密钥',\n accountAddConfirm: '添加',\n accountNamePlaceholder: '备注名(可选,网页登录时默认使用账户名)',\n accountNameN: '账户 {n}',\n accountKeyPlaceholder: '粘贴 API 密钥',\n accountOpFailed: '账户操作未能完成,请重试。',\n accountCleanupPending: '账户已移除,但有密钥尚未清理。可重试,不影响其他账户。',\n accountCleanupRetry: '重试清理密钥',\n accountModels: '专用模型',\n accountModelsHint: '选中的模型优先由此账户处理,此账户不可用时仍会自动切换。一个模型只属于一个账户,选中会把它从其他账户移过来。',\n accountModelOwner: '属于 {name}',\n modelPick: '选择模型…',\n modelCount: '已选 {count} 个模型',\n modelCatalogFailed: '模型目录获取失败,暂时无法选择模型;已保存的设置仍会生效。',\n modelsTitle: '模型',\n privacyTitle: '隐私与安全',\n integrationsTitle: '集成与显示',\n}\n\nexport const en: Record<SettingsCommandCodeKey, string> = {\n openAnalytics: 'View model usage, cost and performance',\n nav: 'Command Code',\n title: 'Command Code',\n intro: 'Account actions apply immediately; other settings are written by Save at the bottom. The API key stays in the local credential service and is never echoed.',\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 requestTimeoutMs: 'Request timeout (seconds)',\n requestTimeoutMsHint: 'Time to wait for the first response byte; default 300 s (the official CLI’s). The Provider API route withholds headers until the upstream model emits its first token, so a slow upstream can still outlast the default; raise it when a timeout message suggests it.',\n streamIdleTimeoutMs: 'Stream idle timeout (seconds)',\n streamIdleTimeoutMsHint: 'How long a stalled stream is treated as dead; default 300 s'\n + ' (deliberately generous — long-thinking models can stay silent for minutes).',\n transportMaxRetries: 'Transport retries',\n transportMaxRetriesHint: 'How many times a failed connection is retried automatically; default 5'\n + ' (waits of 0.5+1+2+4+8s, ~15s in total). After that the failure is reported instead of waiting'\n + ' on the exponential backoff. 0 disables the retries. Rate limits and 5xx answers keep their'\n + ' own, longer retry window.',\n offloadSeenImagesForCache: 'Stop replaying images already seen',\n offloadSeenImagesForCacheHint: 'CLI transport only. After this model responds to an image, durably replace older pixels with text to avoid cache rollback when another image arrives. To inspect an old image again, the model must reread its file or the user must attach it again. Off by default.',\n advancedSettings: 'Advanced',\n advancedSettingsHint: 'API base URL and network limits; usually leave as-is.',\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: 'Show only models in your plan; on-demand credit accounts still see the full catalog.',\n webSearch: 'Serve dsh web search with Command Code',\n webSearchHint: 'Use the same key for dsh web search; turning it off restores the previous backend.',\n showSidebarQuota: 'Show the quota card in the sidebar',\n showSidebarQuotaHint: 'Show a plan and quota card at the bottom of the sidebar that opens the full dashboard. Off by default; while off, no background usage refresh runs for it.',\n zdr: 'Zero data retention (ZDR)',\n zdrHint: 'Use only upstreams that retain no data and do not train on requests; availability and pricing may differ.',\n accountsTitle: 'Accounts',\n accountsHint: 'Account actions apply immediately, no save needed. Add more accounts and requests switch to the next one when the current account hits its usage limit or its key stops working.',\n accountAdd: 'Add account',\n accountDefault: 'Default account',\n modelSearchPlaceholder: 'Search models…',\n modelSearchEmpty: 'No matching models.',\n modelStale: 'Retired',\n modelAllowance: '${amount}/mo',\n modelAllowanceTitle: 'Monthly usage this model can draw, in USD. Every model shares one monthly pool — this is not extra credit on top of the plan.',\n visibleModelsTitle: 'Model allowlist',\n visibleModelsHint:\n 'Check the models you want to keep, and model pickers will list only those. '\n + 'If nothing is checked, every model is shown. After saving, the change '\n + 'applies in both web and terminal settings. This page shows their effective selection; plan access is filtered separately.',\n visibleModelsPick: 'Select models to keep…',\n visibleModelsCount: '{count} model(s) selected',\n visibleModelsShowAll: 'Show all',\n visibleModelsStaleHint: '{count} selected model(s) are no longer in the catalog (possibly retired);'\n + ' other models are unaffected. Clean them up or keep them.',\n visibleModelsCleanStale: 'Clean stale ({count})',\n overridden: 'Overridden',\n reset: 'Reset',\n invalidNumber: 'Invalid number',\n numberTooSmall: 'Retries must be at least 0',\n numberTooLarge: 'Retries must not exceed 50',\n durationTooSmall: 'Must be at least 0.001 seconds (1 ms)',\n durationTooLarge: 'Must not exceed 3600 seconds',\n durationInvalid: 'Enter seconds with at most three decimal places',\n readOnly: 'Settings are read-only.',\n save: 'Save',\n saving: 'Saving',\n saved: 'Settings saved',\n saveFailed: 'Save failed, please retry.',\n writeConflict: '待提交字段已被其他操作修改,配置未写入;请核对后再保存。',\n writeConfigUnconfirmed: '配置提交未获确认;密钥未写入,请核对宿主状态后重试。',\n writeConfigSaved: '配置已保存。',\n writeKeyNotIssued: '密钥操作尚未发出;请核对后重试。',\n writeKeyUnconfirmed: '密钥操作未获确认;请核对后手动重试。',\n writeKeyConfirmed: '原引用的密钥操作已获确认。',\n writeTargetBefore: '默认密钥引用已变化,本次密钥操作未发出;请核对当前目标。',\n writeTargetAfter: '原引用的密钥操作已发出,默认引用随后变化;请核对两个引用。',\n writeClosed: '客户端已销毁,未发出的操作已停止;已确认的修改保留。',\n writeCleanupPending: '账号修改已确认,清理记录尚未收束,请重试清理。',\n writeRefreshFailed: '密钥状态刷新失败;已获确认的写入仍有效。',\n writeRefreshRetry: '仅刷新密钥状态',\n writeStateUnknown: '密钥状态尚未确认',\n unsavedChanges: 'You have unsaved changes',\n saveInvalid: 'Fix the highlighted field before saving',\n discard: 'Discard',\n cancel: 'Cancel',\n show: 'Show',\n hide: 'Hide',\n usageRefresh: 'Refresh',\n usageRefreshing: 'Refreshing…',\n usageLoading: 'Fetching account usage…',\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 usageMonthlyLeft: 'Monthly left',\n usageExceeded: 'Exceeded',\n usageReset: 'Resets',\n usagePartial: 'Some endpoint data unavailable',\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 usageInvalidResponse: 'Could not read the Command Code response',\n usageInvalidResponseHint: 'Responses arrived, but reading or parsing their bodies failed. Details below distinguish timeouts, interrupted reads, and invalid formats. Try Refresh again.',\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: 'Alternatively, sign in to fetch and store a key automatically.',\n loginButton: 'Sign in to Command Code',\n loginStarting: 'Starting the local callback server…',\n loginWaiting: 'Waiting for authorization in your browser. If the page did not open automatically, use the authorization link.',\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 and is waiting for the settings page to finish assembling.',\n accountsRotationHint: 'Account actions apply immediately. When the current account hits its usage limit or its key stops working, requests switch to the next usable account in list order.',\n accountModeAuto: 'Mode: switch automatically (list order)',\n accountModePinned: 'Mode: pinned to \"{name}\", still switching when it is unavailable',\n accountStatusPinned: 'Pinned',\n accountActions: 'Account actions',\n accountActionPin: 'Pin this account',\n accountActionUnpin: 'Switch automatically',\n accountActionLogin: 'Sign in for a new key',\n accountActionKey: 'Paste a new key',\n accountActionRename: 'Rename',\n accountActionClearKey: 'Delete key',\n accountActionRemove: 'Remove account',\n accountRemoveConfirm: 'Remove \"{name}\"? Its stored key and dedicated models are deleted with it.',\n accountClearKeyConfirm: 'Delete the default account\\'s stored key? The provider then falls back to the environment or the official CLI sign-in.',\n accountConfirmRemove: 'Remove',\n accountConfirmClear: 'Delete',\n accountApply: 'Apply',\n accountNoKeyHint: 'No key yet: sign in through the browser, or paste an API key created in the commandcode.ai console.',\n accountAddHint: 'Sign-in opens the Command Code authorization page and adds the account once you approve; you can also paste an API key.',\n accountAddLogin: 'Sign in',\n accountAddPaste: 'Paste key',\n accountAddConfirm: 'Add',\n accountNamePlaceholder: 'Name (optional; sign-in uses the account name)',\n accountNameN: 'Account {n}',\n accountKeyPlaceholder: 'Paste an API key',\n accountOpFailed: 'The account change did not complete. Try again.',\n accountCleanupPending: 'The account was removed, but credential cleanup is still pending. Retry without affecting other accounts.',\n accountCleanupRetry: 'Retry credential cleanup',\n accountModels: 'Dedicated models',\n accountModelsHint: 'These models prefer this account and still switch when it is unavailable. A model belongs to one account; selecting it here moves it from any other.',\n accountModelOwner: 'on {name}',\n modelPick: 'Choose models…',\n modelCount: '{count} models selected',\n modelCatalogFailed: 'The model catalog could not be loaded; saved settings still apply.',\n modelsTitle: 'Models',\n privacyTitle: 'Privacy & security',\n integrationsTitle: 'Integrations & display',\n}\n\n/** 同一确认结果在设置页和模型卡使用相同措辞,不从 configured 推断写入结果。 */\nexport function settingsWriteNotice(\n result: import('./settings-write.ts').SettingsWriteResult | undefined,\n t: (key: SettingsCommandCodeKey) => string,\n): string {\n if (!result) return ''\n let key: SettingsCommandCodeKey | undefined\n if (result.issue === 'closed') key = 'writeClosed'\n else if (result.issue === 'target-changed') key = result.credential === 'not-issued' ? 'writeTargetBefore' : 'writeTargetAfter'\n else if (result.issue === 'cleanup-pending') key = 'writeCleanupPending'\n else if (result.config === 'conflict') key = 'writeConflict'\n else if (result.config === 'unconfirmed') key = 'writeConfigUnconfirmed'\n else if (result.credential === 'unconfirmed') key = 'writeKeyUnconfirmed'\n else if (result.credential === 'not-issued') key = 'writeKeyNotIssued'\n const messages = key ? [t(key)] : []\n if (result.issue === 'target-changed' && result.credentialRef) {\n messages.push(t(result.credential === 'confirmed' ? 'writeKeyConfirmed' : 'writeKeyUnconfirmed'))\n messages.push(`(原引用:${result.credentialRef})`)\n }\n if (key && result.config === 'confirmed' && result.issue !== 'cleanup-pending') messages.unshift(t('writeConfigSaved'))\n if (result.refreshFailed) messages.push(t('writeRefreshFailed'))\n return messages.join(' ')\n}\n","/** Shared plan-tier presentation facts; safe to inline into the browser bundle. */\n\nexport const PLAN_TIER_ORDER = ['go', 'goat', 'pro', 'provider', 'max'] as const\n\nexport const PLAN_LABELS: Readonly<Record<string, string>> = {\n go: 'Go',\n goat: 'GOAT',\n pro: 'Pro',\n provider: 'Provider',\n max: 'Max',\n}\n\nexport const PLAN_ORDER: Readonly<Record<string, number>> = Object.fromEntries(\n PLAN_TIER_ORDER.map((tier, index) => [tier, index]),\n)\n","/**\n * Model-select helpers for the settings page's model editors (browser half).\n *\n * The routing-rule editor and the visible-models filter both pick catalog models\n * through the same checkbox multi-select dropdown (`ModelMultiSelect` in\n * section.tsx). The dropdown's data shaping — search filtering, stale-id\n * detection, tier grouping — lives here, React-free, so node tests can drive\n * it directly.\n *\n * The shared tier module is dependency-free and inlined into the client bundle;\n * importing the Host's full capability snapshot here would bloat that bundle.\n *\n * @module dsh-commandcode-provider/model-select\n */\n\nimport { PLAN_LABELS } from '../plan-tiers.ts'\n\n/**\n * The dropdown section heading for a catalog model id, or undefined for\n * models outside the known plan tiers (unmapped models and stale ids render\n * unheaded). `knownPlans` is the Host-side `KNOWN_PLANS` table, threaded in\n * by the caller so this module stays dependency-free.\n */\nexport function tierHeadingFor(\n modelId: string,\n knownPlans: Readonly<Record<string, string>>,\n): string | undefined {\n const tier = knownPlans[modelId]\n if (tier === undefined) return undefined\n return PLAN_LABELS[tier] ?? tier\n}\n\n/** One selectable catalog model (mirrors `CatalogModelOption` in settings.ts). */\nexport interface SelectableModel {\n /** Catalog model id (e.g. `deepseek/deepseek-v4-pro`). */\n id: string\n name: string\n /**\n * Per-model monthly allowance in USD, already resolved by the Host. Passed\n * through untouched: this module renders it, it does not interpret it.\n */\n allowance?: number\n}\n\n/** One dropdown row: a live catalog model or a stale selection. */\nexport interface ModelSelectOption {\n /** Catalog model id (stale ids keep their raw id as the value). */\n value: string\n label: string\n /** True when the id is selected but the catalog no longer carries it. */\n stale: boolean\n /**\n * Per-model monthly allowance in USD. Only live catalog rows can carry one —\n * a stale id is no longer priced by the page, so there is nothing to show.\n */\n allowance?: number\n}\n\n/** One dropdown section: a plan-tier heading plus its rows. */\nexport interface ModelSelectGroup {\n /** Section heading, or undefined for models outside the known plan tiers. */\n heading: string | undefined\n /** Rows in this section, in picker order. */\n options: ModelSelectOption[]\n}\n\n/**\n * Whether `text` matches `query` as a case-insensitive substring over the\n * model id AND display name. An empty/blank query matches everything.\n */\nexport function matchesModelQuery(\n model: SelectableModel,\n query: string,\n): boolean {\n const needle = query.trim().toLowerCase()\n if (needle === '') return true\n return model.id.toLowerCase().includes(needle)\n || model.name.toLowerCase().includes(needle)\n}\n\n/**\n * Build the dropdown options: the catalog (already in picker order) plus any\n * selected ids the catalog no longer carries, flagged stale so a saved\n * selection never silently loses an entry. Stale rows survive a non-blank\n * {@link matchesModelQuery} search only while they match too, so a search for\n * a live model does not surface unrelated stale ids.\n */\nexport function buildModelSelectOptions(\n catalog: readonly SelectableModel[],\n selected: readonly string[],\n query = '',\n): ModelSelectOption[] {\n const catalogIds = new Set(catalog.map((model) => model.id))\n const options = catalog\n .filter((model) => matchesModelQuery(model, query))\n .map((model) => ({\n value: model.id,\n label: model.name,\n stale: false,\n ...(model.allowance === undefined ? {} : { allowance: model.allowance }),\n }))\n // Dedupe defensively (order-preserving): hand-edited settings can repeat\n // or blank an id, and duplicate Menu ids would confuse selection state.\n const seen = new Set(catalogIds)\n for (const id of selected) {\n if (id === '' || seen.has(id)) continue\n seen.add(id)\n if (catalogIds.has(id)) continue\n if (!matchesModelQuery({ id, name: id }, query)) continue\n options.push({ value: id, label: id, stale: true })\n }\n return options\n}\n\n/**\n * Group dropdown options under plan-tier headings (`tierOf` maps a model id to\n * its heading, or undefined for unmapped models — see {@link tierHeadingFor}).\n * Live rows keep their relative order and repeats merge, so a catalog\n * interleaving two tiers still renders one section per tier.\n */\nexport function groupModelSelectOptions(\n options: readonly ModelSelectOption[],\n tierOf: (modelId: string) => string | undefined,\n): ModelSelectGroup[] {\n const groups: ModelSelectGroup[] = []\n const byHeading = new Map<string | undefined, ModelSelectGroup>()\n for (const option of options) {\n // Stale ids always render unheaded (their tier is unknowable); unmapped\n // live rows join the same trailing group so `heading: undefined`\n // appears at most once.\n const heading = option.stale ? undefined : tierOf(option.value)\n let group = byHeading.get(heading)\n if (group === undefined) {\n group = { heading, options: [] }\n byHeading.set(heading, group)\n groups.push(group)\n }\n group.options.push(option)\n }\n return groups\n}\n\n/**\n * Toggle one model id in a selection: remove it when present, append it\n * when absent (append keeps catalog order irrelevant — the picker re-sorts\n * by plan tier on render).\n */\nexport function toggleModelSelection(\n selected: readonly string[],\n modelId: string,\n): string[] {\n return selected.includes(modelId)\n ? selected.filter((value) => value !== modelId)\n : [...selected, modelId]\n}\n\n/** The catalog facts the visible-models card reads (mirrors `SettingsPageState`). */\nexport interface CatalogReadiness {\n /** Catalog model ids the Host reported (`[]` before the first fetch lands). */\n catalogIds: readonly string[]\n /** Whether the catalog fetch failed (or the Remote is unavailable). */\n catalogFailed: boolean\n}\n\n/**\n * Whether the catalog is trustworthy enough to call an unlisted selection\n * \"retired\". FALSE while the first fetch is in flight, after a failure, and\n * for a loaded-but-empty catalog — an empty list makes every selected id look\n * stale, which would turn the one-click stale cleanup into a button that\n * silently empties the allowlist. Users who really want it cleared have the\n * explicit \"show all\" entry.\n */\nexport function catalogIsReady(readiness: CatalogReadiness): boolean {\n return readiness.catalogIds.length > 0 && !readiness.catalogFailed\n}\n\n/**\n * Selected ids the loaded catalog no longer carries, in selection order.\n * Callers gate user-visible \"stale\" affordances on {@link catalogIsReady} —\n * the list itself is informational.\n */\nexport function staleModelIds(\n selected: readonly string[],\n readiness: CatalogReadiness,\n): string[] {\n const catalogIds = new Set(readiness.catalogIds)\n return selected.filter((id) => !catalogIds.has(id))\n}\n","","/**\n * The plugin's own version, read from package.json at build time. The client\n * bundle inlines the JSON import (rolldown resolves it during the tsdown\n * build; node tests read it through tsx), so the rendered value always matches\n * the published package version with no second constant to keep in sync —\n * rendered as a muted footer line so a user can report the exact build.\n *\n * @module dsh-commandcode-provider/client/version\n */\n\nimport pkg from '../../package.json'\n\n/** The published package version. */\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 * Tolerates both repository shapes (`{ url }` and the plain string form).\n */\nexport const PLUGIN_RELEASES_URL: string = (() => {\n const repo: unknown = (pkg as { repository?: unknown }).repository\n const url = typeof repo === 'string' ? repo : (repo as { url?: unknown } | undefined)?.url\n return `${typeof url === 'string' ? url.replace(/^git\\+/, '').replace(/\\.git$/, '') : 'https://github.com/Mars-Sea/dsh-commandcode-provider'}/releases`\n})()\n","/**\n * Plugin update hint (browser half).\n *\n * When the \"Command Code\" settings page opens, ask the npm registry for the\n * package's published `latest` version and — only when it is newer than the\n * running build — let the page's footer show a muted \"newer version available\"\n * link to the GitHub releases. Everything here is React-free and side-effect\n * seamed so node tests can drive it.\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` with\n * the attempt time, so re-opening the page is free. A FAILED check records the\n * attempt time too (an offline browser must not hammer the registry) but keeps\n * any previously learned version, so the hint survives transient outages. Every\n * failure mode — blocked network, non-OK status, malformed payload,\n * unavailable storage — degrades to \"no hint\"; nothing ever throws out of\n * {@link checkForUpdate}. The registry serves `access-control-allow-origin: *`,\n * so the plain browser fetch works from the GUI origin with no Host proxy.\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]`): negative when `a`\n * 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. Enough for release tags,\n * not a full 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 // Split on the FIRST dash only: `1.0.0-alpha-1` has prerelease `alpha-1`,\n // not `alpha` (a split on every dash would drop the `-1`).\n const cleaned = value.trim().replace(/^v/i, '')\n const dash = cleaned.indexOf('-')\n const coreText = dash < 0 ? cleaned : cleaned.slice(0, dash)\n const preText = dash < 0 ? undefined : cleaned.slice(dash + 1)\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. All copy comes from the\n * `settings.commandcode` locale namespace; all state comes from the\n * `CommandCodeSettingsController` injected by the slot registration.\n *\n * Layout, top to bottom: Accounts (one card per account, status, quota,\n * actions and dedicated models — every operation commits immediately), Models\n * (plan filter + visible-model allowlist), Privacy & security (ZDR),\n * Integrations & display (web search, sidebar quota card), and a collapsed\n * Advanced card (API base + network limits). Everything below Accounts is a\n * flat group of rows (title/description left, control right) inside the staged\n * form the floating save bar writes.\n *\n * Styles are injected once by the client entry (see src/client/index.ts) and\n * class-prefixed `cc-` to stay local.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } 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 { settingsWriteNotice, type SettingsCommandCodeKey } from './locales.ts'\nimport type { CatalogModelOption, SettingsPageState, StagedField } from './settings.ts'\nimport type { AccountEnrollmentController, EnrollmentPageState } from './enrollment.ts'\nimport type { LoginPageState } from './login.ts'\nimport { loginHint, loginStateForTarget } from './login.ts'\nimport { buildModelSelectOptions, catalogIsReady, groupModelSelectOptions, staleModelIds, tierHeadingFor, toggleModelSelection } from './model-select.ts'\nimport type { UsagePageState } from './usage.ts'\nimport { usageCardState } from './usage.ts'\nimport { formatMoney, formatMoneyExact, formatResetAt, formatSuccessRate, formatTokensCompact, windowRatio } from '../display-format.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 openAnalytics?(): void\n refreshCredentials(): void\n beginLogin(targetRef?: string): void\n cancelLogin(): void\n createEnrollment(): AccountEnrollmentController\n renameAccount(ref: string, label: string): Promise<boolean>\n removeAccount(ref: string): Promise<boolean>\n retryCredentialCleanup(ref: string): Promise<boolean>\n setAccountKey(target: string, key: string): Promise<boolean>\n clearAccountKey(target: string): Promise<boolean>\n setActiveAccount(id: string): Promise<boolean>\n setAccountModels(target: string, ids: string[]): Promise<boolean>\n editVisibleModels(ids: string[]): void\n clearVisibleModels(): void\n}\n\n/** The section fields folded into the collapsible Advanced card. */\ntype AdvancedField = 'apiBase' | 'requestTimeoutMs' | 'streamIdleTimeoutMs' | 'transportMaxRetries' | 'offloadSeenImagesForCache'\nconst ADVANCED_FIELDS: readonly AdvancedField[] = [\n 'apiBase',\n 'requestTimeoutMs',\n 'streamIdleTimeoutMs',\n 'transportMaxRetries',\n 'offloadSeenImagesForCache',\n]\n\n/** The \"customized\" tag and reset link a staged field shows once it differs from the default. */\nfunction FieldOverride({ label, state, disabled, t, onReset }: {\n label: string\n state: StagedField\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onReset(): void\n}) {\n if (!state.overridden && !state.clear) return null\n return (\n <button type=\"button\" className=\"cc-linkButton\" disabled={disabled} onClick={onReset} aria-label={`${label} — ${t('reset')}`}>\n {t('reset')}\n </button>\n )\n}\n\n/**\n * One settings row, laid out like the harness's own General page: the title\n * and description on the left, the control on the right, a hairline between\n * rows.\n */\nfunction SettingRow({ title, titleFor, titleId, tag, description, error, control, className }: {\n title: string\n /** Makes the title a `<label>` for this control id. */\n titleFor?: string\n titleId?: string\n tag?: ReactNode\n description?: ReactNode\n /** Replaces the description while set. */\n error?: string | undefined\n control?: ReactNode\n className?: string\n}) {\n return (\n <div className={className === undefined ? 'cc-row' : `cc-row ${className}`}>\n <div className=\"cc-rowText\">\n <div className=\"cc-rowTitleLine\">\n {titleFor !== undefined\n ? <label className=\"cc-rowTitle\" id={titleId} htmlFor={titleFor}>{title}</label>\n : <span className=\"cc-rowTitle\" id={titleId}>{title}</span>}\n {tag}\n </div>\n {error !== undefined ? <p className=\"cc-rowError\">{error}</p> : null}\n {error === undefined && description !== undefined ? <div className=\"cc-rowDesc\">{description}</div> : null}\n </div>\n {control !== undefined ? <div className=\"cc-rowControl\">{control}</div> : null}\n </div>\n )\n}\n\n/** The tag a row title carries while its field overrides the default. */\nfunction OverrideTag({ state, t }: { state: StagedField; t: Translate<SettingsCommandCodeKey> }) {\n return state.overridden ? <span className=\"cc-badge\">{t('overridden')}</span> : null\n}\n\n/** One text/number field row. */\nfunction Field({\n id,\n label,\n hint,\n state,\n disabled,\n numeric,\n decimal,\n wide,\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 decimal?: boolean\n wide?: boolean\n placeholder?: string | undefined\n onEdit(text: string): void\n onReset(): void\n t: Translate<SettingsCommandCodeKey>\n}) {\n return (\n <SettingRow\n title={label}\n titleFor={id}\n tag={<OverrideTag state={state} t={t} />}\n description={hint}\n error={state.invalid ? invalidCopy(state.invalidReason, t, decimal) : undefined}\n control={\n <>\n <FieldOverride label={label} state={state} disabled={disabled} t={t} onReset={onReset} />\n <input\n id={id}\n className={`cc-input ${wide ? 'cc-rowInputWide' : 'cc-rowInput'}${state.invalid ? ' cc-inputInvalid' : ''}`}\n type=\"text\"\n inputMode={decimal ? 'decimal' : numeric ? 'numeric' : undefined}\n aria-invalid={state.invalid || undefined}\n value={state.text}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(event) => onEdit(event.target.value)}\n />\n </>\n }\n />\n )\n}\n\n/** The per-field error copy for a staged draft's failure reason. */\nfunction invalidCopy(reason: StagedField['invalidReason'], t: Translate<SettingsCommandCodeKey>, duration = false): string {\n if (duration) {\n if (reason === 'tooSmall') return t('durationTooSmall')\n if (reason === 'tooLarge') return t('durationTooLarge')\n return t('durationInvalid')\n }\n if (reason === 'tooSmall') return t('numberTooSmall')\n if (reason === 'tooLarge') return t('numberTooLarge')\n return t('invalidNumber')\n}\n\n/**\n * One boolean field row rendered as a switch. 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 <SettingRow\n title={label}\n titleFor={id}\n tag={<OverrideTag state={state} t={t} />}\n description={hint}\n control={\n <>\n <FieldOverride label={label} state={state} disabled={disabled} t={t} onReset={onReset} />\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 </>\n }\n />\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,\n t,\n}: {\n label: string\n limit: NonNullable<CommandCodeCredits['fiveHour']>\n t: Translate<SettingsCommandCodeKey>\n}) {\n const { used, cap, exceeded, resetAt } = limit\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-label={label} 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 pool account's facts (identity, totals, credits, window limits). */\nfunction AccountReport({ entry, fetchedAt, t, headless = false }: {\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 /** Omit the identity header (the account row already shows it). */\n headless?: boolean\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 {!headless ? (\n <div className=\"cc-usageHead\">\n <h4 className=\"cc-usageTitle\">{entry.label}</h4>\n {accountName !== '' ? <span className=\"cc-usageAccount\">{accountName}</span> : null}\n {planName !== '' ? <span className=\"cc-usagePlan\">{planName}</span> : null}\n </div>\n ) : null}\n {planStatus !== '' ? <p className=\"cc-usagePlanStatus\">{planStatus}</p> : null}\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 {/* Keep the per-endpoint failures visible alongside the summary:\n they carry the actual status or transport error for diagnosis. */}\n {report.failures.length > 0 ? (\n <p className=\"cc-usageBlockedDetail\" title={report.failures.join('; ')}>\n {report.failures.join(' · ')}\n </p>\n ) : null}\n </div>\n ) : null}\n\n {report.usage !== undefined ? (\n <div className=\"cc-usageStats cc-usageStatsActivity\">\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={`${formatSuccessRate(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 cc-usageStatsBalance\">\n <UsageStat label={t('usageMonthly')} value={credits.monthlyReported === false ? '—' : formatMoney(credits.monthlyCredits)} />\n <UsageStat label={t('usagePurchased')} value={credits.purchasedReported === false ? '—' : formatMoney(credits.purchasedCredits)} />\n <UsageStat label={t('usageFree')} value={credits.freeReported === false ? '—' : formatMoney(credits.freeCredits)} />\n </div>\n ) : null}\n\n {credits?.fiveHour !== undefined || credits?.weekly !== undefined ? (\n <div className=\"cc-usageWindows\">\n {credits.fiveHour !== undefined ? (\n <UsageWindow label={t('usageFiveHour')} limit={credits.fiveHour} t={t} />\n ) : null}\n {credits.weekly !== undefined ? (\n <UsageWindow label={t('usageWeekly')} limit={credits.weekly} t={t} />\n ) : null}\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 if (reason === 'invalid-response') return t('usageInvalidResponse')\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 if (reason === 'invalid-response') return t('usageInvalidResponseHint')\n return t('usageNetworkHint')\n}\n\n/**\n * A checkbox multi-select dropdown for picking catalog models (the routing-rule\n * rows and the visible-models filter share it). The trigger shows the selection\n * count; the Menu lists every catalog model, grouping under plan-tier headings\n * and flagging selected ids the catalog no longer carries as stale, so a saved\n * selection never silently loses an entry (the VisibleModelsCard offers a\n * one-click cleanup).\n *\n * With `deferCommit` the toggles collect in a local draft that is handed to\n * `onSelect` once, when the menu closes: the per-account picker writes\n * immediately, and one write per click would be a burst of document writes.\n */\nfunction ModelMultiSelect({ id, selected: committed, catalog, disabled, deferCommit = false, ownerOf, t, onSelect }: {\n id: string\n selected: string[]\n catalog: CatalogModelOption[]\n disabled: boolean\n deferCommit?: boolean\n /** Names the other account a model currently belongs to, if any. */\n ownerOf?: (modelId: string) => string | undefined\n t: Translate<SettingsCommandCodeKey>\n onSelect(ids: string[]): void\n}) {\n const [open, setOpen] = useState(false)\n const [query, setQuery] = useState('')\n const [draft, setDraft] = useState<string[] | undefined>(undefined)\n const selected = draft ?? committed\n // The search box must not inherit a stale query from a previous open.\n useEffect(() => {\n if (open) setQuery('')\n }, [open])\n const close = () => {\n setOpen(false)\n if (draft !== undefined) {\n setDraft(undefined)\n const changed = draft.length !== committed.length || draft.some((modelId) => !committed.includes(modelId))\n if (changed) onSelect(draft)\n }\n }\n // Tier headings come from the catalog entries themselves (the Host stamps\n // each entry's plan-tier key on the Remote); rebuild only when the catalog\n // changes.\n const tiers = useMemo(\n () => Object.fromEntries(\n catalog.flatMap((model) => model.tier === undefined ? [] : [[model.id, model.tier] as const]),\n ),\n [catalog],\n )\n const options = buildModelSelectOptions(catalog, selected, query)\n const groups = groupModelSelectOptions(options, (modelId) => tierHeadingFor(modelId, tiers))\n const items: MenuEntry[] = groups.flatMap((group) => [\n ...(group.heading === undefined\n ? []\n : [{ type: 'label' as const, id: `cc-tier-${group.heading}`, text: group.heading }]),\n ...group.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={selected.includes(option.value)}\n readOnly\n tabIndex={-1}\n />\n <span className=\"cc-checkName\">{option.label}</span>\n {option.stale ? <span className=\"cc-badge\">{t('modelStale')}</span> : null}\n {option.allowance !== undefined ? (\n <span className=\"cc-badgeMuted\" title={t('modelAllowanceTitle')}>\n {t('modelAllowance', { amount: option.allowance })}\n </span>\n ) : null}\n {!selected.includes(option.value) && ownerOf?.(option.value) !== undefined ? (\n <span className=\"cc-badgeMuted\">{t('accountModelOwner', { name: ownerOf(option.value)! })}</span>\n ) : null}\n </span>\n ),\n })),\n ])\n // The search box lives INSIDE the Menu anchor (which renders in place\n // inside the Menu's root span): a pointerdown there counts as \"inside\",\n // so focusing/typing never trips the Menu's outside-click close. A box\n // rendered as a sibling would close the Menu on the first click.\n return (\n <Menu\n open={open}\n onClose={close}\n onSelect={(modelId) => {\n const next = toggleModelSelection(selected, modelId)\n if (deferCommit) setDraft(next)\n else onSelect(next)\n }}\n selectedIds={selected}\n items={items}\n footer={options.length === 0 ? [{\n type: 'label' as const,\n id: 'cc-model-search-empty',\n text: t('modelSearchEmpty'),\n }] : []}\n portal\n anchor={\n <span className=\"cc-modelSelectAnchor\">\n <button\n id={id}\n type=\"button\"\n className=\"cc-selector\"\n disabled={disabled || catalog.length === 0}\n onClick={() => (open ? close() : setOpen(true))}\n >\n <span className=\"cc-selectorText\">\n {selected.length === 0 ? t('modelPick') : t('modelCount', { count: selected.length })}\n </span>\n <span className=\"cc-selectorCaret\" aria-hidden=\"true\" />\n </button>\n {open ? (\n <input\n type=\"search\"\n className=\"cc-input cc-modelSearch\"\n placeholder={t('modelSearchPlaceholder')}\n aria-label={t('modelSearchPlaceholder')}\n value={query}\n disabled={disabled}\n autoFocus\n onChange={(event) => setQuery(event.target.value)}\n />\n ) : null}\n </span>\n }\n />\n )\n}\n\n/** The visible-model filter row: an allowlist over the catalog. Empty = show all. */\nfunction VisibleModelsRow({ t, state, disabled, onSelect, onClear }: {\n t: Translate<SettingsCommandCodeKey>\n state: SettingsPageState\n disabled: boolean\n onSelect(ids: string[]): void\n onClear(): void\n}) {\n const count = state.visibleModels.length\n const pickT: Translate<SettingsCommandCodeKey> = (key, params) => {\n if (key === 'modelPick' || key === 'modelCount') {\n return state.visibleModelsAll ? t('visibleModelsShowAll') : t('visibleModelsCount', { count })\n }\n return t(key, params)\n }\n // Selected ids the live catalog no longer carries (retired upstream): kept,\n // flagged stale in the dropdown, removable in one click — never auto-dropped,\n // since an empty catalog (fetch failure) must not wipe the list. Both the\n // cleanup button and its hint are gated on catalogIsReady, whose doc states\n // why an empty catalog makes every selection look retired.\n const readiness = { catalogIds: state.catalogModels.map((model) => model.id), catalogFailed: state.catalogFailed }\n const staleIds = staleModelIds(state.visibleModels, readiness)\n const catalogReady = catalogIsReady(readiness)\n return (\n <SettingRow\n title={t('visibleModelsTitle')}\n titleFor=\"cc-visible-models\"\n description={\n <>\n <p>{t('visibleModelsHint')}</p>\n {staleIds.length > 0 && catalogReady ? <p>{t('visibleModelsStaleHint', { count: staleIds.length })}</p> : null}\n </>\n }\n error={state.catalogFailed ? t('modelCatalogFailed') : undefined}\n control={\n <>\n {catalogReady && staleIds.length > 0 ? (\n <button\n type=\"button\"\n className=\"cc-linkButton\"\n disabled={disabled}\n onClick={() => onSelect(state.visibleModels.filter((id) => !staleIds.includes(id)))}\n >\n {t('visibleModelsCleanStale', { count: staleIds.length })}\n </button>\n ) : null}\n {!state.visibleModelsAll ? (\n <button type=\"button\" className=\"cc-linkButton\" disabled={disabled} onClick={onClear}>\n {t('visibleModelsShowAll')}\n </button>\n ) : null}\n <ModelMultiSelect\n id=\"cc-visible-models\"\n selected={state.visibleModels}\n catalog={state.catalogModels}\n disabled={disabled}\n t={pickT}\n onSelect={onSelect}\n />\n </>\n }\n />\n )\n}\n\n/**\n * One titled group of rows. No card surface: like the harness's own settings\n * pages, a group is a heading over its rows. The hairline between sections is\n * `cc-groupDivided`, so it belongs to every group but the first one on the page\n * (accounts opens it) and never to the rows inside a group.\n */\nfunction SettingsGroup({ title, action, divided = false, children }: { title: string; action?: ReactNode; divided?: boolean; children: ReactNode }) {\n return (\n <section className={divided ? 'cc-group cc-groupDivided' : 'cc-group'} aria-label={title}>\n <div className=\"cc-groupHead\">\n <h3 className=\"cc-groupTitle\">{title}</h3>\n {action}\n </div>\n <div className=\"cc-rows\">{children}</div>\n </section>\n )\n}\n\n/** The staged-field callbacks every form card shares. */\ninterface FormCardProps {\n state: SettingsPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onEdit(field: string, text: string): void\n onReset(field: string): void\n}\n\n/**\n * Models: the plan filter and the allowlist sit together because both decide\n * what the model picker lists (the allowlist applies after the plan filter).\n */\nfunction ModelsCard({ state, disabled, t, onEdit, onReset, onSelect, onClear }: FormCardProps & {\n onSelect(ids: string[]): void\n onClear(): void\n}) {\n return (\n <SettingsGroup title={t('modelsTitle')} divided>\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 <VisibleModelsRow t={t} state={state} disabled={disabled} onSelect={onSelect} onClear={onClear} />\n </SettingsGroup>\n )\n}\n\n/**\n * Privacy & security: the opt-in that changes where data goes. ZDR restricts\n * which upstream serves a request, so it starts off.\n */\nfunction PrivacyCard({ state, disabled, t, onEdit, onReset }: FormCardProps) {\n return (\n <SettingsGroup title={t('privacyTitle')} divided>\n <ToggleField\n id=\"cc-zdr\"\n label={t('zdr')}\n hint={t('zdrHint')}\n state={state.zdr}\n disabled={disabled}\n defaultChecked={false}\n onEdit={(text) => onEdit('zdr', text)}\n onReset={() => onReset('zdr')}\n t={t}\n />\n </SettingsGroup>\n )\n}\n\n/** Integrations & display: surfaces outside chat that reuse this provider. */\nfunction IntegrationsCard({ state, disabled, t, onEdit, onReset }: FormCardProps) {\n return (\n <SettingsGroup title={t('integrationsTitle')} divided>\n <ToggleField\n id=\"cc-web-search\"\n label={t('webSearch')}\n hint={t('webSearchHint')}\n state={state.webSearch}\n disabled={disabled}\n defaultChecked\n onEdit={(text) => onEdit('webSearch', text)}\n onReset={() => onReset('webSearch')}\n t={t}\n />\n {/* Opt-in, and off by default: the sidebar quota card is a display\n surface, so an unset document shows nothing on the left. */}\n <ToggleField\n id=\"cc-show-sidebar-quota\"\n label={t('showSidebarQuota')}\n hint={t('showSidebarQuotaHint')}\n state={state.showSidebarQuota}\n disabled={disabled}\n defaultChecked={false}\n onEdit={(text) => onEdit('showSidebarQuota', text)}\n onReset={() => onReset('showSidebarQuota')}\n t={t}\n />\n </SettingsGroup>\n )\n}\n\n/**\n * The collapsed \"Advanced\" card: the API base and the network limits. Starts\n * collapsed on every visit; while collapsed, a badge names the customized\n * count and an invalid number (which blocks save) is surfaced on the header.\n */\nfunction AdvancedSection({ state, disabled, t, onEdit, onReset }: FormCardProps) {\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 <section className=\"cc-group cc-groupDivided\" aria-label={t('advancedSettings')}>\n <button\n type=\"button\"\n className=\"cc-groupHead cc-disclosure\"\n aria-expanded={expanded}\n aria-controls=\"cc-advanced-body\"\n onClick={() => setExpanded((value) => !value)}\n >\n <span className=\"cc-groupTitle\">{t('advancedSettings')}</span>\n {overridden > 0 ? (\n <span className=\"cc-badge\">\n {overridden === 1 ? t('advancedOverriddenOne') : t('advancedOverriddenMany', { count: overridden })}\n </span>\n ) : null}\n {!expanded && invalid ? (\n <span className=\"cc-badge cc-badgeWarn\">{t('advancedInvalid')}</span>\n ) : null}\n <span className=\"cc-spacer\" />\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-rows\">\n <p className=\"cc-groupDesc\">{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 wide\n onEdit={(text) => onEdit('apiBase', text)}\n onReset={() => onReset('apiBase')}\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 decimal\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 decimal\n onEdit={(text) => onEdit('streamIdleTimeoutMs', text)}\n onReset={() => onReset('streamIdleTimeoutMs')}\n t={t}\n />\n <Field\n id=\"cc-transport-max-retries\"\n label={t('transportMaxRetries')}\n hint={t('transportMaxRetriesHint')}\n state={state.transportMaxRetries}\n disabled={disabled}\n numeric\n onEdit={(text) => onEdit('transportMaxRetries', text)}\n onReset={() => onReset('transportMaxRetries')}\n t={t}\n />\n <ToggleField\n id=\"cc-offload-seen-images-for-cache\"\n label={t('offloadSeenImagesForCache')}\n hint={t('offloadSeenImagesForCacheHint')}\n state={state.offloadSeenImagesForCache}\n disabled={disabled}\n defaultChecked={false}\n onEdit={(text) => onEdit('offloadSeenImagesForCache', text)}\n onReset={() => onReset('offloadSeenImagesForCache')}\n t={t}\n />\n </div>\n ) : null}\n {expanded && invalid ? (\n <p className=\"cc-rowError\" role=\"status\">{t('advancedInvalid')}</p>\n ) : null}\n </section>\n )\n}\n\n/** One row of the unified account list: a stored account merged with its usage entry. */\ninterface AccountRowModel {\n /** Slot id: `default` or the extra account's credential reference. */\n id: string\n label: string\n /** Credential reference for extra accounts; undefined for the default slot. */\n ref: string | undefined\n isDefault: boolean\n /** Whether this page can manage the row (false for literal-only composition entries). */\n managed: boolean\n /** Whether a key resolves for this account (stored credential or a Host-side source). */\n configured: boolean\n /** Whether a stored credential exists this page could delete. */\n storedKey: boolean\n credentialKnown: boolean\n keyWritable: boolean\n usage: CommandCodeAccountUsage | undefined\n}\n\n/**\n * Merge the controller's accounts with the usage report. The default slot is\n * always first; report entries this page cannot manage (literal keys from the\n * composition config) still render, read-only, so the list names every\n * account the pool rotates through.\n */\nfunction accountRows(state: SettingsPageState, usage: UsagePageState, t: Translate<SettingsCommandCodeKey>): AccountRowModel[] {\n const report = new Map((usage.report?.accounts ?? []).map((entry) => [entry.id, entry]))\n const defaultUsage = report.get('default')\n const rows: AccountRowModel[] = [{\n id: 'default',\n label: t('accountDefault'),\n ref: undefined,\n isDefault: true,\n managed: true,\n configured: state.apiKeyConfigured || defaultUsage?.configured === true,\n storedKey: state.apiKeyConfigured,\n credentialKnown: state.apiKeyKnown || typeof defaultUsage?.configured === 'boolean',\n keyWritable: state.apiKeyWritable,\n usage: defaultUsage,\n }]\n for (const account of state.accounts) {\n const entry = report.get(account.id)\n rows.push({\n id: account.id,\n label: account.label,\n ref: account.ref,\n isDefault: false,\n managed: true,\n configured: account.configured || entry?.configured === true,\n storedKey: account.configured,\n credentialKnown: account.credentialKnown || typeof entry?.configured === 'boolean',\n keyWritable: account.writable,\n usage: entry,\n })\n }\n const known = new Set(rows.map((row) => row.id))\n for (const entry of usage.report?.accounts ?? []) {\n if (known.has(entry.id)) continue\n known.add(entry.id)\n rows.push({\n id: entry.id,\n label: entry.label,\n ref: undefined,\n isDefault: false,\n managed: false,\n configured: entry.configured,\n storedKey: false,\n credentialKnown: true,\n keyWritable: false,\n usage: entry,\n })\n }\n return rows\n}\n\n/**\n * The row's status dot. Read top-down, so a problem always outranks \"serving\":\n * red for a key the Host rejected, amber while a rate limit is cooling down,\n * green for the account that is actually serving requests. A standby (or not\n * yet configured) account draws NOTHING — `cc-tabDotBlank` is an unfilled,\n * borderless dot that only holds the column so the account names stay aligned\n * with the rows that do have a verdict. Green therefore means \"in use\", not\n * \"healthy\": a wall of green dots would say nothing.\n */\nfunction statusDotClass(row: AccountRowModel): string {\n const entry = row.usage\n if (entry?.mark === 'invalid-credential') return 'cc-tabDot cc-tabDotError'\n if (entry !== undefined && (entry.mark !== '' || entry.cooldownUntil > 0)) return 'cc-tabDot cc-tabDotWarn'\n if (row.configured && entry?.active === true) return 'cc-tabDot cc-tabDotOk'\n return 'cc-tabDot cc-tabDotBlank'\n}\n\n/**\n * The same verdict as a sentence, for the dot's tooltip. Undefined on a blank\n * dot: there is no verdict to read out, and a hover hotspot on an invisible\n * 8px mark would only invite the question it cannot usefully answer.\n */\nfunction statusDotTitle(row: AccountRowModel, t: Translate<SettingsCommandCodeKey>): string | undefined {\n const entry = row.usage\n if (entry?.mark === 'invalid-credential') return t('usageInvalidKey')\n if (entry !== undefined && (entry.mark !== '' || entry.cooldownUntil > 0)) return t('usageCooldown')\n if (!row.credentialKnown) return t('writeStateUnknown')\n if (!row.configured) return t('apiKeyUnset')\n return entry?.active === true ? t('usageActive') : undefined\n}\n\n/** One compact quota meter for a row's summary line. */\nfunction MiniMeter({ label, limit }: { label: string; limit: NonNullable<CommandCodeCredits['fiveHour']> }) {\n const ratio = windowRatio(limit.used, limit.cap)\n const percent = limit.cap > 0 ? `${Math.round(ratio * 100)}%` : formatMoney(limit.used)\n return (\n <span className=\"cc-miniMeter\" title={limit.cap > 0 ? `${formatMoney(limit.used)} / ${formatMoney(limit.cap)}` : undefined}>\n <span className=\"cc-miniMeterLabel\">{label}</span>\n <span className=\"cc-miniMeterTrack\" aria-hidden=\"true\">\n <span className={limit.exceeded ? 'cc-miniMeterFill cc-usageBarFillWarn' : 'cc-miniMeterFill'} style={{ width: `${ratio * 100}%` }} />\n </span>\n <span className=\"cc-miniMeterValue\">{percent}</span>\n </span>\n )\n}\n\n/**\n * The monthly credit balance for a row's summary line: the billing endpoint's\n * `monthlyCredits` is what is LEFT, shown as the amount alone.\n */\nfunction MonthlyBalance({ label, remaining }: { label: string; remaining: number }) {\n return (\n <span className=\"cc-miniMeter\">\n <span className=\"cc-miniMeterLabel\">{label}</span>\n <span className=\"cc-miniMeterValue\">{formatMoney(Math.max(0, remaining))}</span>\n </span>\n )\n}\n\n/** A single-input inline form (paste key, rename) with confirm/cancel. */\nfunction InlineInput({ id, label, secret, initial, placeholder, confirmLabel, disabled, t, onSubmit, onCancel }: {\n id: string\n label: string\n secret?: boolean\n initial?: string\n placeholder?: string\n confirmLabel: string\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onSubmit(value: string): void\n onCancel(): void\n}) {\n const [value, setValue] = useState(initial ?? '')\n const [visible, setVisible] = useState(false)\n const ready = value.trim() !== ''\n return (\n <form\n className=\"cc-inlineForm\"\n onSubmit={(event) => {\n event.preventDefault()\n if (ready && !disabled) onSubmit(value)\n }}\n >\n <input\n id={id}\n className=\"cc-input\"\n type={secret && !visible ? 'password' : 'text'}\n aria-label={label}\n autoComplete=\"new-password\"\n spellCheck={false}\n autoFocus\n placeholder={placeholder}\n value={value}\n disabled={disabled}\n onChange={(event) => setValue(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') onCancel()\n }}\n />\n <div className=\"cc-inlineActions\">\n {secret && value !== '' ? (\n <button type=\"button\" className=\"cc-reset\" onClick={() => setVisible((shown) => !shown)}>\n {visible ? t('hide') : t('show')}\n </button>\n ) : null}\n <span className=\"cc-spacer\" />\n <Button variant=\"ghost\" size=\"sm\" type=\"button\" onClick={onCancel}>{t('cancel')}</Button>\n <Button variant=\"primary\" size=\"sm\" type=\"submit\" disabled={!ready || disabled}>{confirmLabel}</Button>\n </div>\n </form>\n )\n}\n\n/** A destructive confirmation bar shown in place of a menu action. */\nfunction ConfirmBar({ text, confirmLabel, disabled, t, onConfirm, onCancel }: {\n text: string\n confirmLabel: string\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n onConfirm(): void\n onCancel(): void\n}) {\n return (\n <div className=\"cc-confirmBar\" role=\"alertdialog\" aria-label={text}>\n <p className=\"cc-confirmText\">{text}</p>\n <div className=\"cc-inlineActions\">\n <span className=\"cc-spacer\" />\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>{t('cancel')}</Button>\n <Button variant=\"outline\" size=\"sm\" className=\"cc-dangerButton\" disabled={disabled} onClick={onConfirm}>{confirmLabel}</Button>\n </div>\n </div>\n )\n}\n\ntype RowMode = 'key' | 'rename' | 'remove' | 'clearKey' | undefined\n\n/** One account row: identity, status, quota summary, actions and expandable details. */\nfunction AccountItem({ row, rows, state, usage, login, disabled, pinned, t, actions }: {\n row: AccountRowModel\n rows: readonly AccountRowModel[]\n state: SettingsPageState\n usage: UsagePageState\n login: LoginPageState\n disabled: boolean\n pinned: boolean\n t: Translate<SettingsCommandCodeKey>\n actions: AccountActions\n}) {\n const [expanded, setExpanded] = useState(false)\n const [menuOpen, setMenuOpen] = useState(false)\n const [mode, setMode] = useState<RowMode>(undefined)\n const entry = row.usage\n const report = entry?.report\n const accountName = report?.account === undefined ? '' : report.account.userName || report.account.name\n const planName = report?.plan?.name ?? ''\n const credits = report?.credits\n // Only an explicit `false` means the balance was omitted (an older Host\n // never sends the flag and always sent a real number).\n const monthlyReported = credits !== undefined && credits.monthlyReported !== false\n const multi = rows.length > 1\n const loginTarget = row.ref\n const { visible: loginState, busyElsewhere } = loginStateForTarget(login, loginTarget)\n const loginBusy = loginState.phase === 'starting' || loginState.phase === 'waiting'\n const showLogin = loginState.phase !== 'idle'\n const locked = disabled || !row.managed\n const keyActions = !locked && row.keyWritable\n\n const items: MenuEntry[] = []\n if (row.managed && multi) {\n items.push(pinned\n ? { id: 'unpin', label: t('accountActionUnpin'), disabled: locked }\n : { id: 'pin', label: t('accountActionPin'), disabled: locked || !row.configured })\n }\n if (row.managed) {\n if (items.length > 0) items.push({ type: 'separator', id: 'sep-key' })\n items.push(\n { id: 'login', label: t('accountActionLogin'), disabled: !keyActions || loginBusy || busyElsewhere },\n { id: 'key', label: t('accountActionKey'), disabled: !keyActions },\n )\n if (!row.isDefault) items.push({ id: 'rename', label: t('accountActionRename'), disabled: locked })\n if (row.isDefault && row.storedKey) {\n items.push(\n { type: 'separator', id: 'sep-danger' },\n { id: 'clearKey', label: t('accountActionClearKey'), disabled: !keyActions, danger: true },\n )\n }\n if (!row.isDefault) {\n items.push(\n { type: 'separator', id: 'sep-danger' },\n { id: 'remove', label: t('accountActionRemove'), disabled: locked, danger: true },\n )\n }\n }\n\n const onAction = (id: string) => {\n setMenuOpen(false)\n if (id === 'pin') void actions.setActive(row.id)\n else if (id === 'unpin') void actions.setActive('')\n else if (id === 'login') actions.beginLogin(loginTarget)\n else if (id === 'key' || id === 'rename' || id === 'remove' || id === 'clearKey') setMode(id)\n }\n\n const models = state.accountModels[row.id] ?? []\n const ownerOf = (modelId: string): string | undefined => {\n for (const [account, list] of Object.entries(state.accountModels)) {\n if (account === row.id || !list.includes(modelId)) continue\n return rows.find((candidate) => candidate.id === account)?.label ?? account\n }\n return undefined\n }\n\n return (\n <div className={row.usage?.active ? 'cc-accountItem cc-accountItemActive' : 'cc-accountItem'}>\n <div className=\"cc-accountHead\">\n <button\n type=\"button\"\n className=\"cc-accountToggle\"\n aria-expanded={expanded}\n aria-controls={`cc-account-${row.id}-details`}\n onClick={() => setExpanded((value) => !value)}\n >\n <span className={statusDotClass(row)} title={statusDotTitle(row, t)} aria-hidden=\"true\" />\n <span className=\"cc-accountName\">{row.label}</span>\n {accountName !== '' && accountName !== row.label ? <span className=\"cc-usageAccount\">{accountName}</span> : null}\n {planName !== '' ? <span className=\"cc-usagePlan\">{planName}</span> : null}\n {entry?.active && multi ? <span className=\"cc-badge\">{t('usageActive')}</span> : null}\n {pinned ? <span className=\"cc-badge\">{t('accountStatusPinned')}</span> : null}\n {!row.credentialKnown || !row.configured ? <span className=\"cc-badgeMuted\">{t(row.credentialKnown ? 'apiKeyUnset' : 'writeStateUnknown')}</span> : null}\n {entry?.mark === 'invalid-credential' ? <span className=\"cc-usagePlanStatus\">{t('usageInvalidKey')}</span> : null}\n {entry !== undefined && entry.mark !== 'invalid-credential' && (entry.cooldownUntil > 0 || entry.mark === 'rate-limit') ? (\n <span className=\"cc-usagePlanStatus\">\n {t('usageCooldown')}{entry.cooldownUntil > 0 ? ` ${formatResetAt(entry.cooldownUntil)}` : ''}\n </span>\n ) : null}\n <span className=\"cc-spacer\" />\n <span className={expanded ? 'cc-chevron cc-chevronUp' : 'cc-chevron'} aria-hidden=\"true\" />\n </button>\n {items.length > 0 ? (\n <Menu\n open={menuOpen}\n onClose={() => setMenuOpen(false)}\n onSelect={onAction}\n items={items}\n align=\"end\"\n portal\n anchor={\n <button\n type=\"button\"\n className=\"cc-iconButton\"\n aria-label={`${row.label} — ${t('accountActions')}`}\n title={t('accountActions')}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n onClick={() => setMenuOpen((value) => !value)}\n >\n <span className=\"cc-kebab\" aria-hidden=\"true\" />\n </button>\n }\n />\n ) : null}\n </div>\n\n {credits !== undefined && (credits.fiveHour !== undefined || credits.weekly !== undefined || monthlyReported) ? (\n <div className=\"cc-accountMeters\">\n {credits.fiveHour !== undefined ? <MiniMeter label={t('usageFiveHour')} limit={credits.fiveHour} /> : null}\n {credits.weekly !== undefined ? <MiniMeter label={t('usageWeekly')} limit={credits.weekly} /> : null}\n {monthlyReported ? (\n <MonthlyBalance label={t('usageMonthlyLeft')} remaining={credits.monthlyCredits} />\n ) : null}\n </div>\n ) : null}\n\n {row.credentialKnown && !row.configured && row.managed && mode === undefined && !showLogin ? (\n <div className=\"cc-accountSetup\">\n <p className=\"cc-hint\">{row.keyWritable ? t('accountNoKeyHint') : t('apiKeyLocked')}</p>\n {keyActions ? (\n <div className=\"cc-inlineActions\">\n <Button variant=\"primary\" size=\"sm\" disabled={loginBusy || busyElsewhere} onClick={() => actions.beginLogin(loginTarget)}>\n {t('accountAddLogin')}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setMode('key')}>{t('accountAddPaste')}</Button>\n </div>\n ) : null}\n </div>\n ) : null}\n\n {showLogin ? <LoginStatus state={loginState} t={t} onCancel={actions.cancelLogin} /> : null}\n\n {mode === 'key' ? (\n <InlineInput\n id={`cc-account-${row.id}-key`}\n label={t('accountKeyPlaceholder')}\n secret\n placeholder={t('accountKeyPlaceholder')}\n confirmLabel={t('accountApply')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onSubmit={(value) => {\n void actions.setKey(row.id, value).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n {mode === 'rename' && row.ref !== undefined ? (\n <InlineInput\n id={`cc-account-${row.id}-rename`}\n label={t('accountActionRename')}\n initial={row.label}\n confirmLabel={t('accountApply')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onSubmit={(value) => {\n void actions.rename(row.ref!, value).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n {mode === 'remove' && row.ref !== undefined ? (\n <ConfirmBar\n text={t('accountRemoveConfirm', { name: row.label })}\n confirmLabel={t('accountConfirmRemove')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onConfirm={() => {\n void actions.remove(row.ref!).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n {mode === 'clearKey' ? (\n <ConfirmBar\n text={t('accountClearKeyConfirm')}\n confirmLabel={t('accountConfirmClear')}\n disabled={disabled || state.accountBusy}\n t={t}\n onCancel={() => setMode(undefined)}\n onConfirm={() => {\n void actions.clearKey(row.id).then((ok) => {\n if (ok) setMode(undefined)\n })\n }}\n />\n ) : null}\n\n {expanded ? (\n <div id={`cc-account-${row.id}-details`} className=\"cc-accountDetails\">\n {entry !== undefined ? (\n <AccountReport entry={entry} fetchedAt={usage.fetchedAt} t={t} headless />\n ) : (\n <p className=\"cc-usageHint\">{usage.status === 'loading' ? t('usageLoading') : t('usageUnconfigured')}</p>\n )}\n {multi && row.managed ? (\n <SettingRow\n className=\"cc-rowFlush\"\n title={t('accountModels')}\n titleFor={`cc-account-${row.id}-models`}\n description={t('accountModelsHint')}\n error={state.catalogFailed ? t('modelCatalogFailed') : undefined}\n control={\n <ModelMultiSelect\n id={`cc-account-${row.id}-models`}\n selected={models}\n catalog={state.catalogModels}\n disabled={disabled || state.accountBusy}\n deferCommit\n ownerOf={ownerOf}\n t={t}\n onSelect={(ids) => void actions.setModels(row.id, ids)}\n />\n }\n />\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n\n/** The live status of one browser sign-in: link while waiting, outcome after. */\nfunction LoginStatus({ state, t, onCancel }: {\n state: LoginPageState\n t: Translate<SettingsCommandCodeKey>\n onCancel(): void\n}) {\n const hint = loginHint(state, t)\n const busy = state.phase === 'starting' || state.phase === 'waiting'\n return (\n <div className=\"cc-loginStatus\" role=\"status\">\n <p className={hint.className} title={hint.title}>{hint.text}</p>\n {state.authUrl !== undefined ? (\n <a className=\"cc-loginLink\" href={state.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n ) : null}\n {busy ? <button type=\"button\" className=\"cc-reset\" onClick={onCancel}>{t('loginCancel')}</button> : null}\n </div>\n )\n}\n\n/** The immediate account operations the list and its rows call. */\ninterface AccountActions {\n refreshCredentials(): void\n cleanup(ref: string): Promise<boolean>\n rename(ref: string, label: string): Promise<boolean>\n remove(ref: string): Promise<boolean>\n setKey(target: string, key: string): Promise<boolean>\n clearKey(target: string): Promise<boolean>\n setActive(id: string): Promise<boolean>\n setModels(target: string, ids: string[]): Promise<boolean>\n beginLogin(targetRef?: string): void\n cancelLogin(): void\n}\n\n/** 新增面板只负责输入和操作意图;账号、登录、命名与补偿由宿主过程负责。 */\nfunction AddAccountPanel({ state, disabled, t, enrollment, snapshot, onClose }: {\n state: SettingsPageState\n disabled: boolean\n t: Translate<SettingsCommandCodeKey>\n enrollment: AccountEnrollmentController\n snapshot: EnrollmentPageState\n onClose(): void\n}) {\n const [label, setLabel] = useState('')\n const [pasting, setPasting] = useState(false)\n const active = snapshot.active\n const busy = active !== undefined && ['creating', 'waiting', 'writing', 'cancelling', 'naming'].includes(active.phase)\n const fallbackName = t('accountNameN', { n: state.accounts.length + 2 })\n useEffect(() => { if (active?.phase === 'finished') onClose() }, [active?.phase, onClose])\n const start = (key?: string) => enrollment.begin({ mode: key === undefined ? 'browser' : 'manual',\n label: label.trim() || fallbackName, automaticName: label.trim() === '', ...(key === undefined ? {} : { key }) })\n const close = () => { enrollment.cancel(); onClose() }\n return (\n <div className=\"cc-addPanel\" aria-label={t('accountAdd')}>\n <span className=\"cc-panelTitle\">{t('accountAdd')}</span>\n <input className=\"cc-input\" type=\"text\" aria-label={t('accountNamePlaceholder')} placeholder={t('accountNamePlaceholder')}\n value={label} disabled={disabled || busy} onChange={(event) => setLabel(event.target.value)} />\n {active ? <p className=\"cc-hint\" role=\"status\">{active.message}</p> : null}\n {active?.authUrl && active.phase === 'waiting' ? <p className=\"cc-hint\">若登录页面未自动打开,请点击下方链接。</p> : null}\n {active?.authUrl && active.phase === 'waiting' ? <a className=\"cc-linkButton\" href={active.authUrl} target=\"_blank\" rel=\"noreferrer\">打开浏览器登录</a> : null}\n {snapshot.error ? <p className=\"cc-loginError\" role=\"status\">{snapshot.error}</p> : null}\n {active?.phase === 'naming' ? (\n <div className=\"cc-inlineActions\">\n <Button variant=\"primary\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.name(active.suggestedName || label || fallbackName)}>重试保存名称</Button>\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.name()}>接受已有名称</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>{t('cancel')}</Button>\n </div>\n ) : pasting ? (\n <InlineInput id=\"cc-add-account-key\" label={t('accountKeyPlaceholder')} secret placeholder={t('accountKeyPlaceholder')}\n confirmLabel={t('accountAddConfirm')} disabled={disabled || busy} t={t}\n onCancel={close} onSubmit={(key) => { void start(key) }} />\n ) : (\n <div className=\"cc-inlineActions\">\n <Button variant=\"primary\" size=\"sm\" disabled={disabled || busy} onClick={() => void start()}>{t('accountAddLogin')}</Button>\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled || busy} onClick={() => setPasting(true)}>{t('accountAddPaste')}</Button>\n <span className=\"cc-spacer\" />\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>{t('cancel')}</Button>\n </div>\n )}\n {busy && active?.phase !== 'naming' && pasting ? <Button variant=\"ghost\" size=\"sm\" onClick={close}>取消开通</Button> : null}\n </div>\n )\n}\n\n/**\n * The unified account card: every account the pool rotates through, one row\n * each, with its status and quota inline — so one account's facts no longer\n * have to be cross-read across separate surfaces.\n */\nfunction AccountsCard({ t, state, usage, login, disabled, actions, onRefresh, createEnrollment }: {\n t: Translate<SettingsCommandCodeKey>\n state: SettingsPageState\n usage: UsagePageState\n login: LoginPageState\n disabled: boolean\n actions: AccountActions\n onRefresh(): void\n createEnrollment(): AccountEnrollmentController\n}) {\n const [adding, setAdding] = useState(false)\n const [enrollment] = useState(createEnrollment)\n const snapshot = useSyncExternalStore(enrollment.store.subscribe, enrollment.store.getSnapshot)\n useEffect(() => { enrollment.activate(); return () => enrollment.dispose() }, [enrollment])\n const closeAdd = useCallback(() => setAdding(false), [])\n const { loading, shouldRefresh } = usageCardState(usage)\n // Ask the Host on first paint: CLI auth and composition keys are not\n // represented by browser credential references.\n useEffect(() => {\n if (shouldRefresh) onRefresh()\n }, [shouldRefresh, onRefresh])\n const rows = accountRows(state, usage, t).filter((row) => row.ref === undefined || !state.accountEnrollmentRefs.includes(row.ref))\n const multi = rows.length > 1\n const pinnedRow = rows.find((row) => row.id === state.activeAccount)\n return (\n <section className=\"cc-group\" aria-label={t('accountsTitle')}>\n <div className=\"cc-groupHead\">\n <h3 className=\"cc-groupTitle\">{t('accountsTitle')}</h3>\n <span className=\"cc-spacer\" />\n <button type=\"button\" className=\"cc-linkButton\" disabled={loading} onClick={() => { onRefresh(); void enrollment.refresh() }}>\n {loading ? t('usageRefreshing') : t('usageRefresh')}\n </button>\n </div>\n <p className=\"cc-groupDesc\">{multi ? t('accountsRotationHint') : t('accountsHint')}</p>\n {multi ? (\n <div className=\"cc-accountMode\">\n <span>{pinnedRow !== undefined ? t('accountModePinned', { name: pinnedRow.label }) : t('accountModeAuto')}</span>\n {pinnedRow !== undefined ? (\n <button type=\"button\" className=\"cc-reset\" disabled={disabled || state.accountBusy} onClick={() => void actions.setActive('')}>\n {t('accountActionUnpin')}\n </button>\n ) : null}\n </div>\n ) : null}\n {usage.status === 'error' ? (\n <p className=\"cc-rowError\" role=\"status\">\n {t('usageError')}{usage.error !== undefined && usage.error !== '' ? ` — ${usage.error}` : ''}\n </p>\n ) : null}\n {settingsWriteNotice(state.accountResult, t) || state.accountFailed !== undefined ? <p className=\"cc-rowError\" role=\"status\">{settingsWriteNotice(state.accountResult, t) || t('accountOpFailed')}</p> : null}\n {state.credentialRefreshFailed || state.accountResult?.refreshFailed || state.saveResult?.refreshFailed ? <div className=\"cc-rowError\" role=\"status\"><p>{t('writeRefreshFailed')}</p><button type=\"button\" className=\"cc-btn cc-btnSm\" onClick={actions.refreshCredentials}>{t('writeRefreshRetry')}</button></div> : null}\n {!adding && snapshot.error ? <p className=\"cc-rowError\" role=\"status\">{snapshot.error}</p> : null}\n {state.pendingCredentialCleanup.length > 0 ? (\n <div className=\"cc-rowError\" role=\"status\">\n <p>{t('accountCleanupPending')}</p>\n <button type=\"button\" className=\"cc-btn cc-btnSm\" disabled={disabled || state.accountBusy}\n onClick={() => { for (const ref of state.pendingCredentialCleanup) void actions.cleanup(ref) }}>\n {t('accountCleanupRetry')}\n </button>\n </div>\n ) : null}\n {snapshot.pending.filter((record) => record.id !== snapshot.active?.id).map((record) => (\n <div className=\"cc-rowError\" role=\"status\" key={record.id}>\n <p>{record.ref}:{record.message}</p>\n {record.phase === 'naming' && record.suggestedName ? (\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.recover(record, record.suggestedName)}>重试保存名称</Button>\n ) : null}\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.recover(record)}>\n {record.phase === 'naming' ? '接受已有名称' : '重试清理'}\n </Button>\n </div>\n ))}\n {snapshot.active?.phase === 'cleanup-needed' ? (\n <div className=\"cc-rowError\" role=\"status\">\n <p>{snapshot.active.message}</p>\n <Button variant=\"ghost\" size=\"sm\" disabled={disabled} onClick={() => void enrollment.recover(snapshot.active!)}>重试清理</Button>\n </div>\n ) : null}\n <div className=\"cc-accountList\">\n {rows.map((row) => (\n <AccountItem\n key={row.id}\n row={row}\n rows={rows}\n state={state}\n usage={usage}\n login={login}\n disabled={disabled}\n pinned={state.activeAccount === row.id}\n t={t}\n actions={actions}\n />\n ))}\n </div>\n {adding ? (\n <AddAccountPanel\n state={state}\n disabled={disabled}\n t={t}\n enrollment={enrollment}\n snapshot={snapshot}\n onClose={closeAdd}\n />\n ) : (\n <button type=\"button\" className=\"cc-addButton\" disabled={disabled} onClick={() => { enrollment.reset(); setAdding(true) }}>\n <span className=\"cc-addGlyph\" aria-hidden=\"true\" />\n {t('accountAdd')}\n </button>\n )}\n </section>\n )\n}\n\n/**\n * Show the save bar's \"saved\" confirmation 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 // The count lives in the shared controller and outlives this component, so\n // a remount (switching settings pages, reopening settings) sees a non-zero\n // count it did not witness. Only a save landing while mounted may flash.\n const seen = useRef(tick)\n useEffect(() => {\n if (tick === seen.current) return\n seen.current = tick\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\ntype SaveBarTone = 'pending' | 'error' | 'success'\n\ninterface SaveBarView {\n visible: boolean\n tone: SaveBarTone\n message: string\n /** Whether Discard/Save apply (hidden while only the saved confirmation shows). */\n actions: boolean\n}\n\n/**\n * What the save bar says. It exists only while there is something to act on\n * or to confirm: pending edits, a save in flight, a failure, or the brief\n * confirmation after a save landed. Account operations never reach it, they\n * commit on their own.\n */\nfunction saveBarView(state: SettingsPageState, savedVisible: boolean, t: Translate<SettingsCommandCodeKey>): SaveBarView {\n const notice = settingsWriteNotice(state.saveResult, t)\n if (notice) return { visible: true, tone: state.failed ? 'error' : 'pending', message: notice, actions: state.dirty || state.failed }\n if (state.failed) return { visible: true, tone: 'error', message: t('saveFailed'), actions: state.dirty || state.failed }\n if (state.dirty || state.saving) {\n return state.invalid\n ? { visible: true, tone: 'error', message: t('saveInvalid'), actions: true }\n : { visible: true, tone: 'pending', message: t('unsavedChanges'), actions: true }\n }\n if (savedVisible) return { visible: true, tone: 'success', message: t('saved'), actions: false }\n return { visible: false, tone: 'success', message: '', actions: false }\n}\n\n/** The save bar's leading status mark: a soft dot while pending, a glyph once there is an outcome. */\nfunction SaveBarIcon({ tone }: { tone: SaveBarTone }) {\n if (tone === 'pending') return <span className=\"cc-saveBarIcon\" aria-hidden=\"true\"><span className=\"cc-saveBarPulse\" /></span>\n return (\n <span className=\"cc-saveBarIcon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" />\n {tone === 'success' ? <path d=\"M5.2 8.2l1.9 1.9 3.7-3.9\" /> : <path d=\"M8 4.8v3.6M8 11.1v.1\" />}\n </svg>\n </span>\n )\n}\n\n/**\n * The floating save bar: pinned to the bottom of the settings scrollport and\n * slid out of view when there is nothing to save. It stays mounted so it can\n * animate out, and keeps showing its last message while it does (the state\n * that hid it has no message of its own).\n */\nfunction SaveBar({ view, state, t, onDiscard, onSave }: {\n view: SaveBarView\n state: SettingsPageState\n t: Translate<SettingsCommandCodeKey>\n onDiscard(): void\n onSave(): void\n}) {\n const last = useRef(view)\n if (view.visible) last.current = view\n const shown = view.visible ? view : last.current\n return (\n <div className=\"cc-saveBarDock\">\n <div\n className={`cc-saveBar cc-saveBar-${shown.tone}${view.visible ? ' cc-saveBarShown' : ''}`}\n role=\"region\"\n aria-label={t('save')}\n aria-hidden={!view.visible}\n >\n <SaveBarIcon tone={shown.tone} />\n <p className=\"cc-saveBarText\" role=\"status\" aria-live=\"polite\" title={shown.message}>{shown.message}</p>\n {shown.actions ? (\n <div className=\"cc-saveBarActions\">\n {/* Own buttons rather than the primitives: they are sized to sit\n concentrically inside the bar (see .cc-saveBar). */}\n <button\n type=\"button\"\n className=\"cc-saveBarButton cc-saveBarGhost\"\n disabled={!view.visible || (!state.dirty && !state.failed) || state.saving}\n onClick={onDiscard}\n >\n {t('discard')}\n </button>\n <button\n type=\"button\"\n className=\"cc-saveBarButton cc-saveBarPrimary\"\n disabled={!view.visible || !state.dirty || state.invalid || state.saving}\n onClick={onSave}\n >\n {t(state.saving ? 'saving' : 'save')}\n </button>\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n\n/** The settings page body: accounts, then the staged provider settings. */\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 savedVisible = useSavedFlash(state.savedCount)\n const updateVersion = usePluginUpdate()\n // 账号行共享稳定的操作对象;新增账号的过程则由页面自己的控制器持有。\n const {\n renameAccount, removeAccount, retryCredentialCleanup, setAccountKey, clearAccountKey,\n setActiveAccount, setAccountModels, beginLogin, cancelLogin, refreshCredentials,\n } = props\n const actions = useMemo<AccountActions>(() => ({\n rename: renameAccount,\n remove: removeAccount,\n cleanup: retryCredentialCleanup,\n refreshCredentials,\n setKey: setAccountKey,\n clearKey: clearAccountKey,\n setActive: setActiveAccount,\n setModels: setAccountModels,\n beginLogin,\n cancelLogin,\n }), [renameAccount, removeAccount, retryCredentialCleanup, setAccountKey, clearAccountKey, setActiveAccount, setAccountModels, beginLogin, cancelLogin, refreshCredentials])\n const bar = saveBarView(state, savedVisible, t)\n const form = { state, disabled, t, onEdit: props.edit, onReset: props.resetField }\n return (\n <section className={bar.visible ? 'cc-section cc-sectionWithBar' : 'cc-section'} aria-label={t('title')}>\n <h2 className=\"cc-title\">{t('title')}</h2>\n <p className=\"cc-intro\">{t('intro')}</p>\n {props.openAnalytics ? <Button variant=\"ghost\" size=\"sm\" onClick={props.openAnalytics}>{t('openAnalytics')}</Button> : null}\n {!state.writable ? <p className=\"cc-readOnly\" role=\"status\">{t('readOnly')}</p> : null}\n <AccountsCard\n t={t}\n state={state}\n usage={usage}\n login={login}\n disabled={disabled}\n actions={actions}\n onRefresh={props.refreshUsage}\n createEnrollment={props.createEnrollment}\n />\n <ModelsCard {...form} onSelect={props.editVisibleModels} onClear={props.clearVisibleModels} />\n <PrivacyCard {...form} />\n <IntegrationsCard {...form} />\n <AdvancedSection {...form} />\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 <SaveBar view={bar} state={state} t={t} onDiscard={props.discard} onSave={props.save} />\n </section>\n )\n}\n","/**\n * The shared login row: one field row that starts the Host-side browser login,\n * links to the Studio authorization page while the attempt is live, and reports\n * the outcome. Rendered by BOTH the settings page (`section.tsx`) and the\n * Models-page provider card (`card.tsx`) so the two surfaces share one\n * component and one hint state machine — whose copy/class logic lives in the\n * JSX-free `./login.ts` (`loginHint`/`loginFailureCopy`) so node tests can drive\n * every phase. This file only renders it.\n *\n * @module dsh-commandcode-provider/client/login-row\n */\n\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsCommandCodeKey } from './locales.ts'\nimport { loginHint, loginStateForTarget } from './login.ts'\nimport type { LoginPageState } from './login.ts'\n\n/** One login row's props (same face both surfaces supply). */\nexport interface LoginRowProps {\n state: LoginPageState\n /** Only the matching attempt appears in this row; omitted means default. */\n targetRef?: string\n disabled: boolean\n disabledHint?: string | undefined\n t: Translate<SettingsCommandCodeKey>\n onBegin(): void\n onCancel(): void\n}\n\nexport function LoginRow({ state, targetRef, disabled, disabledHint, t, onBegin, onCancel }: LoginRowProps) {\n const { visible: visibleState, busyElsewhere } = loginStateForTarget(state, targetRef)\n const busy = visibleState.phase === 'starting' || visibleState.phase === 'waiting'\n const hint = loginHint(visibleState, t)\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 || busyElsewhere} onClick={onBegin}>{t('loginButton')}</button>\n )}\n </span>\n </div>\n {visibleState.authUrl !== undefined ? (\n <p className=\"cc-hint\">\n <a className=\"cc-loginLink\" href={visibleState.authUrl} target=\"_blank\" rel=\"noreferrer\">{t('loginOpenLink')}</a>\n </p>\n ) : null}\n <p className={hint.className} title={hint.title}>{disabled && !busy && disabledHint !== undefined ? disabledHint : hint.text}</p>\n </div>\n )\n}\n","/**\n * The Command Code configuration panel inside the harness Models settings page,\n * rendered through the `settings.models.provider-card` keyed slot 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 per provider row through its own\n * 编辑 button, and for a namespace it curates no layout for (`llm-commandcode`)\n * that editor is a bare shell: a config hint over a permanently disabled apply.\n * This panel takes its place — it watches the slot outlet's siblings and, while\n * the official editor is open, hides the useless shell and shows the real\n * controls in its slot (credential/route badges, API-key field, sign-in,\n * discard/save). Closed, it renders nothing and the row looks exactly like any\n * other provider row.\n *\n * The slot's owner props (`configured`, `keyConfigured`) mirror what the Models\n * page already knows; the authoritative credential facts still come from this\n * plugin's `CommandCodeSettingsController` — shared with the dedicated settings\n * page, so the two surfaces can never disagree about whether a key is stored.\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. Styles ride the page stylesheet the client entry injects\n * once; 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 { settingsWriteNotice, type SettingsCommandCodeKey } from './locales.ts'\nimport type { SettingsPageState, StagedField } from './settings.ts'\nimport type { LoginPageState } from './login.ts'\nimport { LoginRow } from './login-row.tsx'\n\n/**\n * The Models-page extension slots, merged into the SlotMap with the exact\n * declarations ui-settings-models ships. The merge must stay structurally\n * identical to upstream's (kind/scope/owner), or a dsh carrying its own\n * declaration would fail the duplicate-merge check at 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 readonly displayName: string\n /** The settings namespace the row configures (the slot's dispatch key). */\n readonly settingsNs: string\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 and add-provider\n * cards, where it is always open. The editor is the only such sibling whose\n * CSS module class carries the `editor` stem (`<hash>_editor`); the row header\n * and the add card's provider select never do, so the lookup needs no hash\n * 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 refreshCredentials(): 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/**\n * Decide the card's posture from one settings snapshot. Pure: the component\n * subscribes once and passes the snapshot in, so hook order never depends\n * on the registration→live transition. (The owner facts stay on the\n * component — only the snapshot decides the posture.)\n */\nexport function cardMode(\n snapshot: SettingsPageState | undefined,\n): CardMode {\n if (snapshot === undefined) return { kind: 'registration' }\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/** Credential-state badge: the solid pill when set, the muted outline when not. */\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/** The key paste field, with the show/hide toggle over it. */\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=\"new-password\"\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, add-provider draft).\n *\n * Closed (the official 编辑 toggle off) it renders nothing: the row head the\n * Models page owns already names the provider and shows the credential dot, so\n * a page full of providers stays compact. Open, it hides that editor shell and\n * shows the real controls — badges, API-key field, sign-in, discard/save.\n */\nexport function CommandCodeProviderCard(props: CommandCodeCardProps & ProviderCardOwnerProps) {\n const { t } = props\n // Single subscription: the whole snapshot drives posture + body together.\n const state = props.useCommandCodeSettings !== undefined\n ? props.useCommandCodeSettings((snapshot) => snapshot)\n : undefined\n const mode = cardMode(state)\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 notice = settingsWriteNotice(state?.saveResult, t) || (state?.failed ? t('saveFailed') : '')\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 stable\n // neighbor, so watch ITS siblings for the editor's mount/unmount. The outlet\n // stays mounted either way — it is the observation anchor — so the closed\n // 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 the\n // 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: it is\n // 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(state.apiKeyKnown ? 'apiKeyUnset' : 'writeStateUnknown')} />\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 <LoginRow\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 {notice ? <p className=\"cc-failed\" role=\"status\">{notice}</p> : null}\n {state?.credentialRefreshFailed || state?.saveResult?.refreshFailed ? <button type=\"button\" className=\"cc-reset\" onClick={props.refreshCredentials}>{t('writeRefreshRetry')}</button> : null}\n <button\n type=\"button\"\n className=\"cc-reset\"\n disabled={(!dirty && !state?.failed) || 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","/** 模型分析沿用宿主语言;每个数值有独立标签,缺失样本与试算前提必须可见。 */\nexport const ANALYTICS_COPY_ZH = {\n analyticsNav: '模型分析', quotaNav: '账号额度',\n analysisRecent: '最近会话', analysisRange: '指定时间', analysisLimit: '会话数量', analysisFrom: '开始日期', analysisTo: '结束日期', analysisApply: '读取统计',\n analysisLoading: '正在读取历史记录…', analysisUnavailable: '宿主未提供历史查询服务,无法统计关闭后的会话。', analysisEmpty: '所选范围内没有 Command Code 请求记录。',\n analysisInvalid: '请输入 1–100 个会话,或不超过 366 天的有效日期范围。', analysisScope: '统计范围', analysisScanned: '已读取会话', analysisMatched: '含请求会话', analysisUnreadable: '读取失败', analysisSkipped: '已跳过',\n analysisPartial: '结果不完整:历史超过读取上限,或部分记录不可读。金额只覆盖已读取且可计价的请求。', analysisCatalog: '模型目录暂不可用,历史统计仍可查看。',\n analysisUnpriced: '部分请求缺少用量或价格,金额与词元仅为已知小计。展开明细可查看样本覆盖。',\n analysisOverview: '用量总览', analysisSections: '分析内容', analysisHistory: '历史用量', analysisSimulation: '价格试算', analysisByModel: '模型用量比较', analysisModelHint: '比例条表示占已知成本小计的份额;展开查看明细。',\n analysisIntro: '查看历史用量,比较模型成本与响应表现。', analysisModel: '模型', analysisCostShare: '已知成本 / 占比', analysisNoShare: '无占比', analysisShareHint: '占全部已知成本小计',\n analysisSimulationHeading: '相同工作量价格试算', analysisSimulationHint: '计价覆盖不同的金额不能直接比较。', analysisSimulationCost: '试算成本', analysisCoverage: '计价覆盖', analysisUsd: '美元', analysisTokenUnit: '词元',\n analysisCost: '已知成本 · 美元', analysisRequests: '模型请求', analysisSessionCount: '会话数', analysisResponse: '平均响应', analysisFirstToken: '平均首词元', analysisSpeed: '输出速度', analysisSeconds: '秒', analysisSpeedUnit: '词元/秒',\n analysisPriced: '计价请求', analysisTimed: '响应样本', analysisFirstTokenSamples: '首词元样本', analysisDecodeSamples: '解码样本', analysisUsageSamples: '用量样本', analysisAverage: '每会话均摊', analysisMissing: '无数据',\n analysisDetails: '查看汇总明细', analysisTokens: '词元与缓存', analysisInput: '未缓存输入', analysisOutput: '输出', analysisCacheRead: '缓存读取', analysisCacheWrite: '缓存写入',\n analysisOutcome: '请求状态', analysisCompleted: '完成', analysisFailed: '失败', analysisRetries: '宿主重试', analysisCancelled: '取消', analysisUnknown: '未知状态', analysisSamples: '统计样本', analysisSessionCost: '会话与成本',\n analysisMonthly: '按该时间段折算 30 天', analysisMonthlyHint: '仅完整、全部计价且跨度至少一天的日期范围提供折算。',\n analysisRules: '统计口径与试算说明', analysisShortBasis: '按当前价格估算,非历史账单。缺失用量与耗时不会补零。',\n analysisBasis: '按当前价格快照重算;不是历史账单,不含订阅费和充值,词元用量不等于账号积分。仅有请求数量、没有任务边界;不计算任务质量或智能评分。旧记录缺失的用量和耗时不会补零。',\n analysisAssumption: '沿用原请求的词元与时段,对比不同模型的价格。换模型后的生成长度、缓存命中、重试和质量可能变化;不会调用模型或自动推荐。',\n analysisContext: '上下文词元', analysisCapabilities: '模型能力', analysisEfforts: '推理力度', analysisExcluded: '超出上下文', analysisUnknownPrice: '未知用量或价格', analysisSearch: '筛选试算模型', analysisSearchPlaceholder: '输入模型名称或标识', analysisNoMatches: '没有匹配的模型,请调整筛选条件。',\n analysisImages: '支持图片', analysisTextOnly: '仅文本', analysisNoEfforts: '未提供推理力度',\n analysisCoverageHint: '耗时从步骤或重试开始计至模型结算;包含前置处理,不含后续工具执行。首词元包含推理与工具参数。速度按有解码计时的输出词元总量计算。试算未校验图片及工具兼容性,也不代表账号已获授权。',\n effortNone: '关闭 (none)', effortLow: '低 (low)', effortMedium: '中 (medium)', effortHigh: '高 (high)', effortXhigh: '极高 (xhigh)', effortMax: '最高 (max)',\n} as const\nexport type AnalyticsKey = keyof typeof ANALYTICS_COPY_ZH\n/** 按项目约定,错误、缺失与读取状态在各语言环境中统一为中文。 */\nexport const ANALYTICS_COPY_EN: Record<AnalyticsKey, string> = {\n analyticsNav: 'Model analysis', quotaNav: 'Account quota',\n analysisRecent: 'Recent sessions', analysisRange: 'Date range', analysisLimit: 'Session count', analysisFrom: 'Start date', analysisTo: 'End date', analysisApply: 'Read statistics',\n analysisLoading: ANALYTICS_COPY_ZH.analysisLoading, analysisUnavailable: ANALYTICS_COPY_ZH.analysisUnavailable, analysisEmpty: ANALYTICS_COPY_ZH.analysisEmpty,\n analysisInvalid: ANALYTICS_COPY_ZH.analysisInvalid, analysisScope: 'Scope', analysisScanned: 'Sessions read', analysisMatched: 'Sessions with requests', analysisUnreadable: 'Read failures', analysisSkipped: 'Skipped',\n analysisPartial: ANALYTICS_COPY_ZH.analysisPartial, analysisCatalog: ANALYTICS_COPY_ZH.analysisCatalog,\n analysisUnpriced: ANALYTICS_COPY_ZH.analysisUnpriced,\n analysisOverview: 'Usage overview', analysisSections: 'Analysis sections', analysisHistory: 'Recorded usage', analysisSimulation: 'Price simulation', analysisByModel: 'Model usage comparison', analysisModelHint: 'Bars show each share of the known cost subtotal; expand for details.',\n analysisIntro: 'Review recorded usage and compare model cost and response times.', analysisModel: 'Model', analysisCostShare: 'Known cost / share', analysisNoShare: ANALYTICS_COPY_ZH.analysisNoShare, analysisShareHint: 'Share of the known cost subtotal',\n analysisSimulationHeading: 'Price simulation for the same workload', analysisSimulationHint: 'Amounts with different priced coverage are not directly comparable.', analysisSimulationCost: 'Simulated cost', analysisCoverage: 'Priced coverage', analysisUsd: 'USD', analysisTokenUnit: 'tokens',\n analysisCost: 'Known cost · USD', analysisRequests: 'Model requests', analysisSessionCount: 'Sessions', analysisResponse: 'Mean response', analysisFirstToken: 'Mean first token', analysisSpeed: 'Output speed', analysisSeconds: 's', analysisSpeedUnit: 'tokens/s',\n analysisPriced: 'Priced requests', analysisTimed: 'Response samples', analysisFirstTokenSamples: 'First-token samples', analysisDecodeSamples: 'Decode samples', analysisUsageSamples: 'Usage samples', analysisAverage: 'Per session', analysisMissing: ANALYTICS_COPY_ZH.analysisMissing,\n analysisDetails: 'View aggregate details', analysisTokens: 'Tokens and cache', analysisInput: 'Uncached input', analysisOutput: 'Output', analysisCacheRead: 'Cache read', analysisCacheWrite: 'Cache write',\n analysisOutcome: 'Request outcomes', analysisCompleted: 'Completed', analysisFailed: 'Failed', analysisRetries: 'Host retries', analysisCancelled: 'Cancelled', analysisUnknown: 'Unknown outcome', analysisSamples: 'Samples', analysisSessionCost: 'Sessions and cost',\n analysisMonthly: '30-day extrapolation from this range', analysisMonthlyHint: 'Requires a complete, fully priced date range spanning at least one day.',\n analysisRules: 'Statistics and simulation notes', analysisShortBasis: 'Estimated at current prices, not an invoice. Missing usage and timing stay unknown.',\n analysisBasis: 'Repriced with the current snapshot; not an invoice. Excludes subscriptions and top-ups. Tokens are not account credits. Requests have no task boundaries; no task quality or intelligence scores. Missing usage and timing stay unknown.',\n analysisAssumption: 'Compares model prices using original tokens and request times. Output length, cache hits, retries and quality may change with another model. Makes no model calls or automatic recommendations.',\n analysisContext: 'Context tokens', analysisCapabilities: 'Model capabilities', analysisEfforts: 'Reasoning efforts', analysisExcluded: 'Over context limit', analysisUnknownPrice: 'Unknown usage or price', analysisSearch: 'Filter simulation models', analysisSearchPlaceholder: 'Model name or ID', analysisNoMatches: ANALYTICS_COPY_ZH.analysisNoMatches,\n analysisImages: 'Images supported', analysisTextOnly: 'Text only', analysisNoEfforts: 'No reasoning efforts listed',\n analysisCoverageHint: 'Response time runs from step/retry start to model settlement, includes preparation and excludes subsequent tools. First token includes reasoning and tool arguments. Speed uses output tokens with decode timing. Simulation does not validate image/tool compatibility or prove account entitlement.',\n effortNone: 'None', effortLow: 'Low', effortMedium: 'Medium', effortHigh: 'High', effortXhigh: 'Extra high', effortMax: 'Max',\n}\n","/**\n * Bilingual copy for the Command Code **plans & quota panel** (the sidebar\n * footer card and the center-column dashboard it opens).\n *\n * The panel follows the harness's active language: `PANEL_LOCALE_NS` is a\n * registered locale namespace (`ctx.locale.register`), both panel slot\n * registrations declare it, and the renderer hands the component a `t` seat\n * whose identity changes on a language switch (so a memoized panel re-renders).\n * {@link buildPanelView} takes that translator as an input and builds every\n * string through it, so the projection stays React-free and testable and no\n * component carries copy of its own. The settings page keeps its own\n * `settings.commandcode` namespace (see `./locales.ts`); the two never mix.\n *\n * @module dsh-commandcode-provider/client/panel-copy\n */\n\nimport { ANALYTICS_COPY_ZH, ANALYTICS_COPY_EN, type AnalyticsKey } from './analytics-copy.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Copy of the plans & quota panel (footer card + dashboard). */\n 'panel.commandcode': PanelKey\n }\n}\n\n/**\n * The plans & quota panel key set. `zh` is the source of truth for the key set\n * (repo convention); en must carry the exact same keys — a mismatch is a\n * compile error at the register site.\n */\nexport type PanelKey =\n | AnalyticsKey\n /** Footer card title and panel heading. */\n | 'nav'\n /** Panel sub-heading under the title. */\n | 'subtitle'\n /** Refresh button / in-flight label. */\n | 'refresh'\n | 'refreshing'\n /** Dashboard exit: the button's accessible name and its tooltip. */\n | 'close'\n | 'closeHint'\n /** First-paint fetch. */\n | 'loading'\n /** No credential at all: how to get one. */\n | 'noKey'\n | 'noKeyHint'\n /** Report section headings. */\n | 'plan'\n | 'credits'\n | 'limits'\n | 'usage'\n /** Monthly credit state and its tiles. */\n | 'monthly'\n | 'monthlyLimit'\n | 'monthlyUsed'\n | 'remaining'\n | 'purchased'\n | 'free'\n /** Usage-window rows (long labels in the dashboard, short in the footer). */\n | 'fiveHour'\n | 'weekly'\n | 'fiveHourShort'\n | 'weeklyShort'\n | 'windowUnlimited'\n | 'exceeded'\n | 'exhausted'\n | 'resets'\n /** Usage tiles. */\n | 'requests'\n | 'failed'\n | 'successRate'\n | 'spend'\n | 'tokens'\n | 'tokensIn'\n | 'tokensOut'\n /** Meta line. */\n | 'periodEnds'\n | 'updated'\n | 'partial'\n /** Rotation state on an account. */\n | 'active'\n | 'coolingDown'\n | 'invalidKey'\n /** Footer-card plan fallbacks. */\n | 'unconfigured'\n | 'unavailable'\n /** Whole-report failures (mirrors the settings card's blocked taxonomy). */\n | 'errorInvalidKey'\n | 'errorInvalidKeyHint'\n | 'errorServiceUnavailable'\n | 'errorServiceUnavailableHint'\n | 'errorNetwork'\n | 'errorNetworkHint'\n | 'errorInvalidResponse'\n | 'errorInvalidResponseHint'\n /** A fetch that failed for any other reason. */\n | 'errorGeneric'\n\n/** The locale namespace both panel slots bind their `t` seat to. */\nexport const PANEL_LOCALE_NS = 'panel.commandcode'\n\n/** A panel translator: one key in, one localized string out. */\nexport type PanelTranslator = (key: PanelKey) => string\n\n/** The panel's Simplified Chinese string table (the key-set source of truth). */\nexport const PANEL_COPY_ZH: Record<PanelKey, string> = {\n ...ANALYTICS_COPY_ZH,\n nav: 'Command Code',\n subtitle: '套餐、额度与配额窗口',\n refresh: '刷新',\n refreshing: '刷新中…',\n close: '关闭',\n closeHint: '返回会话',\n loading: '正在获取账户用量…',\n noKey: '尚未配置 API 密钥',\n noKeyHint: '在 设置 → Command Code 中粘贴密钥或登录后,点击刷新。',\n plan: '套餐',\n credits: '额度',\n limits: '配额窗口',\n usage: '用量',\n monthly: '月额度',\n monthlyLimit: '月额度上限',\n monthlyUsed: '本月已用',\n remaining: '剩余',\n purchased: '已购',\n free: '赠送',\n fiveHour: '5 小时窗口',\n weekly: '每周窗口',\n fiveHourShort: '5 小时',\n weeklyShort: '每周',\n windowUnlimited: '不限',\n exceeded: '已超限',\n exhausted: '已用尽',\n resets: '重置于',\n requests: '请求',\n failed: '失败',\n successRate: '成功率',\n spend: '花费',\n tokens: 'Token',\n tokensIn: '入',\n tokensOut: '出',\n periodEnds: '账期截止',\n updated: '更新于',\n partial: '部分端点数据不可用',\n active: '当前使用',\n coolingDown: '限额冷却中',\n invalidKey: '密钥无效',\n unconfigured: '未配置',\n unavailable: '无数据',\n errorInvalidKey: 'API 密钥无效或已过期',\n errorInvalidKeyHint: '服务端拒绝了全部请求(401)。请检查该账户的密钥,或到 commandcode.ai 控制台重新生成。',\n errorServiceUnavailable: 'Command Code 服务暂时不可用',\n errorServiceUnavailableHint: '服务端返回错误(5xx),请稍后点击刷新重试。',\n errorNetwork: '无法连接 Command Code 服务',\n errorNetworkHint: '所有请求都没有到达服务端。请检查网络连接或 API 地址设置。',\n errorInvalidResponse: 'Command Code 响应无法读取',\n errorInvalidResponseHint: '已收到响应,但正文读取或解析失败。下方详情可区分读取超时、中断与格式异常;可先点击刷新重试。',\n errorGeneric: '用量获取失败',\n}\n\n/** The panel's English string table (must mirror {@link PANEL_COPY_ZH}). */\nexport const PANEL_COPY_EN: Record<PanelKey, string> = {\n ...ANALYTICS_COPY_EN,\n nav: 'Command Code',\n subtitle: 'Plans, credits and quota windows',\n refresh: 'Refresh',\n refreshing: 'Refreshing…',\n close: 'Close',\n closeHint: 'Back to the conversation',\n loading: 'Loading account usage…',\n noKey: 'No API key configured',\n noKeyHint: 'Paste a key — or sign in — under Settings → Command Code, then refresh.',\n plan: 'Plan',\n credits: 'Credits',\n limits: 'Quota windows',\n usage: 'Usage',\n monthly: 'Monthly',\n monthlyLimit: 'Monthly limit',\n monthlyUsed: 'Monthly used',\n remaining: 'Remaining',\n purchased: 'Purchased',\n free: 'Free',\n fiveHour: '5-hour window',\n weekly: 'Weekly window',\n fiveHourShort: '5-hour',\n weeklyShort: 'Weekly',\n windowUnlimited: 'unlimited',\n exceeded: 'Exceeded',\n exhausted: 'Used up',\n resets: 'Resets',\n requests: 'Requests',\n failed: 'failed',\n successRate: 'Success rate',\n spend: 'Spend',\n tokens: 'Tokens',\n tokensIn: 'in',\n tokensOut: 'out',\n periodEnds: 'Period ends',\n updated: 'Updated',\n partial: 'Some endpoint data unavailable',\n active: 'Active',\n coolingDown: 'Cooling down',\n invalidKey: 'Invalid key',\n unconfigured: 'Not configured',\n unavailable: 'No data',\n errorInvalidKey: 'API key invalid or expired',\n errorInvalidKeyHint: 'The server rejected every request (401). Check the key for this account, or generate a new one in the commandcode.ai console.',\n errorServiceUnavailable: 'The Command Code service is temporarily unavailable',\n errorServiceUnavailableHint: 'The server returned errors (5xx). Try Refresh again in a moment.',\n errorNetwork: 'Could not reach the Command Code service',\n errorNetworkHint: 'No request reached the server. Check your network connection or the API base setting.',\n errorInvalidResponse: 'Could not read the Command Code response',\n errorInvalidResponseHint: 'Responses arrived, but reading or parsing their bodies failed. Details below distinguish timeouts, interrupted reads, and invalid formats. Try Refresh again.',\n errorGeneric: 'Could not fetch account usage',\n}\n\n/** Every panel key, in the English table's declaration order. */\nexport const PANEL_KEYS: readonly PanelKey[] = Object.keys(PANEL_COPY_EN) as PanelKey[]\n\n/**\n * The English translator. Used as the fallback when no locale seat is\n * available (a defensive path: every supported engine supplies one) and as the\n * default in tests that only assert the projection's figures.\n */\nexport function panelTextEN(key: PanelKey): string {\n return PANEL_COPY_EN[key] ?? key\n}\n","/**\n * View model for the Command Code plans & quota panel (the sidebar footer card\n * and the dashboard it opens).\n *\n * JSX-free and React-free, mirroring `./settings.ts` / `./usage.ts`: it turns\n * the shared usage snapshot into one presentation tree both components render,\n * and owns the one shared side effect (the throttled auto refresh below). Node\n * tests drive everything here without a DOM.\n *\n * Every displayed string is decided here, as a `PanelKey` plus a `text` record\n * resolved through the injected translator, so the components carry no copy of\n * their own and the panel follows the harness's active language\n * (`./panel-copy.ts` owns both dictionaries and the `panel.commandcode` locale\n * namespace; the slots hand the translator in).\n *\n * @module dsh-commandcode-provider/client/panel\n */\n\nimport type { CommandCodeUsageReport } from '../adapter.ts'\nimport type { CommandCodeAccountUsage } from '../usage-wire.ts'\nimport type { UsagePageState } from './usage.ts'\nimport { formatMoney, formatMoneyExact, formatSuccessRate, formatTokensCompact, formatResetAt } from '../display-format.ts'\nimport { PANEL_KEYS, panelTextEN } from './panel-copy.ts'\nimport type { PanelKey, PanelTranslator } from './panel-copy.ts'\n\n/** One quota window (5-hour or weekly) in display form. */\nexport interface PanelWindowView {\n /** Row-label key into the view's `text` record. */\n label: PanelKey\n /** `used / cap`, or just `used` when the window is uncapped. */\n value: string\n /** The window reports a cap, so `percent` is meaningful. */\n capped: boolean\n /** Percentage actually consumed (may exceed 100 when over the cap). */\n percent: number\n /** Fill width for the bar, clamped to [0, 100]. */\n barPercent: number\n /** Window is over its cap. */\n exceeded: boolean\n /** Local reset time, empty when the endpoint reported none. */\n resetsAt: string\n}\n\n/**\n * Monthly credit state. Consumption is derived the way the official CLI derives\n * it (`getCreditDepletionPct`): the plan's credit total is the LIMIT and the\n * billing endpoint's `credits.monthlyCredits` is the REMAINING balance, so\n * consumption is `limit - remaining`. Purchased and free credits are separate\n * balances that extend what an account can spend, so they are their own tiles.\n */\nexport interface PanelMonthlyView {\n /**\n * A ratio is meaningful — the plan published a credit total AND the billing\n * endpoint published the balance left of it. When false the view draws no bar:\n * a percentage needs both halves, and inventing either is how a failed billing\n * call becomes a confident \"100% used\".\n */\n known: boolean\n /** Plan credit total for the period (the limit); a dash when unreported. */\n limit: string\n /** Consumed this period (`limit - remaining`); a dash until both are known. */\n used: string\n /** Credits still available; a dash when the balance was not reported. */\n remaining: string\n /** Purchased top-up balance. */\n purchased: string\n /** Promotional balance. */\n free: string\n /** Consumption as a percentage of the limit; 0 when there is no ratio. */\n percent: number\n /** Fill width for the bar, clamped to [0, 100]. */\n barPercent: number\n /** The plan's credits are used up. */\n exhausted: boolean\n /** Billing period end, local date; empty when unreported. */\n periodEnds: string\n}\n\n/** One compact bar in the sidebar footer card. */\nexport interface PanelFooterBar {\n /** Row label key (short forms: `Monthly`, `5-hour`, `Weekly`). */\n label: PanelKey\n /** Printed right-hand percentage, e.g. `32%`; empty when there is no ratio. */\n percent: string\n /** Fill width, clamped to [0, 100]. */\n barPercent: number\n /** Render in the warning colour. */\n warn: boolean\n /**\n * This window's own spend against its limit, e.g. `$1.32 / $6.00`. RENDERED,\n * not just a tooltip: the card exists to show these figures, and the\n * magnitudes are small dollar amounts.\n */\n detail: string\n}\n\n/** One usage tile. */\nexport interface PanelStatView {\n label: PanelKey\n value: string\n /** Secondary line, empty when there is none. */\n sub: string\n}\n\n/** One pool account's report, ready to render. */\nexport interface PanelAccountView {\n id: string\n label: string\n /** The account's display name (user name, else account name); empty when unreported. */\n owner: string\n /** Subscription display name; empty when unreported. */\n planName: string\n /** Subscription status when it is not a plain `active`; empty otherwise. */\n planStatus: string\n /** Rotation/credential state ('invalidKey' / 'coolingDown'); undefined when plain. */\n mark: PanelKey | undefined\n /** Known cooldown end, appended to the cooling-down badge; empty otherwise. */\n cooldownUntil: string\n /** No credential resolved for this slot. */\n unconfigured: boolean\n /** Billing period end, empty when unreported. */\n periodEnds: string\n /** Whether the account currently serves requests. */\n active: boolean\n /** Monthly credit state; undefined when neither endpoint reported it. */\n monthly: PanelMonthlyView | undefined\n windows: PanelWindowView[]\n stats: PanelStatView[]\n}\n\n/** What actually went wrong, once — for the alert box. */\nexport interface PanelFailureView {\n title: PanelKey\n /** The actionable line under the title. */\n hint: PanelKey\n /** The underlying transport message, shown small; empty when there is none. */\n detail: string\n}\n\n/** The whole panel, in render order. */\nexport interface PanelView {\n /** Every localized string this view references, by key. */\n text: Partial<Record<PanelKey, string>>\n /** Footer-card plan text (`Go`, `Pro`, …), or a state word. */\n planName: string\n /** Footer-card rotation/credential state line; empty when nothing to say. */\n status: string\n /**\n * The compact bars the sidebar footer card stacks: the two quota windows an\n * account actually runs into, 5-hour first then weekly. The monthly bar\n * belongs to the DASHBOARD alone — it moves once a billing period, whereas\n * these two are what stop a session — and a window with no cap is left out\n * (no ratio to draw).\n */\n footerBars: PanelFooterBar[]\n /**\n * This period's spend in dollars; empty when the usage endpoint reported\n * nothing. NOT drawn as its own row — the card's visible figures are the two\n * windows' own spend (see {@link PanelFooterBar.detail}) — so it rides the\n * tooltip and the accessible name instead.\n */\n cost: string\n /**\n * The footer card's accessible name and tooltip: `Command Code · Pro ·\n * 5-hour $0.04 / $3.00 (1%) · Weekly $1.32 / $6.00 (22%) · Spend $1.32`.\n * Always starts with the visible title, so the accessible name contains the\n * visible label.\n */\n footTitle: string\n /** Every account, in rotation order (empty when there is nothing to show). */\n accounts: PanelAccountView[]\n /** Id of the account the panel opens on (the serving one), if any. */\n selectedId: string | undefined\n /** That account's view, for the footer card; undefined with no accounts. */\n selected: PanelAccountView | undefined\n /** A fetch is in flight and no data has landed for this paint. */\n loading: boolean\n /** No credential is configured at all. */\n noKey: boolean\n /** Report-level failure box; undefined when the report is usable. */\n failure: PanelFailureView | undefined\n /** A fetch failed while data is still on screen. */\n staleError: string | undefined\n /** Endpoint-level partial failure note; undefined when every endpoint answered. */\n partial: PanelKey | undefined\n /** Freshness line, empty when nothing has been fetched. */\n updatedAt: string\n}\n\n/** Inputs {@link buildPanelView} needs beyond the usage snapshot. */\nexport interface PanelViewInput {\n usage: UsagePageState\n /** Whether any account holds a credential (the settings controller's fact). */\n apiKeyConfigured: boolean\n /**\n * Locale translator for every label the view composes. The panel slots bind\n * their `t` seat to the `panel.commandcode` namespace and pass it here; an\n * omitted one falls back to English (the tests' default, and the defensive\n * path when no locale face is installed).\n */\n t?: PanelTranslator\n}\n\n/** A quota window's state as the wire carries it. */\ninterface WindowInput {\n used: number\n cap: number\n exceeded: boolean\n resetAt: number\n}\n\n/** `$1.23`, and `$0.0123` only when the amount is too small for cents to show it. */\nfunction money(value: number): string {\n if (value === 0) return formatMoney(0)\n return Math.abs(value) < 0.01 ? formatMoneyExact(value) : formatMoney(value)\n}\n\n/**\n * What a figure shows when the endpoint that carries it did not report one. A\n * dash, never a zero: the panel exists to state what the account has spent, so\n * \"we were not told\" has to look different from \"nothing\".\n */\nconst UNREPORTED = '—'\n\n/** Local reset time; empty when the endpoint reported none. */\nfunction resetText(ms: number): string {\n return formatResetAt(ms)\n}\n\n/** Local short date; empty when unset. */\nfunction dateText(ms: number): string {\n if (ms <= 0) return ''\n return new Date(ms).toLocaleDateString()\n}\n\n/** Local time-of-day; empty when unset. */\nfunction timeText(ms: number): string {\n if (ms <= 0) return ''\n return new Date(ms).toLocaleTimeString()\n}\n\n/**\n * Consumption as a percentage, NOT clamped at 100 — an over-quota window\n * reports its real overshoot (150%), which is what the printed figure should\n * say. Bar widths clamp separately via {@link barPercent}.\n */\nfunction rawPercent(used: number, cap: number): number {\n if (cap <= 0) return 0\n return Math.round((used / cap) * 100)\n}\n\n/** A percentage usable as a CSS width, clamped into [0, 100]. */\nfunction barPercent(percent: number): number {\n return Math.min(100, Math.max(0, percent))\n}\n\n/** Build one quota-window view. */\nfunction windowView(label: PanelKey, limit: WindowInput): PanelWindowView {\n const percent = rawPercent(limit.used, limit.cap)\n const capped = limit.cap > 0\n return {\n label,\n // Spend only: an uncapped window has no denominator, so its row pairs this\n // figure with the \"unlimited\" label instead of a `used / cap` it lacks.\n value: capped ? `${money(limit.used)} / ${money(limit.cap)}` : money(limit.used),\n capped,\n percent,\n barPercent: barPercent(percent),\n exceeded: limit.exceeded,\n resetsAt: resetText(limit.resetAt),\n }\n}\n\n/**\n * Build the monthly credit view from the two endpoints that carry it.\n *\n * The limit is the PLAN's credit total, not the billing endpoint's\n * `monthlyCredits` (that field is a remaining balance — see\n * {@link PanelMonthlyView}), so a plan that publishes no total still shows its\n * balances, just without a ratio.\n *\n * The trap this guards: a MISSING balance is not a consumed one. The billing\n * endpoint is one of four the report fetches in parallel, so it fails on its\n * own while the plan still arrives, and reading the absent balance as 0 turns\n * that partial failure into `limit - 0 = limit` — a confident \"100% used\" for\n * an account that may have spent nothing. The official CLI draws no meter unless\n * the credits payload is present at all (`hasCreditsInfo`); every derived figure\n * here stays a placeholder until the balance reported.\n */\nfunction monthlyView(report: CommandCodeUsageReport): PanelMonthlyView | undefined {\n const credits = report.credits\n const plan = report.plan\n if (credits === undefined && plan === undefined) return undefined\n\n const limitValue = plan?.monthlyCredits ?? null\n // Only an EXPLICIT `false` means the balance was omitted. An unset flag comes\n // from a Host half older than the field, which always sent a real number.\n const remainingReported = credits !== undefined && credits.monthlyReported !== false\n const remaining = remainingReported ? Math.max(0, credits.monthlyCredits) : 0\n // A ratio needs BOTH halves: the plan's total and the balance left of it.\n const known = limitValue !== null && limitValue > 0 && remainingReported\n const used = known ? Math.max(0, limitValue - remaining) : 0\n const percent = known ? rawPercent(used, limitValue) : 0\n\n return {\n known,\n limit: limitValue !== null ? money(limitValue) : UNREPORTED,\n used: known ? money(used) : UNREPORTED,\n remaining: remainingReported ? money(remaining) : UNREPORTED,\n purchased: credits !== undefined && credits.purchasedReported !== false ? money(Math.max(0, credits.purchasedCredits)) : UNREPORTED,\n free: credits !== undefined && credits.freeReported !== false ? money(Math.max(0, credits.freeCredits)) : UNREPORTED,\n percent,\n barPercent: barPercent(percent),\n exhausted: known && remaining <= 0,\n periodEnds: dateText(plan?.currentPeriodEnd ?? 0),\n }\n}\n\n/** Build one account's view. */\nfunction accountView(entry: CommandCodeAccountUsage, t: PanelTranslator): PanelAccountView {\n const { report } = entry\n const account = report.account\n const plan = report.plan\n const credits = report.credits\n const usage = report.usage\n\n const stats: PanelStatView[] = []\n if (usage !== undefined) {\n stats.push({\n label: 'requests',\n value: String(usage.completedCount),\n sub: `${usage.failedCount} ${t('failed')}`,\n })\n stats.push({ label: 'successRate', value: `${formatSuccessRate(usage.successRate)}%`, sub: '' })\n stats.push({\n label: 'spend',\n value: formatMoneyExact(usage.totalCost),\n sub: `${formatMoney(usage.totalCredits)} credits`,\n })\n stats.push({\n label: 'tokens',\n value: formatTokensCompact(usage.totalTokensIn + usage.totalTokensOut),\n sub: `${formatTokensCompact(usage.totalTokensIn)} ${t('tokensIn')} / ${formatTokensCompact(usage.totalTokensOut)} ${t('tokensOut')}`,\n })\n }\n\n const windows: PanelWindowView[] = []\n // One row per window the endpoint actually REPORTED: an unlimited plan\n // reports none, and drawing two zero-cap rows would invent a limit it does not\n // have. A window reporting `cap === 0` is uncapped spend and does get a row.\n if (credits?.fiveHour !== undefined) windows.push(windowView('fiveHour', credits.fiveHour))\n if (credits?.weekly !== undefined) windows.push(windowView('weekly', credits.weekly))\n\n // Rotation/credential state: the serving account first, then the two marks\n // the pool can carry, then a cooldown whose end time is known.\n let mark: PanelKey | undefined\n if (entry.active) mark = 'active'\n else if (entry.mark === 'invalid-credential') mark = 'invalidKey'\n else if (entry.cooldownUntil > 0 || entry.mark === 'rate-limit') mark = 'coolingDown'\n\n return {\n id: entry.id,\n label: entry.label,\n owner: account === undefined ? '' : account.userName || account.name,\n planName: plan?.name ?? '',\n planStatus: plan !== undefined && plan.status !== '' && plan.status !== 'active' ? plan.status : '',\n mark,\n cooldownUntil: entry.cooldownUntil > 0 ? resetText(entry.cooldownUntil) : '',\n unconfigured: !entry.configured,\n periodEnds: dateText(plan?.currentPeriodEnd ?? 0),\n active: entry.active,\n monthly: monthlyView(report),\n windows,\n stats,\n }\n}\n\n/** The report-level failure box, or undefined when the report is usable. */\nfunction failureView(state: UsagePageState): PanelFailureView | undefined {\n const blockedEntry = state.report?.accounts.find((entry) => entry.report.blocked !== undefined)\n const blocked = blockedEntry?.report.blocked\n // Preserve each endpoint's status or transport error beside the summary.\n const detail = (blockedEntry?.report.failures ?? []).join(' · ')\n if (blocked === 'invalid-key') {\n return { title: 'errorInvalidKey', hint: 'errorInvalidKeyHint', detail }\n }\n if (blocked === 'service-unavailable') {\n return { title: 'errorServiceUnavailable', hint: 'errorServiceUnavailableHint', detail }\n }\n if (blocked === 'network') {\n return { title: 'errorNetwork', hint: 'errorNetworkHint', detail }\n }\n if (blocked === 'invalid-response') {\n return { title: 'errorInvalidResponse', hint: 'errorInvalidResponseHint', detail }\n }\n // A transport-level failure (unmounted Remote, offline browser) arrives as\n // the controller's own error rather than as a blocked report.\n if (state.status === 'error' && state.report === undefined) {\n return { title: 'errorGeneric', hint: 'errorGeneric', detail: state.error ?? '' }\n }\n return undefined\n}\n\n/**\n * Every panel string, resolved once per projection through the translator. One\n * object with all keys (rather than per-field lookups in the components) keeps\n * the copy table and the render sites in lockstep: a key cannot be read from\n * `text` unless {@link PANEL_KEYS} declares it.\n */\nfunction panelStrings(t: PanelTranslator): Record<PanelKey, string> {\n const out = {} as Record<PanelKey, string>\n for (const key of PANEL_KEYS) out[key] = t(key)\n return out\n}\n\n/**\n * Project the shared usage snapshot into the panel's render tree.\n *\n * Deduplication matches the settings card: hand-edited settings can name one\n * credential twice.\n */\nexport function buildPanelView(input: PanelViewInput): PanelView {\n const { usage } = input\n const t = input.t ?? panelTextEN\n const seen = new Set<string>()\n const entries = (usage.report?.accounts ?? []).filter((entry) => {\n if (seen.has(entry.id)) return false\n seen.add(entry.id)\n return true\n })\n const accounts = entries.map((entry) => accountView(entry, t))\n const selectedEntry = entries.find((entry) => entry.active) ?? entries[0]\n const selectedView = accounts.find((view) => view.id === selectedEntry?.id)\n\n // The footer card stacks BOTH quota windows — the two limits an account\n // actually runs into — 5-hour first (the tighter and nearer one), then\n // weekly. `barPercent` clamps the fill; the printed percentage keeps the true\n // consumption, so an over-cap window still reads 150%.\n const footerBars: PanelFooterBar[] = []\n const windowBars: Array<[PanelKey, WindowInput | undefined]> = [\n ['fiveHourShort', selectedEntry?.report.credits?.fiveHour],\n ['weeklyShort', selectedEntry?.report.credits?.weekly],\n ]\n for (const [label, window] of windowBars) {\n if (window === undefined || window.cap <= 0) continue\n const percent = rawPercent(window.used, window.cap)\n footerBars.push({\n label,\n percent: `${percent}%`,\n barPercent: barPercent(percent),\n warn: window.exceeded,\n detail: `${money(window.used)} / ${money(window.cap)}`,\n })\n }\n\n // The card's one non-ratio figure: what this period has cost in dollars.\n const totalCost = selectedEntry?.report.usage?.totalCost\n const cost = totalCost === undefined ? '' : money(totalCost)\n\n let status = ''\n if (entries.length > 0 && !entries.some(entry => entry.configured)) status = t('unconfigured')\n else if (selectedView?.mark !== undefined && selectedView.mark !== 'active') status = t(selectedView.mark)\n else if (selectedEntry === undefined) status = t('unavailable')\n\n const planName = selectedView !== undefined && selectedView.planName !== '' ? selectedView.planName : t('nav')\n // `planName` falls back to the panel name, so it is only a second part when it\n // actually names a plan — otherwise the title would read `Command Code ·\n // Command Code`.\n const titleParts = planName === t('nav') ? [planName] : [t('nav'), planName]\n for (const bar of footerBars) {\n const figures = bar.detail === '' ? '' : ` ${bar.detail}`\n titleParts.push(`${t(bar.label)}${figures} (${bar.percent})`)\n }\n if (cost !== '') titleParts.push(`${t('spend')} ${cost}`)\n\n return {\n text: panelStrings(t),\n planName,\n status,\n footerBars,\n cost,\n footTitle: titleParts.join(' · '),\n accounts,\n selectedId: selectedEntry?.id,\n selected: selectedView,\n loading: usage.status === 'loading' && usage.report === undefined,\n noKey: entries.length > 0 && !entries.some(entry => entry.configured),\n failure: failureView(usage),\n staleError: usage.status === 'error' && usage.report !== undefined ? usage.error ?? '' : undefined,\n partial: (usage.report?.accounts.some((entry) => entry.report.failures.length > 0 && entry.report.blocked === undefined) ?? false)\n ? 'partial'\n : undefined,\n updatedAt: timeText(usage.fetchedAt ?? 0),\n }\n}\n\n// --- Auto refresh (one shared loop, started by whichever surface mounts first)\n\n/**\n * How often the panel re-reads the report while a surface is mounted. The quota\n * windows move slowly and one report costs four upstream calls, so this is a\n * background freshness tick, not a live meter.\n */\nexport const PANEL_AUTO_REFRESH_MS = 120_000\n\n/** The narrow face of `CommandCodeUsageController` this module drives. */\nexport interface RefreshSource {\n state(): UsagePageState\n refresh(): Promise<void>\n}\n\n/** Timer seam: injectable so tests never wait on real time. */\nexport interface AutoRefreshTimer {\n set(callback: () => void, ms: number): unknown\n clear(handle: unknown): void\n}\n\n/** The default timer (the client bundle runs in a browser; node tests inject one). */\nconst REAL_TIMER: AutoRefreshTimer = {\n set: (callback, ms) => setTimeout(callback, ms),\n clear: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),\n}\n\n/** Live mount count of {@link startPanelAutoRefresh}. */\nlet references = 0\n/** Owner ticket of the running loop, if any. */\nlet activeTicket: number | undefined\n/** Ticket handed to the next starter. */\nlet ticketSeq = 0\n/** Pending timer handle of the running loop. */\nlet handle: unknown\n\n/**\n * Start the shared auto refresh. One fetch when the surface appears (the sidebar\n * row is the point of the panel — it must be current, not wait for a click), then\n * a tick every {@link PANEL_AUTO_REFRESH_MS} while a surface stays mounted.\n *\n * Reference-counted: the sidebar entry and the dashboard can be mounted at once,\n * so only the first start fetches and only the last stop halts the loop. Every\n * tick goes through `usage.refresh()`, which collapses a concurrent fetch onto\n * the in-flight one. Returns the disposer that drops this surface's reference.\n *\n * @param usage - the shared usage controller.\n * @param isConfigured - whether a credential exists right now (re-read per tick).\n * @param timer - timer seam for tests.\n */\nexport function startPanelAutoRefresh(\n usage: RefreshSource,\n isConfigured: () => boolean,\n timer: AutoRefreshTimer = REAL_TIMER,\n): () => void {\n references += 1\n const ticket = ++ticketSeq\n const tick = (): void => {\n if (activeTicket !== ticket) return\n if (isConfigured()) void usage.refresh()\n handle = timer.set(tick, PANEL_AUTO_REFRESH_MS)\n }\n\n if (activeTicket === undefined) {\n activeTicket = ticket\n handle = timer.set(tick, PANEL_AUTO_REFRESH_MS)\n // First paint: refresh immediately so the row is never blank on arrival.\n if (isConfigured()) void usage.refresh()\n }\n\n let stopped = false\n return () => {\n if (stopped) return\n stopped = true\n references -= 1\n // Still mounted elsewhere: drop this reference only. The check is the\n // REFCOUNT, not this surface's ticket — the surface that started the loop\n // is not necessarily the last to unmount.\n if (references > 0) return\n activeTicket = undefined\n if (handle !== undefined) {\n timer.clear(handle)\n handle = undefined\n }\n }\n}\n\n/**\n * Drop every live reference and halt the loop without a timer.\n *\n * Exported for tests only: the loop's state is module-level on purpose (two\n * surfaces, one upstream poll). Production code releases through the disposer\n * {@link startPanelAutoRefresh} returns.\n */\nexport function resetPanelAutoRefresh(): void {\n references = 0\n activeTicket = undefined\n handle = undefined\n}\n","/** 模型分析的只读契约;只传数字和模型能力,不传会话正文、标题、路径或密钥。 */\nimport type { InvocationDescriptor, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { makeBoundaryValidator, makeRemoteDescriptor, makeStrictCodec, REMOTE_PACKAGE } from './wire-shared.ts'\nimport type { CostTokens } from './cost-facts.ts'\n\nexport type AnalyticsQuery = { mode: 'recent'; limit: number } | { mode: 'range'; from: number; to: number }\nexport interface AnalyticsMetrics {\n sessions: number; requests: number; completed: number; failed: number; cancelled: number; unknown: number; retries: number\n usageSamples: number; pricedRequests: number; cost: number; tokens: CostTokens\n latencySamples: number; latencyMs: number; ttftSamples: number; ttftMs: number; decodeSamples: number; decodeMs: number; decodeTokens: number\n}\nexport interface AnalyticsModel extends AnalyticsMetrics { id: string }\nexport interface AnalyticsScenario {\n id: string; name: string; contextWindow: number | null; images: boolean; efforts: string[]\n cost: number; pricedRequests: number; excludedRequests: number; unknownRequests: number\n}\nexport interface AnalyticsReport {\n generatedAt: number; pricingKey: number; query: AnalyticsQuery\n status: 'ready' | 'unavailable'\n scannedSessions: number; matchedSessions: number; unreadableSessions: number; skippedSessions: number; truncated: boolean; catalogUnavailable: boolean\n totals: AnalyticsMetrics; models: AnalyticsModel[]; scenarios: AnalyticsScenario[]\n monthlyEstimate: number | null\n}\nconst g = makeBoundaryValidator('commandcode/analytics')\nconst nonnegative = (s: Record<string, unknown>, k: string): number => {\n const n = g.numberField(s, k, k)\n return n >= 0 ? n : g.reject(k)\n}\nconst count = (s: Record<string, unknown>, k: string): number => {\n const n = nonnegative(s, k)\n return Number.isSafeInteger(n) ? n : g.reject(k)\n}\nexport function parseAnalyticsQuery(value: unknown): AnalyticsQuery {\n const s = g.record(value, 'query')\n if (s.mode === 'recent') {\n const limit = count(s, 'limit')\n if (limit < 1 || limit > 100) return g.reject('limit')\n return { mode: 'recent', limit }\n }\n if (s.mode !== 'range') return g.reject('mode')\n const from = count(s, 'from'), to = count(s, 'to')\n if (to <= from || to - from > 366 * 86400000 || to > 8640000000000000) return g.reject('range')\n return { mode: 'range', from, to }\n}\nconst counts = ['sessions', 'requests', 'completed', 'failed', 'cancelled', 'unknown', 'retries', 'usageSamples', 'pricedRequests', 'latencySamples', 'ttftSamples', 'decodeSamples'] as const\nconst quantities = ['cost', 'latencyMs', 'ttftMs', 'decodeMs', 'decodeTokens'] as const\nconst tokenKeys = ['uncachedInputTokens', 'outputTokens', 'cacheReadTokens', 'cacheWriteTokens'] as const\nfunction metrics(value: unknown): AnalyticsMetrics {\n const s = g.record(value, 'metrics'), result = {} as AnalyticsMetrics\n for (const k of counts) result[k] = count(s, k)\n for (const k of quantities) result[k] = nonnegative(s, k)\n const tokens = g.record(s.tokens, 'tokens')\n result.tokens = Object.fromEntries(tokenKeys.map(k => [k, nonnegative(tokens, k)])) as unknown as CostTokens\n if (result.completed + result.failed + result.cancelled + result.unknown !== result.requests\n || result.pricedRequests > result.usageSamples || result.usageSamples > result.requests\n || result.retries > result.requests || result.ttftSamples > result.requests || result.latencySamples > result.requests || result.decodeSamples > result.requests) return g.reject('coverage')\n return result\n}\nconst nullable = (s: Record<string, unknown>, k: string): number | null => s[k] === null ? null : nonnegative(s, k)\nexport function parseAnalyticsReport(value: unknown): AnalyticsReport {\n const s = g.record(value, 'report')\n if (s.status !== 'ready' && s.status !== 'unavailable') return g.reject('status')\n if (!Array.isArray(s.models) || !Array.isArray(s.scenarios) || s.models.length > 1000 || s.scenarios.length > 1000) return g.reject('models')\n return {\n generatedAt: count(s, 'generatedAt'), pricingKey: count(s, 'pricingKey'), query: parseAnalyticsQuery(s.query), status: s.status,\n scannedSessions: count(s, 'scannedSessions'), matchedSessions: count(s, 'matchedSessions'), unreadableSessions: count(s, 'unreadableSessions'), skippedSessions: count(s, 'skippedSessions'),\n truncated: g.booleanField(s, 'truncated', 'truncated'), catalogUnavailable: g.booleanField(s, 'catalogUnavailable', 'catalogUnavailable'),\n totals: metrics(s.totals), monthlyEstimate: nullable(s, 'monthlyEstimate'),\n models: s.models.map(value => { const m = g.record(value, 'model'); return { ...metrics(m), id: g.stringField(m, 'id', 'id') } }),\n scenarios: s.scenarios.map(value => {\n const m = g.record(value, 'scenario')\n if (!Array.isArray(m.efforts) || !m.efforts.every(v => typeof v === 'string')) return g.reject('efforts')\n return { id: g.stringField(m, 'id', 'id'), name: g.stringField(m, 'name', 'name'), contextWindow: nullable(m, 'contextWindow'), images: g.booleanField(m, 'images', 'images'), efforts: m.efforts as string[], cost: nonnegative(m, 'cost'), pricedRequests: count(m, 'pricedRequests'), excludedRequests: count(m, 'excludedRequests'), unknownRequests: count(m, 'unknownRequests') }\n }),\n }\n}\nexport const ANALYTICS_DESCRIPTOR: InvocationDescriptor = {\n ...makeRemoteDescriptor('commandcode/analytics', 'analytics', `${REMOTE_PACKAGE}#AnalyticsReport`, { parse: parseAnalyticsReport }),\n parameters: [{ name: 'query', wire: 'query', source: 'json' as const, codec: makeStrictCodec(`${REMOTE_PACKAGE}#AnalyticsQuery`, { parse: parseAnalyticsQuery }) }],\n}\nexport const ANALYTICS_REMOTE_CONTRIBUTION: TypertRemoteContribution = { package: REMOTE_PACKAGE, descriptors: [ANALYTICS_DESCRIPTOR] }\n","/** 只展示数字快照;筛选提交后才查询,页签、展开与模型筛选不触发历史读取。 */\nimport { useEffect, useId, useState } from 'react'\nimport type { KeyboardEvent, ReactNode } from 'react'\nimport type { AnalyticsMetrics, AnalyticsQuery, AnalyticsScenario } from '../analytics-wire.ts'\nimport { parseAnalyticsQuery } from '../analytics-wire.ts'\nimport type { AnalyticsState } from './analytics.ts'\nimport type { AnalyticsKey } from './analytics-copy.ts'\n\nexport interface AnalyticsViewProps {\n useCommandCodeAnalytics<T>(selector: (state: AnalyticsState) => T): T\n refreshAnalytics(query?: AnalyticsQuery): void\n text(key: AnalyticsKey): string\n}\ntype Text = AnalyticsViewProps['text']\nfunction localDate(time: number): string {\n const d = new Date(time)\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n/** 日期按用户本地日历展开为半开区间;截止日包括当日全部时间,夏令时不固定加 24 小时。 */\nexport function dateRange(from: string, to: string): AnalyticsQuery {\n const start = new Date(`${from}T00:00:00`), end = new Date(`${to}T00:00:00`)\n if (localDate(start.getTime()) !== from || localDate(end.getTime()) !== to) throw new TypeError('无效日期')\n end.setDate(end.getDate() + 1)\n return parseAnalyticsQuery({ mode: 'range', from: start.getTime(), to: end.getTime() })\n}\nconst money = (n: number) => `$${n.toFixed(4)}`\nconst digits = (n: number) => n.toLocaleString()\nconst meanSeconds = (ms: number, samples: number, text: Text) => samples ? `${(ms / samples / 1000).toFixed(2)} ${text('analysisSeconds')}` : text('analysisMissing')\nconst speed = (m: AnalyticsMetrics, text: Text) => m.decodeSamples && m.decodeMs ? `${(m.decodeTokens * 1000 / m.decodeMs).toFixed(1)} ${text('analysisSpeedUnit')}` : text('analysisMissing')\nfunction effortName(effort: string, text: Text): string {\n const keys: Record<string, AnalyticsKey> = { none: 'effortNone', low: 'effortLow', medium: 'effortMedium', high: 'effortHigh', xhigh: 'effortXhigh', max: 'effortMax' }\n return keys[effort] ? text(keys[effort]!) : effort\n}\nfunction Chevron() {\n return <svg className=\"ccp-analysisChevron\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"m9 5 7 7-7 7\" /></svg>\n}\nfunction AnalysisIcon({ kind }: { kind: 'info' | 'search' }) {\n return <svg className=\"ccp-analysisIcon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">{kind === 'info' ? <><circle cx=\"12\" cy=\"12\" r=\"9\" /><path d=\"M12 11v6M12 7h.01\" /></> : <><circle cx=\"10.5\" cy=\"10.5\" r=\"6.5\" /><path d=\"m16 16 4.5 4.5\" /></>}</svg>\n}\nfunction Metric({ label, value, sub, children }: { label: string; value: string; sub?: string; children?: ReactNode }) {\n return <span className=\"ccp-analysisMetric\"><span className=\"ccp-analysisLabel ccp-analysisMetricLabel\">{label}</span><span className=\"ccp-analysisValue\">{value}</span>{sub ? <span className=\"ccp-analysisSub\">{sub}</span> : null}{children}</span>\n}\n/** 只比较已知成本;没有计价样本或已知小计为零时,不制造百分比。 */\nexport function knownCostShare(m: Pick<AnalyticsMetrics, 'cost' | 'pricedRequests'>, totalCost: number): number | null {\n return m.pricedRequests > 0 && totalCost > 0 ? m.cost / totalCost * 100 : null\n}\nfunction CostShare({ m, totalCost, text }: { m: AnalyticsMetrics; totalCost: number; text: Text }) {\n const share = knownCostShare(m, totalCost)\n if (share === null) return <span className=\"ccp-analysisSub\">{text('analysisNoShare')}</span>\n const percentage = `${share.toFixed(1)}%`\n return <span className=\"ccp-analysisShare\" title={`${text('analysisShareHint')} ${percentage}`}><span className=\"ccp-analysisShareTrack\" aria-hidden=\"true\"><span className=\"ccp-analysisShareFill\" style={{ width: `${Math.min(100, Math.max(0, share))}%` }} /></span><span className=\"ccp-analysisShareValue\">{percentage}</span></span>\n}\nfunction DetailGroup({ title, values, text }: { title: AnalyticsKey; values: Array<[AnalyticsKey, string]>; text: Text }) {\n return <div className=\"ccp-analysisDetailGroup\"><h4 className=\"ccp-analysisDetailTitle\">{text(title)}</h4><dl className=\"ccp-analysisFacts\">{values.map(([key, value]) => <div className=\"ccp-analysisFact\" key={key}><dt className=\"ccp-analysisLabel\">{text(key)}</dt><dd className=\"ccp-analysisFactValue\">{value}</dd></div>)}</dl></div>\n}\n/** 样本为零时词元仍为未知;汇总和单模型复用相同口径,展开只改变展示。 */\nfunction MetricsDetails({ m, text }: { m: AnalyticsMetrics; text: Text }) {\n const tokens = m.tokens, tokenValue = (n: number) => m.usageSamples ? digits(n) : text('analysisMissing')\n return <div className=\"ccp-analysisDetails\">\n <DetailGroup title=\"analysisTokens\" text={text} values={[\n ['analysisInput', tokenValue(tokens.uncachedInputTokens)], ['analysisOutput', tokenValue(tokens.outputTokens)],\n ['analysisCacheRead', tokenValue(tokens.cacheReadTokens)], ['analysisCacheWrite', tokenValue(tokens.cacheWriteTokens)],\n ]} />\n <DetailGroup title=\"analysisOutcome\" text={text} values={[\n ['analysisCompleted', digits(m.completed)], ['analysisFailed', digits(m.failed)], ['analysisRetries', digits(m.retries)],\n ['analysisCancelled', digits(m.cancelled)], ['analysisUnknown', digits(m.unknown)],\n ]} />\n <DetailGroup title=\"analysisSamples\" text={text} values={[\n ['analysisUsageSamples', digits(m.usageSamples)], ['analysisPriced', digits(m.pricedRequests)], ['analysisTimed', digits(m.latencySamples)],\n ['analysisFirstTokenSamples', digits(m.ttftSamples)], ['analysisDecodeSamples', digits(m.decodeSamples)],\n ]} />\n <DetailGroup title=\"analysisSessionCost\" text={text} values={[\n ['analysisSessionCount', digits(m.sessions)], ['analysisRequests', digits(m.requests)],\n ['analysisAverage', m.sessions && m.pricedRequests ? money(m.cost / m.sessions) : text('analysisMissing')], ['analysisSpeed', speed(m, text)],\n ]} />\n </div>\n}\nfunction ModelRow({ m, name, totalCost, text }: { m: AnalyticsMetrics & { id: string }; name: string | undefined; totalCost: number; text: Text }) {\n return <details className=\"ccp-analysisModelRow\"><summary className=\"ccp-analysisModelSummary\">\n <span className=\"ccp-analysisIdentity\"><span className=\"ccp-analysisModelName\">{name || m.id}</span>{name && name !== m.id ? <span className=\"ccp-analysisSub\">{m.id}</span> : null}<span className=\"ccp-analysisSub ccp-analysisModelCount\">{text('analysisRequests')} {digits(m.requests)} · {text('analysisSessionCount')} {digits(m.sessions)}</span></span>\n <Metric label={text('analysisCostShare')} value={m.pricedRequests ? money(m.cost) : text('analysisMissing')} sub={`${text('analysisPriced')} ${m.pricedRequests}/${m.requests}`}><CostShare m={m} totalCost={totalCost} text={text} /></Metric>\n <Metric label={text('analysisResponse')} value={meanSeconds(m.latencyMs, m.latencySamples, text)} />\n <Metric label={text('analysisFirstToken')} value={meanSeconds(m.ttftMs, m.ttftSamples, text)} />\n <Metric label={text('analysisSpeed')} value={speed(m, text)} />\n <Chevron />\n </summary><MetricsDetails m={m} text={text} /></details>\n}\nfunction ScenarioRow({ m, text }: { m: AnalyticsScenario; text: Text }) {\n return <details className=\"ccp-analysisModelRow\"><summary className=\"ccp-analysisScenarioSummary\">\n <span className=\"ccp-analysisIdentity\"><span className=\"ccp-analysisModelName\">{m.name}</span><span className=\"ccp-analysisSub\">{m.id}</span></span>\n <Metric label={text('analysisSimulationCost')} value={m.pricedRequests ? money(m.cost) : text('analysisMissing')} sub={text('analysisUsd')} />\n <Metric label={text('analysisCoverage')} value={`${m.pricedRequests}/${m.pricedRequests + m.excludedRequests + m.unknownRequests}`} sub={`${text('analysisExcluded')} ${digits(m.excludedRequests)} · ${text('analysisUnknownPrice')} ${digits(m.unknownRequests)}`} />\n <Metric label={text('analysisCapabilities')} value={m.contextWindow === null ? text('analysisMissing') : `${digits(m.contextWindow)} ${text('analysisTokenUnit')}`} sub={text(m.images ? 'analysisImages' : 'analysisTextOnly')} /><Chevron />\n </summary><div className=\"ccp-analysisDetails ccp-analysisScenarioDetails\">\n <DetailGroup title=\"analysisSamples\" text={text} values={[\n ['analysisPriced', digits(m.pricedRequests)], ['analysisExcluded', digits(m.excludedRequests)], ['analysisUnknownPrice', digits(m.unknownRequests)],\n ]} />\n <DetailGroup title=\"analysisCapabilities\" text={text} values={[\n ['analysisEfforts', m.efforts.length ? m.efforts.map(e => effortName(e, text)).join(', ') : text('analysisNoEfforts')],\n ]} />\n </div></details>\n}\nexport function AnalyticsView(props: AnalyticsViewProps) {\n const { text } = props, state = props.useCommandCodeAnalytics(s => s), report = state.report\n const [mode, setMode] = useState<'recent' | 'range'>(report?.query.mode ?? 'recent')\n const [limit, setLimit] = useState(report?.query.mode === 'recent' ? String(report.query.limit) : '20')\n const [from, setFrom] = useState(localDate(report?.query.mode === 'range' ? report.query.from : Date.now() - 29 * 86400000))\n const [to, setTo] = useState(localDate(report?.query.mode === 'range' ? report.query.to - 1 : Date.now()))\n const [invalid, setInvalid] = useState(false), [filter, setFilter] = useState('')\n const [page, setPage] = useState<'history' | 'simulation'>('history'), id = useId()\n const refresh = props.refreshAnalytics\n useEffect(() => { if (state.status === 'idle') refresh() }, [state.status, refresh])\n const busy = state.status === 'loading'\n const apply = () => {\n try {\n const query = mode === 'recent' ? parseAnalyticsQuery({ mode, limit: Number(limit) }) : dateRange(from, to)\n setInvalid(false); refresh(query)\n } catch { setInvalid(true) }\n }\n // 页签遵循键盘导航;只切换本地展示,不重读会话或丢弃筛选草稿。\n const navigateTab = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return\n event.preventDefault()\n const next = event.key === 'Home' ? 'history' : event.key === 'End' ? 'simulation' : page === 'history' ? 'simulation' : 'history'\n setPage(next)\n event.currentTarget.querySelector<HTMLButtonElement>(`[data-page=\"${next}\"]`)?.focus()\n }\n const scenarios = report?.scenarios.filter(m => `${m.id} ${m.name}`.toLowerCase().includes(filter.trim().toLowerCase())) ?? []\n // 名称来自同一份试算目录;目录缺失时保留历史标识,不另读模型接口。\n const names = new Map(report?.scenarios.map(m => [m.id, m.name]))\n const m = report?.totals\n return <section className=\"ccp-analysis\" aria-label={text('analyticsNav')} aria-busy={busy}>\n <form className=\"ccp-analysisFilters\" data-mode={mode} noValidate onSubmit={e => { e.preventDefault(); if (!busy) apply() }}>\n <label className=\"ccp-analysisField ccp-analysisScopeField\">{text('analysisScope')}<span className=\"ccp-analysisSelectShell\"><select className=\"ccp-analysisInput ccp-analysisSelect\" value={mode} disabled={busy} onChange={e => setMode(e.target.value as 'recent' | 'range')}><option value=\"recent\">{text('analysisRecent')}</option><option value=\"range\">{text('analysisRange')}</option></select><Chevron /></span></label>\n {mode === 'recent' ? <label className=\"ccp-analysisField\">{text('analysisLimit')}<input className=\"ccp-analysisInput\" type=\"number\" min=\"1\" max=\"100\" required value={limit} disabled={busy} onChange={e => setLimit(e.target.value)} /></label> : <>\n <label className=\"ccp-analysisField ccp-analysisDateField\">{text('analysisFrom')}<input className=\"ccp-analysisInput\" type=\"date\" required value={from} disabled={busy} onChange={e => setFrom(e.target.value)} /></label>\n <label className=\"ccp-analysisField ccp-analysisDateField\">{text('analysisTo')}<input className=\"ccp-analysisInput\" type=\"date\" required value={to} disabled={busy} onChange={e => setTo(e.target.value)} /></label>\n </>}\n <button className=\"ccp-analysisApply\" type=\"submit\" disabled={busy}>{text('analysisApply')}</button>\n </form>\n {invalid ? <p className=\"ccp-analysisMessage ccp-analysisError\" role=\"alert\">{text('analysisInvalid')}</p> : null}\n {busy ? <p className=\"ccp-analysisMessage\" role=\"status\">{text('analysisLoading')}</p> : null}\n {state.error ? <p className=\"ccp-analysisMessage ccp-analysisError\" role=\"alert\">{state.error}</p> : null}\n {report?.status === 'unavailable' ? <p className=\"ccp-analysisMessage\" role=\"status\">{text('analysisUnavailable')}</p> : null}\n {report?.status === 'ready' && m ? <>\n <div className=\"ccp-analysisScope\"><span>{text('analysisScope')}: {report.query.mode === 'recent' ? `${text('analysisRecent')} ${report.query.limit}` : `${localDate(report.query.from)} — ${localDate(report.query.to - 1)}`}</span><span>{text('analysisScanned')} {report.scannedSessions} · {text('analysisMatched')} {report.matchedSessions} · {text('analysisUnreadable')} {report.unreadableSessions} · {text('analysisSkipped')} {report.skippedSessions}</span></div>\n <div className=\"ccp-analysisOverview\" role=\"group\" aria-label={text('analysisOverview')}>\n <Metric label={text('analysisCost')} value={m.pricedRequests ? money(m.cost) : text('analysisMissing')} sub={`${text('analysisPriced')} ${m.pricedRequests}/${m.requests}`} />\n <Metric label={text('analysisRequests')} value={digits(m.requests)} sub={`${text('analysisSessionCount')} ${digits(m.sessions)}`} />\n <Metric label={text('analysisResponse')} value={meanSeconds(m.latencyMs, m.latencySamples, text)} sub={`${text('analysisTimed')} ${digits(m.latencySamples)}`} />\n <Metric label={text('analysisFirstToken')} value={meanSeconds(m.ttftMs, m.ttftSamples, text)} sub={`${text('analysisFirstTokenSamples')} ${digits(m.ttftSamples)}`} />\n </div>\n <p className=\"ccp-analysisNote\">{text('analysisShortBasis')}</p>\n {report.truncated || report.unreadableSessions > 0 || report.skippedSessions > 0 || m.pricedRequests < m.requests ? <div className=\"ccp-analysisMessage ccp-analysisWarning\" role=\"status\"><AnalysisIcon kind=\"info\" /><div>{report.truncated || report.unreadableSessions > 0 || report.skippedSessions > 0 ? <p>{text('analysisPartial')}</p> : null}{m.pricedRequests < m.requests ? <p>{text('analysisUnpriced')}</p> : null}</div></div> : null}\n <div className=\"ccp-analysisTabs\" role=\"tablist\" aria-label={text('analysisSections')} onKeyDown={navigateTab}>\n {(['history', 'simulation'] as const).map(tab => <button className=\"ccp-analysisTab\" key={tab} id={`${id}-${tab}-tab`} data-page={tab} type=\"button\" role=\"tab\" aria-selected={page === tab} aria-controls={`${id}-${tab}`} tabIndex={page === tab ? 0 : -1} onClick={() => setPage(tab)}>{text(tab === 'history' ? 'analysisHistory' : 'analysisSimulation')}<span className=\"ccp-analysisTabCount\">{digits(tab === 'history' ? report.models.length : report.scenarios.length)}</span></button>)}\n </div>\n <section className=\"ccp-analysisPanel\" id={`${id}-history`} role=\"tabpanel\" aria-labelledby={`${id}-history-tab`} tabIndex={0} hidden={page !== 'history'}>\n <div className=\"ccp-analysisSectionHead\"><h3 className=\"ccp-analysisHeading\">{text('analysisByModel')}</h3><p className=\"ccp-analysisNote\">{text('analysisModelHint')}</p></div>\n {m.requests === 0 ? <p className=\"ccp-analysisEmpty\">{text('analysisEmpty')}</p> : <div className=\"ccp-analysisModels\"><div className=\"ccp-analysisTableHead\" aria-hidden=\"true\"><span>{text('analysisModel')}</span><span>{text('analysisCostShare')}</span><span>{text('analysisResponse')}</span><span>{text('analysisFirstToken')}</span><span>{text('analysisSpeed')}</span><span /></div>{report.models.map(model => <ModelRow key={model.id} m={model} name={names.get(model.id)} totalCost={m.cost} text={text} />)}</div>}\n <div className=\"ccp-analysisFooter\"><details className=\"ccp-analysisAggregate\"><summary className=\"ccp-analysisDisclosure\"><Chevron />{text('analysisDetails')}</summary><MetricsDetails m={m} text={text} /></details>\n <div className=\"ccp-analysisMonthly\"><span>{text('analysisMonthly')}</span><strong className=\"ccp-analysisMonthlyValue\">{report.monthlyEstimate === null || report.truncated || report.unreadableSessions || report.skippedSessions ? text('analysisMissing') : money(report.monthlyEstimate)}</strong><p className=\"ccp-analysisNote\">{text('analysisMonthlyHint')}</p></div>\n </div>\n </section>\n <section className=\"ccp-analysisPanel\" id={`${id}-simulation`} role=\"tabpanel\" aria-labelledby={`${id}-simulation-tab`} tabIndex={0} hidden={page !== 'simulation'}>\n <p className=\"ccp-analysisAssumption\">{text('analysisAssumption')}</p>\n {report.catalogUnavailable ? <p className=\"ccp-analysisMessage ccp-analysisWarning\" role=\"status\">{text('analysisCatalog')}</p> : null}\n <div className=\"ccp-analysisSectionHead\"><div><h3 className=\"ccp-analysisHeading\">{text('analysisSimulationHeading')}</h3><p className=\"ccp-analysisNote\">{text('analysisSimulationHint')}</p></div><label className=\"ccp-analysisField ccp-analysisSearch\"><span className=\"ccp-analysisSearchLabel\">{text('analysisSearch')}</span><span className=\"ccp-analysisSearchShell\"><AnalysisIcon kind=\"search\" /><input className=\"ccp-analysisInput\" type=\"search\" placeholder={text('analysisSearchPlaceholder')} value={filter} onChange={e => setFilter(e.target.value)} /></span></label></div>\n {m.requests === 0 ? <p className=\"ccp-analysisEmpty\">{text('analysisEmpty')}</p> : scenarios.length ? <div className=\"ccp-analysisModels\"><div className=\"ccp-analysisTableHead ccp-analysisScenarioHead\" aria-hidden=\"true\"><span>{text('analysisModel')}</span><span>{text('analysisSimulationCost')}</span><span>{text('analysisCoverage')}</span><span>{text('analysisCapabilities')}</span><span /></div>{scenarios.map(model => <ScenarioRow key={model.id} m={model} text={text} />)}</div> : !report.catalogUnavailable ? <p className=\"ccp-analysisEmpty\" role=\"status\">{text('analysisNoMatches')}</p> : null}\n </section>\n <details className=\"ccp-analysisRules\"><summary className=\"ccp-analysisDisclosure\"><Chevron />{text('analysisRules')}</summary><div className=\"ccp-analysisRulesBody\"><p>{text('analysisBasis')}</p><p>{text('analysisCoverageHint')}</p></div></details>\n </> : null}\n </section>\n}\n","/**\n * React components for the Command Code plans & quota panel: the sidebar footer\n * card and the dashboard it opens in the center column.\n *\n * Both render one {@link PanelView} projected by `./panel.ts` — no fact is\n * derived here. Strings arrive already localized in `view.text`: the slots\n * declare the `panel.commandcode` locale namespace, so the renderer hands this\n * component a `t` seat that is passed into `buildPanelView`, and a language\n * switch mints a new `t` identity, which re-renders both surfaces.\n *\n * The footer card is the panel's home — the shell renders it in the foot area\n * directly above the Settings seat, and unlike a `sidebar.panellist` row (whose\n * chrome and label the SHELL owns) this entry owns its whole surface and\n * therefore calls `open()` itself. Styles ride the stylesheet\n * `./panel-styles.ts` returns; classes are `ccp-` prefixed.\n *\n * @module dsh-commandcode-provider/client/panel-view\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 { SnapshotStore } from './snapshot-store.ts'\nimport type { UsagePageState } from './usage.ts'\nimport type { SettingsPageState } from './settings.ts'\nimport { buildPanelView } from './panel.ts'\nimport type { PanelAccountView, PanelView, PanelWindowView } from './panel.ts'\nimport { panelTextEN } from './panel-copy.ts'\nimport type { PanelKey } from './panel-copy.ts'\n// SlotMap merge for `main` / `sidebar.footer.action` (load-bearing: the slots\n// this file's components register into are typed only by that augmentation).\nimport './panel-slots.ts'\nimport { AnalyticsView } from './analytics-view.tsx'\nimport type { AnalyticsState } from './analytics.ts'\nimport type { AnalyticsQuery } from '../analytics-wire.ts'\n\n/**\n * Owner share of the sidebar-foot action hole: the shell renders the foot area\n * and hands each action only the column fold state. There is no button chrome\n * and no `label` seat — the entry is the whole surface.\n */\nexport interface SidebarFooterActionOwnerProps {\n /** Whether the sidebar renders wide content (false = 56px rail). */\n wide: boolean\n}\n\n/**\n * The injected face both panel slots carry. Bound by the client entry so the\n * components stay unaware of the settings controller, the login controller, the\n * layout service and the module-level auto-refresh loop.\n *\n * NOTE the split from {@link PanelComponentProps}: this is what the\n * registration's `inject` factory RETURNS, and the renderer does not hand it to\n * the component verbatim — `bindInjectSources` destructures the `hooks`\n * compartment OUT and re-exposes each member as a `use<Name>` prop\n * (`commandCodeUsage` → `useCommandCodeUsage`). A component that reads\n * `props.hooks.*` finds `undefined` at runtime and crashes on render, which the\n * slot renderer contains by ABDICATING the entry, so the surface vanishes with\n * no visible error.\n */\nexport interface PanelInjected {\n hooks: {\n commandCodeUsage: SnapshotStore<UsagePageState>\n commandCodeSettings: SnapshotStore<SettingsPageState>\n commandCodeAnalytics?: SnapshotStore<AnalyticsState>\n commandCodePanelMode?: SnapshotStore<'quota' | 'analysis'>\n }\n /** Fetch the report now (the dashboard's Refresh action). */\n refresh(): void\n /**\n * Leave the dashboard and show the Conversation again\n * (`ctx.layout.selectPanel(null)`; the current Session is untouched).\n */\n close(): void\n /** Start the shared background poll for this mount; returns its disposer. */\n startAutoRefresh(): () => void\n /** Select this panel in the center column (`ctx.layout.selectPanel`). */\n open(): void\n refreshAnalytics?(query?: AnalyticsQuery): void\n selectPanelMode?(mode: 'quota' | 'analysis'): void\n}\n\n/**\n * The props a panel component actually receives: the bound `useX` seats (what\n * {@link PanelInjected}'s `hooks` compartment becomes), the pass-through\n * actions, and no raw `hooks` key.\n *\n * `buildPanelView` is cheap (one pass over the account list) and recomputing it\n * per notification is what keeps a store update from ever rendering a stale\n * quota, so the selector is deliberately the whole snapshot.\n */\nexport interface PanelComponentProps {\n useCommandCodeAnalytics?<T>(selector: (state: AnalyticsState) => T): T\n useCommandCodePanelMode?<T>(selector: (state: 'quota' | 'analysis') => T): T\n refreshAnalytics?(query?: AnalyticsQuery): void\n selectPanelMode?(mode: 'quota' | 'analysis'): void\n useCommandCodeUsage<T>(selector: (state: UsagePageState) => T): T\n useCommandCodeSettings<T>(selector: (state: SettingsPageState) => T): T\n /**\n * Locale seat for the `panel.commandcode` namespace, bound by the\n * registration's own `locale` declaration. Optional so a missing locale face\n * degrades to English instead of crashing the surface.\n */\n t?: Translate<PanelKey>\n refresh(): void\n close(): void\n startAutoRefresh(): () => void\n open(): void\n}\n\n/** Props of the sidebar footer card: the panel face plus the shell's fold state. */\nexport interface CommandCodeFooterEntryProps extends PanelComponentProps, SidebarFooterActionOwnerProps {}\n\n/** The panel's view, recomputed from both seats on every notification. */\nfunction usePanelView(props: PanelComponentProps): PanelView {\n const usage = props.useCommandCodeUsage((state) => state)\n const settings = props.useCommandCodeSettings((state) => state)\n return buildPanelView({\n usage,\n apiKeyConfigured: settings.anyAccountConfigured,\n t: props.t ?? panelTextEN,\n })\n}\n\n/**\n * The quota ring. One glyph serves the rail button, the footer card's top row\n * and the dashboard header: a faint track plus an arc whose sweep is the\n * consumption, drawn from 12 o'clock. Circumference 2πr = 45.55 at r = 7.25.\n */\nfunction Ring({ percent, warn, size }: { percent: number; warn: boolean; size: number }) {\n const clamped = Math.min(100, Math.max(0, percent))\n const circumference = 45.55\n // Rounded to three decimals: the raw product lands on floats like\n // 34.162499999999994, which is a needless DOM diff churn.\n const dashoffset = Math.round(circumference * (1 - clamped / 100) * 1000) / 1000\n return (\n <span className=\"ccp-glyph\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\" width={size} height={size} focusable=\"false\">\n <circle cx=\"10\" cy=\"10\" r=\"7.25\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" opacity=\"0.4\" />\n <circle\n cx=\"10\"\n cy=\"10\"\n r=\"7.25\"\n fill=\"none\"\n stroke={warn ? 'var(--dsw-alias-state-error-primary)' : 'currentColor'}\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeDasharray={String(circumference)}\n strokeDashoffset={String(dashoffset)}\n transform=\"rotate(-90 10 10)\"\n />\n </svg>\n </span>\n )\n}\n\n/** One labelled bar. `compact` drops the reset line; the footer draws its own. */\nfunction QuotaBar({ label, value, percent, barPercent, warn, resetsAt, resetsLabel }: {\n label: string\n value: string\n percent: string\n barPercent: number\n warn: string\n resetsAt: string\n resetsLabel: string\n}) {\n const clamped = Math.min(100, Math.max(0, barPercent))\n return (\n <div className=\"ccp-window\">\n <div className=\"ccp-windowHead\">\n <span className=\"ccp-windowLabel\">{label}</span>\n {warn !== '' ? <span className=\"ccp-warnTag\">{warn}</span> : null}\n <span className=\"ccp-spacer\" />\n {value !== '' ? <span className=\"ccp-windowValue\">{value}</span> : null}\n <span className=\"ccp-windowPct\">{percent}</span>\n </div>\n <div className=\"ccp-bar\" role=\"progressbar\" aria-label={label} aria-valuemin={0} aria-valuemax={100} aria-valuenow={clamped}>\n <div className={warn !== '' ? 'ccp-barFill ccp-barFillWarn' : 'ccp-barFill'} style={{ width: `${clamped}%` }} />\n </div>\n {resetsAt !== '' ? <p className=\"ccp-windowReset\">{resetsLabel} {resetsAt}</p> : null}\n </div>\n )\n}\n\n/** A labelled figure. */\nfunction Tile({ label, value, sub }: { label: string; value: string; sub?: string }) {\n return (\n <div className=\"ccp-tile\">\n <span className=\"ccp-tileLabel\">{label}</span>\n <span className=\"ccp-tileValue\">{value}</span>\n {sub !== undefined && sub !== '' ? <span className=\"ccp-tileSub\">{sub}</span> : null}\n </div>\n )\n}\n\n/** The rotation/credential badge line for one account. */\nfunction markText(account: PanelAccountView, text: (key: PanelKey) => string): string {\n if (account.mark === undefined) return ''\n if (account.mark === 'coolingDown' && account.cooldownUntil !== '') {\n return `${text('coolingDown')} · ${account.cooldownUntil}`\n }\n return text(account.mark)\n}\n\n/** `Default account` → `D`; used for the card's monogram chip. */\nfunction initial(label: string): string {\n const trimmed = label.trim()\n return trimmed === '' ? '?' : trimmed[0]!.toUpperCase()\n}\n\n/**\n * One account's full report: the monthly limit/usage bar, the two quota\n * windows, then the credit and usage totals.\n */\nfunction AccountCard({ account, view }: { account: PanelAccountView; view: PanelView }) {\n const text = (key: PanelKey): string => view.text[key] ?? key\n const mark = markText(account, text)\n const monthly = account.monthly\n\n return (\n <section className=\"ccp-card\" aria-label={account.label}>\n <header className=\"ccp-cardHead\">\n <span className=\"ccp-avatar\" aria-hidden=\"true\">{initial(account.label)}</span>\n <span className=\"ccp-cardIdentity\">\n <span className=\"ccp-cardTitle\">{account.label}</span>\n {account.owner !== '' ? <span className=\"ccp-cardOwner\">{account.owner}</span> : null}\n </span>\n <span className=\"ccp-spacer\" />\n {account.planName !== '' ? <span className=\"ccp-badge\">{account.planName}</span> : null}\n {account.planStatus !== '' ? <span className=\"ccp-badge ccp-badgeWarn\">{account.planStatus}</span> : null}\n {mark !== '' ? (\n <span className={account.mark === 'invalidKey' ? 'ccp-badge ccp-badgeError' : 'ccp-badgeMuted'}>{mark}</span>\n ) : null}\n {account.periodEnds !== '' ? (\n <span className=\"ccp-meta\">{text('periodEnds')} {account.periodEnds}</span>\n ) : null}\n </header>\n\n {account.unconfigured ? <p className=\"ccp-hint\">{text('unconfigured')}</p> : null}\n\n {monthly !== undefined && monthly.known ? (\n <QuotaBar\n label={text('monthly')}\n value={`${monthly.used} / ${monthly.limit}`}\n percent={`${monthly.percent}%`}\n barPercent={monthly.barPercent}\n warn={monthly.exhausted ? text('exhausted') : ''}\n resetsAt=\"\"\n resetsLabel=\"\"\n />\n ) : (\n <div className=\"ccp-planRow\">\n {/* The plan is already in the card's header badge; what is missing\n here is the RATIO, so the row names the plan the report carries\n and falls back to a placeholder only when the report is silent. */}\n <span className=\"ccp-fieldLabel\">{text('plan')}</span>\n <span className=\"ccp-planName\">{account.planName !== '' ? account.planName : text('unavailable')}</span>\n </div>\n )}\n\n {/* A balance the billing endpoint DID report, so a card without a ratio\n still states something true. */}\n {monthly !== undefined && monthly.remaining !== '—' ? (\n <div className=\"ccp-planRow\">\n <span className=\"ccp-fieldLabel\">{text('remaining')}</span>\n <span className=\"ccp-planName\">{monthly.remaining}</span>\n </div>\n ) : null}\n\n {account.windows.length > 0 ? (\n <div className=\"ccp-windows\">\n {account.windows.map((window: PanelWindowView) => (\n <QuotaBar\n key={window.label}\n label={text(window.label)}\n value={window.value}\n percent={window.capped ? `${window.percent}%` : text('windowUnlimited')}\n barPercent={window.barPercent}\n warn={window.exceeded ? text('exceeded') : ''}\n resetsAt={window.resetsAt}\n resetsLabel={text('resets')}\n />\n ))}\n </div>\n ) : null}\n\n {monthly !== undefined ? (\n <div className=\"ccp-block\">\n <h4 className=\"ccp-blockTitle\">{text('credits')}</h4>\n <div className=\"ccp-tiles\">\n <Tile label={text('monthlyLimit')} value={monthly.limit} />\n <Tile label={text('monthlyUsed')} value={monthly.used} />\n <Tile label={text('remaining')} value={monthly.remaining} />\n <Tile label={text('purchased')} value={monthly.purchased} />\n <Tile label={text('free')} value={monthly.free} />\n </div>\n </div>\n ) : null}\n\n {account.stats.length > 0 ? (\n <div className=\"ccp-block\">\n <h4 className=\"ccp-blockTitle\">{text('usage')}</h4>\n <div className=\"ccp-tiles\">\n {account.stats.map((stat) => (\n <Tile key={stat.label} label={text(stat.label)} value={stat.value} sub={stat.sub} />\n ))}\n </div>\n </div>\n ) : null}\n </section>\n )\n}\n\n/**\n * The center-column dashboard, registered into the layout's keyed `main` slot\n * under the same id the footer card selects, so the two are one navigation\n * entry: the card shows the plan, the monthly bar and the quota window; the\n * panel shows everything, including the per-account breakdown.\n */\nexport function CommandCodePanel(props: PanelComponentProps) {\n const view = usePanelView(props)\n const [fallbackMode, setFallbackMode] = useState<'quota' | 'analysis'>('quota')\n const mode = props.useCommandCodePanelMode?.(s => s) ?? fallbackMode\n const analyticsBusy = props.useCommandCodeAnalytics?.(s => s.status === 'loading') ?? false\n const selectMode = (next: 'quota' | 'analysis') => { setFallbackMode(next); props.selectPanelMode?.(next) }\n const text = (key: PanelKey): string => view.text[key] ?? key\n const [selectedId, setSelectedId] = useState<string | undefined>(undefined)\n\n const startAutoRefresh = props.startAutoRefresh\n useEffect(() => mode === 'quota' ? startAutoRefresh() : undefined, [startAutoRefresh, mode])\n\n const accounts = view.accounts\n const selected = accounts.find((account) => account.id === selectedId)\n ?? view.selected\n ?? accounts[0]\n\n return (\n <div className=\"ccp-main\" role=\"region\" aria-label={text('nav')}>\n <div className={`ccp-mainInner${mode === 'analysis' ? ' ccp-mainInnerAnalysis' : ''}`}>\n <header className=\"ccp-header\">\n <div className=\"ccp-headerText\">\n <h2 className=\"ccp-title\">{mode === 'analysis' ? `Command Code · ${text('analyticsNav')}` : text('nav')}</h2>\n <p className=\"ccp-subtitle\">{text(mode === 'quota' ? 'subtitle' : 'analysisIntro')}</p>\n </div>\n <span className=\"ccp-spacer\" />\n {mode === 'quota' && view.updatedAt !== '' ? <span className=\"ccp-meta\">{text('updated')} {view.updatedAt}</span> : null}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={mode === 'quota' ? view.loading : analyticsBusy}\n onClick={() => mode === 'quota' ? props.refresh() : props.refreshAnalytics?.()}\n >\n {mode === 'quota' && view.loading ? text('refreshing') : text('refresh')}\n </Button>\n {/* The dashboard REPLACES the conversation in the center column and\n this panel is the only surface that selects it, so without an exit\n the user cannot get back to the session at all (issue #41): the\n sidebar card only re-selects this same panel. The glyph is the\n button's whole content, so the name and tooltip carry the words. */}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ccp-close\"\n aria-label={text('close')}\n title={text('closeHint')}\n onClick={() => props.close()}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"m6 6 12 12M18 6 6 18\" /></svg>\n </Button>\n </header>\n\n <nav className=\"ccp-tabs\" aria-label={text('nav')}>\n <button className={mode === 'quota' ? 'ccp-tab ccp-tabActive' : 'ccp-tab'} type=\"button\" aria-pressed={mode === 'quota'} onClick={() => selectMode('quota')}>{text('quotaNav')}</button>\n <button className={mode === 'analysis' ? 'ccp-tab ccp-tabActive' : 'ccp-tab'} type=\"button\" aria-pressed={mode === 'analysis'} onClick={() => selectMode('analysis')}>{text('analyticsNav')}</button>\n </nav>\n {mode === 'analysis' ? props.useCommandCodeAnalytics && props.refreshAnalytics ? <AnalyticsView useCommandCodeAnalytics={props.useCommandCodeAnalytics} refreshAnalytics={props.refreshAnalytics} text={text} /> : <p className=\"ccp-hint\">{text('analysisUnavailable')}</p> : <>\n\n {view.noKey ? (\n <div className=\"ccp-notice\">\n <p className=\"ccp-noticeTitle\">{text('noKey')}</p>\n <p className=\"ccp-noticeHint\">{text('noKeyHint')}</p>\n </div>\n ) : null}\n\n {view.failure !== undefined ? (\n <div className=\"ccp-notice ccp-noticeError\" role=\"alert\">\n <p className=\"ccp-noticeTitle\">{text(view.failure.title)}</p>\n <p className=\"ccp-noticeHint\">{text(view.failure.hint)}</p>\n {view.failure.detail !== '' ? <p className=\"ccp-noticeDetail\">{view.failure.detail}</p> : null}\n </div>\n ) : null}\n\n {!view.noKey && view.failure === undefined && accounts.length === 0 && view.loading ? (\n <p className=\"ccp-hint\">{text('loading')}</p>\n ) : null}\n\n {view.staleError !== undefined && view.staleError !== '' ? (\n <p className=\"ccp-hint\" role=\"status\">{text('errorGeneric')} — {view.staleError}</p>\n ) : null}\n\n {accounts.length > 1 ? (\n <div className=\"ccp-tabs\" role=\"tablist\" aria-label={text('nav')}>\n {accounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected?.id === account.id}\n className={selected?.id === account.id ? 'ccp-tab ccp-tabActive' : 'ccp-tab'}\n onClick={() => setSelectedId(account.id)}\n >\n {account.label}\n </button>\n ))}\n </div>\n ) : null}\n\n {selected !== undefined ? <AccountCard account={selected} view={view} /> : null}\n\n {view.partial !== undefined ? <p className=\"ccp-hint\">{text(view.partial)}</p> : null}\n </>}\n </div>\n </div>\n )\n}\n\n/**\n * The sidebar footer card, registered into `sidebar.footer.action` — the list\n * the shell renders in the foot area directly ABOVE the Settings seat, so the\n * panel reads as a bottom-pinned sibling of Settings rather than a global panel\n * icon at the top of the column.\n *\n * The shell wraps nothing here, so this component owns the surface: the button,\n * its chrome and its accessible name. Expanded, it draws the title row and one\n * block per quota window (5-hour, then weekly) — the window's own spend and\n * limit, its percentage and its bar — and nothing else, because those two\n * windows are the figures an account runs into, so the period total stays in the\n * tooltip. In the 56px rail it collapses to a 36px icon button carrying the ring,\n * matching the shell's own rail geometry; `wide` comes from the shell.\n *\n * Rendering is gated on the settings page's `showSidebarQuota` toggle, which\n * defaults OFF: a fresh install shows no quota surface in the sidebar and runs\n * no background poll. The gate reads the STORED document (the settings\n * controller's `sidebarQuota` fact), so an unsaved draft cannot show the card\n * while a landed save flips it live. The entry stays REGISTERED — this is a\n * render decision, so nothing churns the slot ledger.\n */\nexport function CommandCodeFooterEntry(props: CommandCodeFooterEntryProps) {\n // While hidden this component renders NOTHING — no expanded card, no rail\n // icon — and starts no background usage poll; the dashboard cell stays\n // registered but has no trigger, which is exactly what \"hide the quota\n // display\" means.\n const visible = props.useCommandCodeSettings((snapshot) => snapshot.sidebarQuota)\n const view = usePanelView(props)\n\n const startAutoRefresh = props.startAutoRefresh\n useEffect(() => {\n if (!visible) return undefined\n return startAutoRefresh()\n }, [visible, startAutoRefresh])\n\n if (!visible) return null\n\n const text = (key: PanelKey): string => view.text[key] ?? key\n // The ring tracks the tightest window — the 5-hour one whenever it is capped,\n // which is the limit an account runs into first, and `footerBars` is ordered\n // that way, so the leading bar is the headline.\n const headline = view.footerBars[0]\n // The tooltip doubles as the accessible name; it always begins with the\n // visible title, so the label the user reads is contained in the name.\n const title = view.footTitle\n\n if (!props.wide) {\n return (\n <button\n type=\"button\"\n className=\"ccp-railButton\"\n aria-label={title}\n title={title}\n onClick={() => props.open()}\n >\n <Ring percent={headline?.barPercent ?? 0} warn={headline?.warn ?? false} size={18} />\n </button>\n )\n }\n\n return (\n <button\n type=\"button\"\n className=\"ccp-foot\"\n aria-label={title}\n title={title}\n onClick={() => props.open()}\n >\n <span className=\"ccp-footTop\">\n <Ring percent={headline?.barPercent ?? 0} warn={headline?.warn ?? false} size={16} />\n <span className=\"ccp-footName\">{text('nav')}</span>\n <span className=\"ccp-spacer\" />\n {view.status !== '' ? (\n <span className=\"ccp-badgeMuted\">{view.status}</span>\n ) : view.planName !== text('nav') ? (\n <span className=\"ccp-badge\">{view.planName}</span>\n ) : null}\n </span>\n\n {view.footerBars.map((bar) => (\n <span className=\"ccp-footRow\" key={bar.label}>\n <span className=\"ccp-footHead\">\n <span className=\"ccp-footLabel\">{text(bar.label)}</span>\n <span className=\"ccp-spacer\" />\n {bar.detail !== '' ? <span className=\"ccp-footAmount\">{bar.detail}</span> : null}\n <span className=\"ccp-footPct\">{bar.percent}</span>\n </span>\n <span className=\"ccp-footBar\">\n <span\n className={bar.warn ? 'ccp-footFill ccp-footFillWarn' : 'ccp-footFill'}\n style={{ width: `${bar.barPercent}%` }}\n />\n </span>\n </span>\n ))}\n </button>\n )\n}\n","/** Shared, JSON-only billing facts. No Host or browser runtime imports. */\nimport type { CommandCodeModelPrice, CommandCodeModelRates, CommandCodePriceTable } from './usage-wire.ts'\n\nexport interface CostTokens {\n uncachedInputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n}\n\n/** Requests with identical model/rates are folded into one group. */\nexport interface CostUsageGroup {\n provider: string\n model: string\n at: number | null\n contextTokens: number\n tokens: CostTokens\n}\n\nexport interface SessionCostFacts {\n pricingKey: number\n groups: CostUsageGroup[]\n}\n\nexport const zeroCostTokens = (): CostTokens => ({ uncachedInputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 })\nexport const COST_TOKEN_KEYS = ['uncachedInputTokens', 'outputTokens', 'cacheReadTokens', 'cacheWriteTokens'] as const\n\nexport function peakHour(at: number, windows: ReadonlyArray<readonly [number, number]>): boolean {\n const time = new Date(at)\n return time.getUTCDay() !== 0 && time.getUTCDay() !== 6\n && windows.some(([start, end]) => time.getUTCHours() >= start && time.getUTCHours() < end)\n}\n\n/**\n * All prompt billing buckets determine a request's band, never cumulative\n * session input.\n *\n * A tiered model returns the matching band and does NOT then apply `peak`: the\n * page publishes those two dimensions independently and no row carries both\n * today, so the combination becoming real is visible before it reaches a user.\n * This ordering is a latent choice, not a verified upstream rule.\n */\nexport function requestRates(price: CommandCodeModelPrice, at: number | null, contextTokens: number, table: CommandCodePriceTable): CommandCodeModelRates {\n // ORDER IS LOAD-BEARING: the generator refuses non-ascending bounds or a\n // bounded last band and the wire parser rejects the same shapes, so a\n // conforming table cannot present bands out of order.\n const tier = price.contextTiers?.find(tier => tier.maxContext === undefined || contextTokens <= tier.maxContext)\n if (tier !== undefined) return tier\n return price.peak !== undefined && at !== null && peakHour(at, table.peakHours) ? price.peak : price\n}\n\n/** Cache version and wire guard: changing bands/rates must refold historical groups. */\nexport function pricingKey(table: CommandCodePriceTable): number {\n const rates = (r: CommandCodeModelRates) => [r.inputCost, r.outputCost, r.cacheReadCost, r.cacheWriteCost ?? null]\n const canonical = JSON.stringify(['commandCodeCost-v1', table.peakHours, table.models.map(p => [p.id, p.slug, p.free === true, rates(p), p.peak ? rates(p.peak) : null, p.contextTiers?.map(t => [t.maxContext ?? null, rates(t)]) ?? null])])\n let hash = 2166136261\n for (const c of canonical) hash = Math.imul(hash ^ c.charCodeAt(0), 16777619) >>> 0\n return hash\n}\n\n/** Only safe to merge requests whose billing classification is identical. */\nexport function costGroupKey(group: CostUsageGroup, table: CommandCodePriceTable): string {\n // The table is mutable, so an identity-keyed index can keep stale model\n // mappings after its rows are changed in place. The projection already\n // indexes its usage groups once per settlement; scan the small price table\n // here so every call observes the current rows.\n const price = table.models.find(p => p.id === group.model || p.slug === group.model)\n return JSON.stringify([group.provider, group.model, price === undefined ? null : requestRates(price, group.at, group.contextTokens, table), group.at === null])\n}\n","/**\n * Session-cost view model for the composer readout.\n *\n * JSX-free and React-free, mirroring `./panel.ts`: it turns the session's token\n * accounting plus the Host's price table into one presentation value AND the\n * exact text the two surfaces of the harness's token-usage UI receive — the\n * amount appended to the shipped pill, and the rows appended to the shipped\n * usage dialog. Node tests therefore drive the whole calculation, and every\n * user-visible string, without a DOM.\n *\n * It prices the session's DURABLE cumulative buckets, which is what the\n * composer's own \"N tokens\" pill reads too (`tokenUsage`), so the two surfaces\n * can never disagree about how much was used. Dollars are computed here because\n * Command Code publishes per-token rates and bills against dollar-denominated\n * windows; the account's own reported `totalCost` is a billing PERIOD figure,\n * not this session's.\n *\n * Three rules are load-bearing: only Command Code usage is priced (a session\n * served by another provider must render nothing, never a Command Code\n * estimate); a missing rate is never invented (the pricing page publishes a\n * cache-WRITE rate for only some models, so unpriced cache-write tokens are\n * surfaced as such rather than charged at a guessed multiple of the input rate);\n * and unpriceable means invisible — a confident `$0.00` would be a lie, and\n * this module never returns one.\n *\n * @module dsh-commandcode-provider/client/session-cost\n */\n\nimport { COST_TOKEN_KEYS, pricingKey, requestRates, peakHour, zeroCostTokens, type SessionCostFacts } from '../cost-facts.ts'\nimport type { CommandCodeModelPrice, CommandCodeModelRates, CommandCodePriceTable } from '../usage-wire.ts'\nimport { formatMoney, formatMoneyExact, formatTokensCompact } from '../display-format.ts'\n\n/** Tokens per published rate unit — the pricing page quotes USD per million. */\nconst TOKENS_PER_RATE_UNIT = 1_000_000\n\n/** The provider route whose usage this surface prices. */\nconst COMMANDCODE_PROVIDER = 'commandcode'\n\n/**\n * The English copy for this surface.\n *\n * A plain constant, NOT the `settings.commandcode` locale namespace: like the\n * plans & quota panel, the readout stays English on a Chinese harness. Do not\n * route it through `ctx.locale`.\n */\nexport const SESSION_COST_COPY = {\n /** Shown instead of an amount when the model costs nothing on every plan. */\n free: 'Free',\n /**\n * The separator the readout prefixes itself with, so the cost reads as the\n * last item of the token-usage pill's text run rather than a control beside\n * it. Rendered with the same colour and margins the shipped pill uses\n * between its own items.\n */\n separator: '·',\n panelTitle: 'Session cost',\n /** Marks an estimate from published rates rather than an invoice. */\n approximate: '≈',\n unpricedCacheWrite: 'cache write tokens have no published rate',\n /** Tooltip line naming the rate half in force. */\n peakRates: 'peak rates',\n offPeakRates: 'off-peak rates',\n /** Tooltip line explaining the approximate marker. */\n approximateNote: 'estimate from published rates, not the provider invoice',\n /** Row/tooltip label for uncached prompt tokens. */\n uncachedInput: 'uncached input',\n /** Row/tooltip label for completion tokens. */\n output: 'output',\n /** Row/tooltip label for cache-served input tokens. */\n cacheRead: 'cache read',\n /** Row/tooltip label for cache-written input tokens. */\n cacheWrite: 'cache write',\n} as const\n\n/**\n * The session's cumulative token buckets, as the `tokenUsage` projection\n * carries them. Declared structurally: this bundle does not depend on the\n * session-controller package, and a bucket the provider never reported is\n * absent rather than zero.\n */\nexport interface SessionUsageBuckets {\n readonly uncachedInputTokens?: number\n readonly outputTokens?: number\n readonly cacheReadTokens?: number\n readonly cacheWriteTokens?: number\n}\n\n/** One entry of the `modelSelection` projection. */\nexport interface SessionModelSelection {\n readonly provider: string\n readonly model: string\n}\n\n/**\n * The `modelSelection` projection: the selection the latest request consumed,\n * and the one the next request will use (falling back to the former).\n */\nexport interface SessionModelSelectionProjection {\n readonly lastUsed: SessionModelSelection | null\n readonly next: SessionModelSelection | null\n}\n\n/** Everything the view needs, already read off the seats by the component. */\nexport interface SessionCostInput {\n /** Durable billing groups; absent on older Hosts means no trustworthy estimate. */\n facts?: SessionCostFacts | undefined\n /** The durable cumulative token buckets, or undefined before any request. */\n usage: SessionUsageBuckets | undefined\n /** The session's model selection fold, or undefined on an older Host. */\n selection: SessionModelSelectionProjection | undefined\n /** The Host's price table, or undefined until it lands. */\n table: CommandCodePriceTable | undefined\n /** Legacy caller field; historical request timestamps alone determine rates. */\n now: number\n}\n\n/** One bucket's line in the usage dialog. */\nexport interface SessionCostBucketRow {\n /** Stable key. */\n key: 'uncachedInput' | 'cacheRead' | 'cacheWrite' | 'output'\n /** Row label. */\n label: string\n /** Tokens charged in this bucket; a bucket that charged nothing withholds its\n * row rather than printing a meaningless zero. */\n tokens: number\n /** What this bucket cost, or undefined when the table has no rate for it. */\n costText: string | undefined\n}\n\n/** The composer readout's presentation value. */\nexport interface SessionCostView {\n /** Priced total in dollars. */\n total: number\n /** Visible amount text, e.g. `$0.0123` (or the free word, when free). */\n value: string\n /** Full tooltip/accessible text, including the bucket breakdown. */\n title: string\n /** Per-bucket lines for the usage dialog, in reading order. */\n rows: SessionCostBucketRow[]\n /** Caveat lines for the pill's tooltip (rate half, approximation, unpriced). */\n notes: string[]\n /** The model costs nothing on every plan right now. */\n free: boolean\n /** The model's `peak` rates are in force. */\n peak: boolean\n /** Cache-write tokens the table has no rate for (never guessed, so the\n * total is a floor rather than an estimate). */\n unpricedCacheWriteTokens: number\n /** Published-rate totals are estimates rather than provider invoices. */\n approximate: boolean\n}\n\n/** A finite, non-negative count — anything else reads as absent. */\nfunction count(value: number | undefined): number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0\n}\n\n/**\n * Index a price table for lookup. Rows are keyed by catalog id and by pricing\n * slug, both exact and lowercased, because a session reports a catalog id while\n * a row no catalog model claims is served under the page's slug.\n */\nfunction indexTable(table: CommandCodePriceTable): Map<string, CommandCodeModelPrice> {\n const index = new Map<string, CommandCodeModelPrice>()\n for (const price of table.models) {\n for (const key of [price.id, price.slug]) {\n if (typeof key !== 'string' || key === '') continue\n if (!index.has(key)) index.set(key, price)\n const lower = key.toLowerCase()\n if (!index.has(lower)) index.set(lower, price)\n }\n }\n return index\n}\n\n/**\n * The dollar cost of each bucket, plus the total and the unpriced remainder.\n *\n * Every bucket is charged at its own published rate; the cache-write bucket\n * contributes only when the model publishes a rate for it, otherwise its tokens\n * come back as {@link SessionCostView.unpricedCacheWriteTokens} and its own cost\n * stays undefined so the panel can say so instead of printing a zero.\n */\ninterface SessionCostBreakdown {\n uncachedInput: number\n cacheRead: number\n cacheWrite: number | undefined\n output: number\n total: number\n unpricedCacheWriteTokens: number\n}\n\nfunction costOf(\n usage: SessionUsageBuckets,\n rates: CommandCodeModelRates,\n free: boolean,\n): SessionCostBreakdown {\n if (free) {\n return { uncachedInput: 0, cacheRead: 0, cacheWrite: 0, output: 0, total: 0, unpricedCacheWriteTokens: 0 }\n }\n const perUnit = (tokens: number, rate: number): number => (tokens * rate) / TOKENS_PER_RATE_UNIT\n const uncachedInput = perUnit(count(usage.uncachedInputTokens), rates.inputCost)\n const output = perUnit(count(usage.outputTokens), rates.outputCost)\n const cacheRead = perUnit(count(usage.cacheReadTokens), rates.cacheReadCost)\n const cacheWriteTokens = count(usage.cacheWriteTokens)\n const cacheWrite = rates.cacheWriteCost === undefined\n ? undefined\n : perUnit(cacheWriteTokens, rates.cacheWriteCost)\n return {\n uncachedInput,\n cacheRead,\n cacheWrite,\n output,\n total: uncachedInput + output + cacheRead + (cacheWrite ?? 0),\n unpricedCacheWriteTokens: rates.cacheWriteCost === undefined ? cacheWriteTokens : 0,\n }\n}\n\n/**\n * Amount text for a session cost.\n *\n * The panel's `money()` convention (2 decimals, 4 below a cent) is right for\n * billing windows, but a live session total starts far below a cent, where\n * `toFixed(4)` would print a flat `$0.0000` — broken rather than small. So a\n * total under $0.0001 is stated as a bound instead.\n */\nexport function sessionCostAmount(total: number): string {\n if (!Number.isFinite(total) || total <= 0) return formatMoney(0)\n if (total < 0.0001) return `<$0.0001`\n return total < 0.01 ? formatMoneyExact(total) : formatMoney(total)\n}\n\n/** One `label value` clause of the tooltip. */\nfunction clause(label: string, tokens: number): string | undefined {\n return tokens > 0 ? `${label} ${formatTokensCompact(tokens)}` : undefined\n}\n\n/**\n * Build the composer readout, or undefined when there is nothing honest to show.\n *\n * Undefined is the correct answer for a session with no usage yet, a session\n * another provider served, a model the price table does not know, and a table\n * that has not landed — the pill simply is not there.\n */\nexport function buildSessionCostView(input: SessionCostInput): SessionCostView | undefined {\n const { usage, table, facts } = input\n if (!usage || !table || !facts || facts.pricingKey !== pricingKey(table)) return undefined\n const totals = zeroCostTokens()\n const index = indexTable(table)\n const breakdown: SessionCostBreakdown = { uncachedInput: 0, cacheRead: 0, cacheWrite: 0, output: 0, total: 0, unpricedCacheWriteTokens: 0 }\n let free = true\n let peak = false\n let partial = false\n let priced = false\n const notes: string[] = []\n for (const group of facts.groups) {\n for (const key of COST_TOKEN_KEYS) totals[key] += group.tokens[key]\n if (group.provider !== COMMANDCODE_PROVIDER) { partial = true; continue }\n const price = index.get(group.model)\n if (!price) { partial = true; continue }\n const isFree = price.free === true\n free &&= isFree\n if (price.peak && group.at === null) {\n partial = true\n notes.push('request time unavailable; off-peak lower bound')\n }\n const rates = requestRates(price, group.at, group.contextTokens, table)\n const part = costOf(group.tokens, rates, isFree)\n priced ||= isFree || part.total > 0\n for (const key of ['uncachedInput', 'cacheRead', 'output', 'total', 'unpricedCacheWriteTokens'] as const) breakdown[key] += part[key]\n breakdown.cacheWrite = (breakdown.cacheWrite ?? 0) + (part.cacheWrite ?? 0)\n if (price.peak) {\n const isPeak = group.at !== null && peakHour(group.at, table.peakHours)\n peak ||= isPeak\n notes.push(isPeak ? SESSION_COST_COPY.peakRates : SESSION_COST_COPY.offPeakRates)\n }\n }\n // Both projections must describe the same durable cut. Never decorate token\n // rows from a newer/older fold, and never price an old Host's cumulative usage.\n if (COST_TOKEN_KEYS.some(key => totals[key] !== count(usage[key])) || !priced) return undefined\n const { total, unpricedCacheWriteTokens } = breakdown\n partial ||= unpricedCacheWriteTokens > 0\n free &&= !partial\n if (partial) notes.push('Command Code priced subtotal only; unpriced or other-provider usage excluded')\n notes.push(SESSION_COST_COPY.approximateNote)\n const uncachedInput = totals.uncachedInputTokens\n const output = totals.outputTokens\n const cacheRead = totals.cacheReadTokens\n const cacheWrite = totals.cacheWriteTokens\n // No billed token of any kind means there is nothing to report yet: a `$0.00`\n // pill on a session that has not made a request would be noise, not\n // information, and on a free model it would be redundant.\n if (uncachedInput === 0 && output === 0 && cacheRead === 0 && cacheWrite === 0) return undefined\n\n // Free priced groups do not establish zero spending for unpriced groups:\n // keep the pure-Free label and real sub-cent amounts, but never a zero\n // subtotal.\n if (!free && total <= 0) return undefined\n\n const value = free\n ? SESSION_COST_COPY.free\n : `${partial ? '≥' : SESSION_COST_COPY.approximate}${sessionCostAmount(total)}`\n const money = (amount: number | undefined): string | undefined =>\n amount === undefined ? undefined : sessionCostAmount(amount)\n // Reading order mirrors the prompt's own order: what was charged at the input\n // rate, then the two cache buckets, then what the model produced.\n const rows: SessionCostBucketRow[] = [\n { key: 'uncachedInput', label: SESSION_COST_COPY.uncachedInput, tokens: uncachedInput, costText: money(breakdown.uncachedInput) },\n { key: 'cacheRead', label: SESSION_COST_COPY.cacheRead, tokens: cacheRead, costText: money(breakdown.cacheRead) },\n { key: 'cacheWrite', label: SESSION_COST_COPY.cacheWrite, tokens: cacheWrite, costText: unpricedCacheWriteTokens === cacheWrite && cacheWrite > 0 ? undefined : money(breakdown.cacheWrite) },\n { key: 'output', label: SESSION_COST_COPY.output, tokens: output, costText: money(breakdown.output) },\n ]\n if (unpricedCacheWriteTokens > 0) notes.push(SESSION_COST_COPY.unpricedCacheWrite)\n // Empty clauses are dropped BEFORE joining: `clause()` returns undefined for\n // a bucket with no tokens, and joining the raw list would leave a `· ·` gap\n // per absent bucket — a tooltip that reads as a rendering bug.\n const title = ([\n `${SESSION_COST_COPY.panelTitle} ${free ? SESSION_COST_COPY.free : sessionCostAmount(total)}`,\n clause(SESSION_COST_COPY.uncachedInput, uncachedInput),\n clause(SESSION_COST_COPY.output, output),\n clause(SESSION_COST_COPY.cacheRead, cacheRead),\n clause(SESSION_COST_COPY.cacheWrite, cacheWrite),\n ...notes,\n ] as Array<string | undefined>).filter((part): part is string => part !== undefined).join(' · ')\n\n return {\n total,\n value,\n title,\n rows,\n notes: [...new Set(notes)],\n free,\n peak,\n unpricedCacheWriteTokens,\n approximate: !free,\n }\n}\n\n/**\n * The two nodes the text appended to the harness's token-usage pill is made of.\n *\n * The separator is a node of its own because it carries the shipped pill's\n * SEPARATOR colour rather than its label colour; the pill is a flex row whose\n * `gap` already spaces the appended item, so the separator is what makes the\n * result read as one continuous run (`1.2M tokens · Cache hit 87% · $0.0123`).\n */\nexport interface SessionCostPillRun {\n /** The shipped pill's own separator glyph. */\n separator: string\n /** The amount, `≈` marker and free word included. */\n value: string\n}\n\n/** Split the appended run into the two nodes the display creates. */\nexport function sessionCostPillRun(view: SessionCostView): SessionCostPillRun {\n return { separator: SESSION_COST_COPY.separator, value: view.value }\n}\n\n/**\n * How the harness's own usage dialog is decorated: one entry per row the\n * shipped component renders, IN ITS OWN ORDER.\n *\n * The price goes on the right of the row it belongs to (`3,206,544 tok $0.07`)\n * rather than in a block of our own rows beneath them, so the dialog keeps the\n * harness's layout and gains nothing to read past.\n *\n * Two rows are special. `cacheHit` carries a percentage, not a count, so it is\n * never priced. `cacheWrite` may be HIDDEN, and only then: the pricing page\n * publishes a cache-write rate for a minority of models, so its cell read\n * `unpriced` far more often than a number — but its tokens still count toward\n * the total the pill shows.\n */\nexport type SessionCostShippedRow = 'cacheHit' | 'uncachedInput' | 'cacheRead' | 'cacheWrite' | 'output'\n\n/** One shipped dialog row and what to do with it. */\nexport interface SessionCostRowDecoration {\n /** Which shipped row this is. */\n row: SessionCostShippedRow\n /**\n * The exact token count that row must be showing, or undefined for a row that\n * carries no count. The display layer verifies it before decorating anything:\n * the shipped labels are the `chat` locale's own strings (never English), so\n * rows are matched POSITIONALLY and this is what proves the position is right.\n */\n tokens: number | undefined\n /** The price to append to the row's value, or undefined to leave it alone. */\n amount: string | undefined\n /** Whether the row is dropped from the dialog entirely. */\n hidden: boolean\n}\n\n/**\n * Decorate the harness's usage dialog, row by row.\n *\n * The row sequence mirrors the shipped component's conditions exactly — the\n * cache-hit row exists while there is billed prompt input, the cache-write row\n * while those tokens are non-zero — because the display layer matches what it\n * finds positionally. A shape it cannot confirm is a shape it does not touch.\n *\n * A free model decorates nothing: every row's cost is zero by definition, the\n * pill already says `Free`, and a column of `$0.00` would be noise. A bucket\n * whose rate the page does not publish is likewise left unfilled rather than\n * filled with an invented number.\n */\nexport function sessionCostRowDecorations(view: SessionCostView): SessionCostRowDecoration[] {\n const bucket = (key: SessionCostBucketRow['key']): number =>\n view.rows.find((row) => row.key === key)?.tokens ?? 0\n const price = (key: SessionCostBucketRow['key']): string | undefined => {\n if (view.free) return undefined\n return view.rows.find((row) => row.key === key)?.costText\n }\n const uncachedInput = bucket('uncachedInput')\n const cacheRead = bucket('cacheRead')\n const cacheWrite = bucket('cacheWrite')\n const output = bucket('output')\n const plan: SessionCostRowDecoration[] = []\n if (uncachedInput + cacheRead + cacheWrite > 0) {\n plan.push({ row: 'cacheHit', tokens: undefined, amount: undefined, hidden: false })\n }\n plan.push({ row: 'uncachedInput', tokens: uncachedInput, amount: price('uncachedInput'), hidden: false })\n plan.push({ row: 'cacheRead', tokens: cacheRead, amount: price('cacheRead'), hidden: false })\n if (cacheWrite !== 0) {\n // Hidden only when the page publishes NO cache-write rate: those tokens are\n // genuinely unpriced, the note says so, and the row would otherwise show a\n // blank cell. When the rate IS known its price is part of the total, so the\n // row must stay — hiding it leaves the visible rows unable to explain the\n // figure above them.\n const amount = price('cacheWrite')\n plan.push({ row: 'cacheWrite', tokens: cacheWrite, amount, hidden: amount === undefined })\n }\n plan.push({ row: 'output', tokens: output, amount: price('output'), hidden: false })\n return plan\n}\n","/**\n * The DOM half of the composer's session-cost figure (browser only).\n *\n * The cost is not a surface of its own any more: it is injected INTO the two\n * surfaces the harness already draws under the composer — the token-usage pill\n * and the usage dialog that pill opens. This module owns that injection;\n * `./session-cost.ts` owns every number and string, and `./session-cost-view.tsx`\n * the two seats the figures come from.\n *\n * Why inject rather than take the pill's cell over (registering a `stats` entry\n * REPLACES the shipped readout, it does not extend it): that row is one component\n * owning its tokens / cache-hit / duration figures through the `chat` locale\n * namespace, and its cache-hit percentage obeys an exact-integer rule this plugin\n * must not re-derive. Owning it would mean reproducing all of it in English, and\n * every upstream change would stop reaching users.\n *\n * Four properties make the injection safe:\n *\n * 1. **The dialog's rows are styled by ELEMENT.** `dsh-client-ui-chat`'s\n * `stat-dialog` module styles its `dl` as a two-column grid and then\n * `.details dt` / `.details dd` — not by class, so a price node appended\n * INSIDE a shipped value cell inherits that cell's tabular numerals and right\n * alignment, and this plugin ships no CSS at all.\n * 2. **The dialog's rows are matched by POSITION and confirmed by value.** Their\n * labels are the `chat` locale's own strings, so no label is ever read: the\n * shape is predicted from the session's buckets and each value cell must then\n * carry exactly the token count predicted for it. A dialog that does not\n * confirm is left alone.\n * 3. **The pill keeps the cost visible when space runs out.** The button is an\n * inline flex row with `gap` and its label carries `min-width:0` plus ellipsis;\n * our appended span keeps the default `min-width:auto`, so the LABEL is what\n * truncates, and the cost inherits the button's typography and tint.\n * 4. **React owns those value cells' text, so a price is re-attached, never\n * assumed.** The shipped component renders each count as a single string, and\n * React rewrites such a cell through `textContent` when the count changes —\n * dropping every child with it, our price included. Every sync therefore\n * re-checks that the node is still where it was put; the cost of that is a\n * read, and the alternative is a price that silently disappears mid-session.\n *\n * A `MutationObserver` on `document.body` with `childList` (deliberately NOT\n * `subtree`, so streaming text never wakes it) is the only way to learn that the\n * portaled dialog has opened or closed. That observer is also what decorates a\n * newly opened dialog from the last view this module was handed.\n *\n * @module dsh-commandcode-provider/client/session-cost-display\n */\n\nimport type { SessionCostPillRun, SessionCostRowDecoration, SessionCostShippedRow, SessionCostView } from './session-cost.ts'\nimport {\n SESSION_COST_COPY,\n sessionCostPillRun,\n sessionCostRowDecorations,\n} from './session-cost.ts'\n\n/**\n * The shipped composer stats row (dsh-client-ui-chat `StatsPills`).\n *\n * A PREFERENCE, not a requirement: the attribute has been dropped TWICE\n * upstream — in 0.1.6-alpha.2, and again in 0.2.1-alpha.1, where the single\n * `StatsPills` component became two independent dock entries (`activity` and\n * `usage`) and each pill lost the shared row wrapper this selector named. A\n * lookup that insisted on it would silently stop finding the row. When it is\n * absent the search falls back to the dock OUTLET — deliberately the outlet\n * and never the outlet's parent, because the parent is the composer footer,\n * which holds the `ContextMeter` as well, and that meter's trigger is itself a\n * `button[aria-haspopup=\"dialog\"]` rendered AFTER the dock. A parent-scoped\n * \"last trigger wins\" would append the cost to the context ring instead.\n *\n * The fallback is still correct on 0.2.1-alpha.1: the dock registers `activity`\n * at order 0 and `usage` at order 1, both keep `aria-haspopup=\"dialog\"` on their\n * trigger button, and `data-session-stats-usage` remains unique to the token\n * dialog — so \"last trigger wins\" still selects the usage pill.\n */\nconst STATS_ROOT = '[data-composer-stats]'\n\n/**\n * The shipped token-usage dialog's `<dl>`. Unique WITHIN one `StatsPills`\n * render (the per-message turn-usage panel has its own dialog with different\n * markup), but not across the document once two composers are live — see\n * {@link resolveDialog}.\n */\nconst USAGE_DIALOG = '[data-session-stats-usage]'\n\n/**\n * The usage dialog's trigger. Both pills announce a dialog, but the token one is\n * rendered LAST — and when no step carries timing the time pill is not a button\n * at all, so \"last\" still selects the token pill in both cases.\n */\nconst DIALOG_TRIGGER = 'button[aria-haspopup=\"dialog\"]'\n\n/**\n * Stable id for the hidden node the appended cost is described by. The pill's own\n * `aria-label` is recomputed by the harness on every render and cannot be\n * extended, so a description is how the cost reaches assistive technology.\n */\nconst A11Y_ID = 'dsh-commandcode-session-cost'\n\n/** How many consecutive misses before the missing anchor is worth a console line. */\nconst MISSES_BEFORE_WARNING = 3\n\n/**\n * How the display learns that the shipped usage dialog opened or closed.\n *\n * `target` is `document.body`, and the returned function detaches. The default\n * is a `MutationObserver`; the seam exists so tests can announce the dialog\n * without a global observer (the repository's usual injected-seam shape).\n */\nexport type SessionCostObserverFactory = (target: Node, listener: () => void) => (() => void) | undefined\n\n/**\n * The default observer: `childList` on `body`, and deliberately NOT `subtree`, so\n * streaming text inside the page never wakes it while the panel the harness\n * portals straight onto `body` does.\n */\nconst observeBodyChildren: SessionCostObserverFactory = (target, listener) => {\n if (typeof MutationObserver === 'undefined') return undefined\n const observer = new MutationObserver(listener)\n observer.observe(target, { childList: true })\n return () => observer.disconnect()\n}\n\n/** What the display layer reads: the injected document and where to look in it. */\nexport interface SessionCostDisplayOptions {\n /** The document to inject into (injected so node tests can drive a double). */\n doc: Document\n /**\n * The composer that owns this entry — our own dock OUTLET, so a session-scoped\n * composer looks in its OWN card rather than at whichever `[data-composer-stats]`\n * happens to come first in the document.\n */\n scope: () => ParentNode | null\n /** Observer seam; defaults to a `childList` `MutationObserver` on `body`. */\n observe?: SessionCostObserverFactory\n}\n\n/**\n * Owns the nodes injected into the shipped token-usage UI.\n *\n * One instance per mounted entry. `sync()` is cheap and idempotent: it re-reads\n * both targets on every call, which is what lets it self-heal when React\n * remounts the row or replaces the dialog, and it rewrites a node only when its\n * text actually changed.\n */\nexport class SessionCostDisplay {\n private readonly doc: Document\n private readonly scope: () => ParentNode | null\n private readonly observe: SessionCostObserverFactory\n private view: SessionCostView | undefined = undefined\n /** Detaches the observer installed by `start()`. */\n private detach: (() => void) | undefined = undefined\n /** The button we appended into, while it is still connected. */\n private pillHost: Element | undefined = undefined\n /** Our appended root, and the two nodes whose text changes. */\n private pillRoot: HTMLElement | undefined = undefined\n private pillValue: HTMLElement | undefined = undefined\n private pillA11y: HTMLElement | undefined = undefined\n /** Whether WE set `aria-describedby` on the button (so only we take it back). */\n private described = false\n /** The dialog we decorated, the price nodes we own, and the cells we hid. */\n private dialogHost: Element | undefined = undefined\n private dialogPrices = new Map<HTMLElement, HTMLElement>()\n private dialogHidden = new Set<HTMLElement>()\n private pillMisses = 0\n\n constructor(options: SessionCostDisplayOptions) {\n this.doc = options.doc\n this.scope = options.scope\n this.observe = options.observe ?? observeBodyChildren\n }\n\n /** Begin watching for the shipped usage dialog opening and closing. */\n start(): void {\n if (this.detach !== undefined) return\n const body = this.doc.body\n if (body === null || body === undefined) return\n this.detach = this.observe(body, () => this.apply())\n }\n\n /**\n * Hand the display the current figure.\n *\n * Undefined — nothing priceable about this session — removes everything this\n * module injected, leaving both shipped surfaces exactly as they ship.\n */\n sync(view: SessionCostView | undefined): void {\n this.view = view\n this.apply()\n }\n\n /** Remove every injected node and stop observing. Safe to call twice. */\n dispose(): void {\n this.detach?.()\n this.detach = undefined\n this.removePill()\n this.clearDialog()\n this.view = undefined\n }\n\n /** Re-apply the last known view to whatever both targets are right now. */\n private apply(): void {\n this.applyPill()\n this.applyDialog()\n }\n\n // --- The pill: the cost as the last item of the shipped token pill's run\n\n private applyPill(): void {\n const view = this.view\n if (view === undefined) {\n this.removePill()\n return\n }\n if (this.pillHost?.isConnected !== true) {\n const button = this.resolvePillButton()\n if (button === null) {\n this.pillMisses += 1\n if (this.pillMisses === MISSES_BEFORE_WARNING) {\n console.warn(\n '[dsh-commandcode-provider] no shipped token pill in this composer\\'s dock outlet to append the session cost to; the figure stays in the usage dialog only',\n )\n }\n return\n }\n this.pillMisses = 0\n this.removePill()\n this.buildPill(button, sessionCostPillRun(view))\n }\n if (this.pillValue !== undefined) {\n const amount = sessionCostPillRun(view).value\n if (this.pillValue.textContent !== amount) this.pillValue.textContent = amount\n }\n if (this.pillRoot !== undefined) {\n if (this.pillRoot.title !== view.title) this.pillRoot.title = view.title\n const approximate = view.approximate ? 'true' : null\n if (this.pillRoot.getAttribute('data-approximate') !== approximate) {\n if (approximate === null) this.pillRoot.removeAttribute('data-approximate')\n else this.pillRoot.setAttribute('data-approximate', approximate)\n }\n }\n if (this.pillA11y !== undefined) {\n const described = `${SESSION_COST_COPY.panelTitle} ${view.value}`\n if (this.pillA11y.textContent !== described) this.pillA11y.textContent = described\n }\n }\n\n /**\n * The shipped token pill, scoped to this entry's own composer.\n *\n * The scope is the dock OUTLET (`display: contents`, one per slot), which holds\n * exactly that slot's entries — the shipped `stats` cell and ours, in their\n * registration order. {@link STATS_ROOT} narrows that to the stats row where\n * the markup marks it; where it does not, the outlet is already the narrowest\n * correct container, because the composer footer's `ContextMeter` sits BESIDE\n * the outlet rather than inside it. A missing scope is \"no pill\", never a\n * document-wide search: the outlet is what makes this lookup per-composer, and\n * two composers can be live at once.\n */\n private resolvePillButton(): Element | null {\n const scope = this.scope()\n if (scope === null) return null\n const root = scope.querySelector(STATS_ROOT) ?? scope\n const triggers = root.querySelectorAll(DIALOG_TRIGGER)\n return triggers.length === 0 ? null : (triggers[triggers.length - 1] ?? null)\n }\n\n /**\n * Create and append the cost run. The button's child list is static\n * (`[svg, label]`), so appending once is enough for it to stay last.\n */\n private buildPill(button: Element, run: SessionCostPillRun): void {\n const doc = this.doc\n const root = doc.createElement('span')\n root.setAttribute('data-composer-session-cost', '')\n // The separator is its own node so it can carry the shipped pill's separator\n // colour. Its LEFT spacing comes from the button's flex gap; the right margin\n // reproduces the shipped separator's `margin:0 6px` rhythm, so the run reads\n // at one consistent rhythm.\n const separator = doc.createElement('span')\n separator.textContent = run.separator\n separator.setAttribute('aria-hidden', 'true')\n separator.style.color = 'var(--dsw-alias-separator-primary)'\n separator.style.margin = '0 6px 0 0'\n const value = doc.createElement('span')\n value.textContent = run.value\n value.style.fontWeight = '500'\n // Referenced by the button's `aria-describedby`: a hidden node named by id is\n // still read out, which is how the cost survives the aria-label override.\n const a11y = doc.createElement('span')\n a11y.id = A11Y_ID\n a11y.style.display = 'none'\n root.appendChild(separator)\n root.appendChild(value)\n root.appendChild(a11y)\n button.appendChild(root)\n // Only ever claim the attribute when the button has none of its own: a\n // shipped `aria-describedby` is the harness's, and overwriting it would\n // delete a description we cannot restore.\n if (!button.hasAttribute('aria-describedby')) {\n button.setAttribute('aria-describedby', A11Y_ID)\n this.described = true\n }\n this.pillHost = button\n this.pillRoot = root\n this.pillValue = value\n this.pillA11y = a11y\n }\n\n private removePill(): void {\n if (this.pillRoot !== undefined && this.pillRoot.parentNode !== null) {\n this.pillRoot.parentNode.removeChild(this.pillRoot)\n }\n if (this.described) {\n this.pillHost?.removeAttribute('aria-describedby')\n this.described = false\n }\n this.pillHost = undefined\n this.pillRoot = undefined\n this.pillValue = undefined\n this.pillA11y = undefined\n }\n\n // --- The dialog: a price on the right of each row the harness already draws\n\n private applyDialog(): void {\n const view = this.view\n const host = view === undefined ? null : this.resolveDialog()\n if (host === null || view === undefined) {\n this.clearDialog()\n return\n }\n this.pruneDialog(host)\n const plan = sessionCostRowDecorations(view)\n const pairs = dialogPairs(host)\n if (!dialogShapeMatches(pairs, plan, this.dialogPrices)) {\n // Not the shape this session's buckets predict — a different build, or a\n // projection carrying values the counts cannot explain. Leave it as the\n // harness drew it rather than pricing the wrong row.\n this.clearDialog()\n return\n }\n const hidden = new Set<HTMLElement>()\n for (const [index, row] of plan.entries()) {\n const pair = pairs[index]\n if (pair === undefined) continue\n const span = this.dialogPrices.get(pair.dd)\n if (row.hidden) {\n // Both cells go, or the grid leaves an empty label behind. An inline\n // `display` survives the harness's own re-renders (React pins no style\n // on these nodes) and is given back on disposal.\n if (pair.dt.style.display !== 'none') pair.dt.style.display = 'none'\n if (pair.dd.style.display !== 'none') pair.dd.style.display = 'none'\n hidden.add(pair.dt)\n hidden.add(pair.dd)\n this.removeDialogPrice(pair.dd, span)\n continue\n }\n if (pair.dt.style.display === 'none') pair.dt.style.display = ''\n if (pair.dd.style.display === 'none') pair.dd.style.display = ''\n if (row.amount === undefined) {\n this.removeDialogPrice(pair.dd, span)\n continue\n }\n const price = span ?? this.createDialogPrice(pair.dd, row.row)\n // React owns this cell's text and rewrites it through `textContent` when\n // the count changes, dropping every child with it — so the price is\n // re-attached on a miss rather than assumed to still be there.\n if (price.parentNode !== pair.dd) pair.dd.appendChild(price)\n if (price.textContent !== row.amount) price.textContent = row.amount\n }\n // Cells hidden by an earlier shape (a cache-write row React then rewrote) go\n // back to the harness.\n for (const cell of [...this.dialogHidden]) {\n if (hidden.has(cell)) continue\n if (cell.style.display === 'none') cell.style.display = ''\n this.dialogHidden.delete(cell)\n }\n for (const cell of hidden) this.dialogHidden.add(cell)\n this.dialogHost = host\n }\n\n /** Forget the cells and prices a re-rendered dialog took with it. */\n private pruneDialog(host: Element): void {\n for (const [dd, price] of [...this.dialogPrices]) {\n if (dd.parentNode === host) continue\n if (price.parentNode !== null) price.parentNode.removeChild(price)\n this.dialogPrices.delete(dd)\n }\n for (const cell of [...this.dialogHidden]) {\n if (cell.parentNode === host) continue\n // The dialog was re-rendered and this cell went with the old tree. Give\n // the style back BEFORE dropping the reference: a detached node can be\n // recycled by the next render (React reuses DOM nodes across a remount of\n // the same shape), and a surviving `display: none` would hide a row of a\n // dialog we are no longer decorating, with nothing left tracking it.\n if (cell.style.display === 'none') cell.style.display = ''\n this.dialogHidden.delete(cell)\n }\n }\n\n /** The price node for one shipped value cell, appended as its last child. */\n private createDialogPrice(dd: HTMLElement, row: SessionCostShippedRow): HTMLElement {\n const price = this.doc.createElement('span')\n price.setAttribute('data-session-cost-price', row)\n // The cell is right-aligned over tabular numerals, so a fixed-width\n // inline-block lines the prices up as a column of their own.\n price.style.marginLeft = '6px'\n price.style.display = 'inline-block'\n price.style.minWidth = '56px'\n price.style.textAlign = 'right'\n price.style.fontWeight = '500'\n dd.appendChild(price)\n this.dialogPrices.set(dd, price)\n return price\n }\n\n private removeDialogPrice(dd: HTMLElement, price: HTMLElement | undefined): void {\n if (price === undefined) return\n if (price.parentNode !== null) price.parentNode.removeChild(price)\n this.dialogPrices.delete(dd)\n }\n\n /**\n * The shipped usage dialog, or null while it is closed (or ambiguous).\n *\n * The dialog is portaled onto `body`, so unlike the pill it cannot be scoped\n * from this entry, and the attribute is unique per DIALOG rather than per\n * document. While one composer was guaranteed a document-level lookup was\n * exact; 0.1.6-alpha.2 ended that guarantee by mounting an embedded\n * Conversation in the sidebar, so a second composer — its own session, dock and\n * dialog — can be live and open at the same time.\n *\n * There is no DOM link from a dialog back to its trigger (the portaled panel\n * carries no id and no `aria-controls`), so document order says nothing about\n * ownership. The shape confirmation in {@link dialogShapeMatches} would usually\n * reject the stranger, but it compares against THIS entry's counts, so a\n * coincidentally matching dialog would be priced with another session's\n * figures. Ambiguity is therefore answered by declining to decorate at all:\n * a dialog we cannot prove is ours is left alone.\n */\n private resolveDialog(): Element | null {\n if (this.dialogHost?.isConnected === true) return this.dialogHost\n // The dialog we injected into is gone: our nodes went with it, so only the\n // bookkeeping is left to drop.\n this.clearDialog()\n const dialogs = this.doc.querySelectorAll(USAGE_DIALOG)\n return dialogs.length === 1 ? (dialogs[0] ?? null) : null\n }\n\n /** Give the dialog back: every price removed, every hidden row restored. */\n private clearDialog(): void {\n for (const price of this.dialogPrices.values()) {\n if (price.parentNode !== null) price.parentNode.removeChild(price)\n }\n this.dialogPrices.clear()\n for (const cell of this.dialogHidden) {\n if (cell.style.display === 'none') cell.style.display = ''\n }\n this.dialogHidden.clear()\n this.dialogHost = undefined\n }\n}\n\n/** The shipped dialog's `dt`/`dd` pairs, in document order. */\nfunction dialogPairs(host: Element): Array<{ dt: HTMLElement; dd: HTMLElement }> {\n const pairs: Array<{ dt: HTMLElement; dd: HTMLElement }> = []\n let label: HTMLElement | null = null\n for (const node of Array.from(host.childNodes)) {\n const tag = tagNameOf(node)\n if (tag === 'DT') label = node as HTMLElement\n else if (tag === 'DD' && label !== null) {\n pairs.push({ dt: label, dd: node as HTMLElement })\n label = null\n }\n }\n return pairs\n}\n\n/** `tagName` upper-cased, or an empty string for a non-element node. */\nfunction tagNameOf(node: Node): string {\n const tag = (node as Element).tagName\n return typeof tag === 'string' ? tag.toUpperCase() : ''\n}\n\n/**\n * Whether the dialog really holds the rows this session's buckets predict.\n *\n * The shipped labels belong to the `chat` locale and differ per language, so rows\n * are matched by POSITION, and this is what makes that safe: the row count must\n * agree, the cache-hit row must be the percentage it is, and every other value\n * must carry exactly the token count of the bucket predicted for it. A mismatch\n * means the dialog is not what this view describes, and nothing is decorated.\n */\nfunction dialogShapeMatches(\n pairs: ReadonlyArray<{ dt: HTMLElement; dd: HTMLElement }>,\n plan: readonly SessionCostRowDecoration[],\n prices: ReadonlyMap<HTMLElement, HTMLElement>,\n): boolean {\n if (pairs.length !== plan.length) return false\n return plan.every((row, index) => {\n const pair = pairs[index]\n if (pair === undefined) return false\n const text = hostValueText(pair.dd, prices.get(pair.dd))\n if (row.tokens === undefined) return text.includes('%')\n return digitsOf(text) === String(row.tokens)\n })\n}\n\n/**\n * A value cell's own text, without the price this module appended to it — the\n * digits of `3,206,544 tok` are the host's, the digits of `$0.07` are ours.\n */\nfunction hostValueText(dd: HTMLElement, price: HTMLElement | undefined): string {\n let text = ''\n for (const node of Array.from(dd.childNodes)) {\n if (node === price) continue\n text += node.textContent ?? ''\n }\n return text\n}\n\n/** Every digit of a display string, so locale grouping cannot break the match. */\nfunction digitsOf(text: string): string {\n return text.replace(/\\D/g, '')\n}\n","/**\n * The composer's live session-cost figure (browser half).\n *\n * This component renders NO surface of its own: the cost lives inside the\n * harness's own token-usage UI, the amount as the last item of the shipped\n * pill's text run (`1.2M tokens · Cache hit 87% · $0.0123`) and the breakdown as\n * extra rows in the usage dialog that pill opens. `./session-cost-display.ts`\n * owns that injection and `./session-cost.ts` every number and string; this file\n * owns the two seats the figures come from and the injection's lifetime.\n *\n * It is registered in `conversation.composer.dock` because that registration is\n * what delivers the seats: `useProjection` is a standard prop the composer hands\n * every dock occupant, and registering under the shipped `stats` cell's id would\n * REPLACE the harness's readout instead of extending it.\n *\n * The rendered node is a hidden marker — `display:none`, so it adds neither a box\n * nor a flex gap. It locates THIS composer from the entry (`closest()` on the\n * dock's outlet anchor), so a session-scoped composer reads its own card rather\n * than whichever row comes first, and it renders only while there is something\n * to show.\n *\n * Two seats are read, from two different owners: `useProjection` comes from the\n * composer (a standard prop, not part of this registration) and\n * `useCommandCodePrices` from our own `inject` face. Reading `props.hooks.*`\n * instead finds `undefined` at runtime and crashes the render, which the slot\n * renderer contains by ABDICATING the entry — a surface that vanishes with no\n * visible error. Both effects are `useEffect`, never `useLayoutEffect`: there is\n * nothing on screen to align with, and a layout effect would warn from the\n * server render the tests use.\n *\n * @module dsh-commandcode-provider/client/session-cost-view\n */\n\nimport type { SessionCostFacts } from '../cost-facts.ts'\nimport { useEffect, useRef } from 'react'\nimport type { SnapshotStore } from './snapshot-store.ts'\nimport type { SessionCostPricesState } from './prices.ts'\nimport { SessionCostDisplay } from './session-cost-display.ts'\nimport {\n buildSessionCostView,\n type SessionModelSelectionProjection,\n type SessionUsageBuckets,\n} from './session-cost.ts'\n\n/**\n * The dock outlet this entry renders inside, i.e. what it scopes itself from.\n *\n * The OUTLET, not its parent. The outlet is one `display:contents` div holding\n * exactly this slot's entries (the shipped `stats` cell and ours), so it is the\n * narrowest container that is still per-composer. Its parent is NOT: from\n * 0.1.6-alpha.2 the composer stacks the dock inside a footer that also holds the\n * `ContextMeter`, whose trigger is another `button[aria-haspopup=\"dialog\"]`\n * rendered after the dock — scoping to the parent would let the cost land on the\n * context ring.\n */\nconst DOCK_ANCHOR = '[data-slot=\"conversation.composer.dock\"]'\n\n/** Module-level constant so the marker's `style` prop never diffs. */\nconst HIDDEN_STYLE = { display: 'none' } as const\n\n/**\n * The injected face this registration carries. Bound by the client entry so the\n * component stays unaware of the Remote, the controller, and its caching.\n *\n * NOTE the split from {@link SessionCostComponentProps}: the renderer\n * destructures this face's `hooks` compartment and re-exposes each member as a\n * `use<Name>` prop (`commandCodePrices` → `useCommandCodePrices`); it does not\n * hand the component this object verbatim.\n */\nexport interface SessionCostInjected {\n hooks: {\n commandCodePrices: SnapshotStore<SessionCostPricesState>\n }\n}\n\n/**\n * The projection keys this readout reads, declared structurally because the\n * plugin bundle does not depend on the session-controller package (whose\n * `UseProjection` this mirrors).\n */\ninterface ProjectionSeats {\n commandCodeCost: SessionCostFacts\n tokenUsage: SessionUsageBuckets\n modelSelection: SessionModelSelectionProjection\n}\n\n/** The projection reader the composer supplies to every dock occupant. */\nexport interface UseProjectionLike {\n <K extends keyof ProjectionSeats>(key: K): ProjectionSeats[K] | undefined\n <K extends keyof ProjectionSeats, S>(\n key: K,\n selector: (value: ProjectionSeats[K] | undefined) => S,\n eq?: (a: S, b: S) => boolean,\n ): S\n}\n\n/** The props this component actually receives. */\nexport interface SessionCostComponentProps {\n useCommandCodePrices<T>(selector: (state: SessionCostPricesState) => T): T\n useProjection: UseProjectionLike\n}\n\n/** Log a missing seat once per page, so a silent no-op stays diagnosable. */\nlet warnedMissingSeat = false\n\n/**\n * The composer's session-cost entry. Guards the two seats before rendering the\n * mount: a dsh that does not supply the projection seat to dock occupants gets\n * an absent cost and one console line, never a render crash — which the renderer\n * would answer by abdicating the entry with no visible trace.\n */\nexport function CommandCodeSessionCost(props: SessionCostComponentProps) {\n if (typeof props.useProjection !== 'function' || typeof props.useCommandCodePrices !== 'function') {\n if (!warnedMissingSeat) {\n warnedMissingSeat = true\n console.error(\n '[dsh-commandcode-provider] the composer does not supply the projection/hook seats the session-cost readout needs; the readout stays hidden',\n )\n }\n return null\n }\n return <SessionCostEntry {...props} />\n}\n\n/** The mount: one injection lifetime, one hidden marker. Every hook lives here. */\nfunction SessionCostEntry(props: SessionCostComponentProps) {\n const markerRef = useRef<HTMLSpanElement | null>(null)\n const displayRef = useRef<SessionCostDisplay | null>(null)\n const prices = props.useCommandCodePrices((state) => state)\n const usage = props.useProjection('tokenUsage')\n const selection = props.useProjection('modelSelection')\n const facts = props.useProjection('commandCodeCost')\n const view = buildSessionCostView({ usage, selection, facts, table: prices.table, now: Date.now() })\n\n useEffect(() => {\n // No DOM outside a browser: the server render used by the tests, and a\n // node-hosted assembly, must both stay no-ops.\n if (typeof document === 'undefined') return\n const display = new SessionCostDisplay({\n doc: document,\n scope: () => markerRef.current?.closest(DOCK_ANCHOR) ?? null,\n })\n displayRef.current = display\n display.start()\n return () => {\n displayRef.current = null\n display.dispose()\n }\n }, [])\n\n // Every render: the projection is a fresh fold, so there is nothing cheaper to\n // compare than the plan the display derives from it — and the display rewrites\n // a node only when that node's own text actually moved.\n useEffect(() => {\n displayRef.current?.sync(view)\n })\n\n if (view === undefined) return null\n return <span ref={markerRef} style={HIDDEN_STYLE} data-ccp-session-cost-anchor=\"\" />\n}\n","/**\n * Stylesheet for the Command Code settings page — and the Models-page provider\n * card, which shares its `cc-` classes.\n *\n * Returned as a string, not injected here, so importing this module has no DOM\n * side effect: `./index.ts` installs it once under {@link PAGE_CSS_ID}. It is a\n * module of its own rather than a literal in the entry so `tests/styles.test.ts`\n * can audit every rule without importing the React tree (which pulls\n * `*.module.css` through the primitives package and needs a loader registered\n * first). The rules are GLOBAL CSS, so containment is a contract (issue #48):\n * every selector is qualified by one of our own `cc-` classes. Colours are\n * harness theme aliases with neutral fallbacks, and the `cc-` prefix keeps\n * these clear of the panel's `ccp-` set.\n *\n * @module dsh-commandcode-provider/client/page-styles\n */\n\n/**\n * Stylesheet id — the `data-plugin-css` value that makes injection idempotent.\n *\n * The prefix must match this package's real name and the panel stylesheet's\n * (`PANEL_CSS_ID`); the two ids must also stay DISTINCT, since they key two\n * separate style tags and a shared id would make the second injection a no-op.\n */\nexport const PAGE_CSS_ID = '@mars-sea/dsh-commandcode-provider/CommandCodeSettingsPage.module.css'\n\n/**\n * The settings-page stylesheet.\n *\n * The metrics are the harness's own settings pages', read out of the 0.1.7\n * bundles so the page sits beside General and Models without looking foreign:\n * a row is 12px of padding, its title 14/22 label-primary and its description\n * 12/18 label-tertiary, the control on the right. The hairline rhythm is\n * section-level: a 0.5px border-l2 rule separates the GROUPS (see\n * `cc-groupDivided`), never the rows inside one, so a group's rows read as one\n * list. Selectors and buttons are capsules (36px / 28px compact), inputs are\n * 32px with an 8px radius and a 0.5px border-l4 edge, a card is a 0.5px\n * border-l4 outline with a 16px radius, and a nested panel is a\n * bg-module-platform fill with a 12px radius. Errors use state-error-primary.\n */\nexport const PAGE_CSS = `\n.cc-section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;display:flex}\n.cc-title{margin:0;color:var(--dsw-alias-label-primary);font-size:16px;font-weight:500;line-height:24px}\n.cc-intro{margin:4px 0 0;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px}\n.cc-readOnly{margin:8px 0 0;color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-tertiary));font-size:12px;line-height:18px}\n.cc-spacer{flex:1}\n.cc-group{flex-direction:column;display:flex;margin-top:28px}\n.cc-groupDivided{margin-top:24px;padding-top:20px;border-top:.5px solid var(--dsw-alias-border-l2)}\n.cc-groupHead{align-items:center;gap:8px;display:flex;min-height:28px;padding-bottom:4px}\n.cc-groupTitle{margin:0;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}\n.cc-groupDesc{margin:0 0 12px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-rows>.cc-groupDesc{margin:0;padding:4px 0 0}\n.cc-disclosure{width:100%;padding:0 0 4px;border:0;background:0 0;font:inherit;text-align:left;cursor:pointer;border-radius:6px}\n.cc-disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\n.cc-rows{flex-direction:column;display:flex}\n.cc-row{align-items:center;gap:8px;display:flex;padding:12px 0}\n.cc-rowFlush{padding:0}\n.cc-rowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:32px;display:flex}\n.cc-rowTitleLine{align-items:center;gap:8px;display:flex;min-width:0}\n.cc-rowTitle{min-width:0;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}\n.cc-rowDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-rowDesc p{margin:0}\n.cc-rowDesc p+p{margin-top:4px}\n.cc-rowError{margin:0;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.cc-rowControl{flex:none;align-items:center;justify-content:flex-end;gap:8px;display:inline-flex;max-width:60%}\n.cc-rowInput{width:200px}\n.cc-rowInputWide{width:280px}\n.cc-linkButton{box-sizing:border-box;flex:none;align-items:center;display:inline-flex;height:28px;padding:0 10px;border:0;border-radius:14px;background:0 0;color:var(--dsw-alias-label-tertiary);font:inherit;font-size:12px;line-height:18px;white-space:nowrap;cursor:pointer}\n.cc-linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}\n.cc-linkButton:disabled{cursor:default;opacity:.4}\n.cc-linkButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-badges{align-items:center;gap:8px;display:inline-flex}\n.cc-badge,.cc-badgeMuted{flex:none;align-items:center;display:inline-flex;white-space:nowrap;border-radius:999px;corner-shape:round;padding:1px 8px;font-size:12px;font-weight:500;line-height:17px}\n.cc-badge{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary)}\n.cc-badgeMuted{border:.5px solid var(--dsw-alias-border-l4);color:var(--dsw-alias-label-tertiary)}\n.cc-badgeWarn{background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-secondary))}\n.cc-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}\n.cc-field+.cc-field{border-top:.5px 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-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:18px}\n.cc-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.cc-reset:disabled{cursor:default;opacity:.4}\n.cc-input{box-sizing:border-box;height:32px;min-width:0;padding:0 10px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-1);font:inherit;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}\n.cc-input::placeholder{color:var(--dsw-alias-label-dimmed)}\n.cc-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}\n.cc-input:disabled{opacity:.6;cursor:default}\n.cc-inputInvalid{border-color:var(--dsw-alias-state-error-primary)}\n.cc-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n.cc-modelSelectAnchor{flex-direction:column;align-items:stretch;gap:6px;display:inline-flex;min-width:160px}\n.cc-selector{box-sizing:border-box;align-items:center;gap:12px;display:inline-flex;height:36px;padding:0 14px;border:0;border-radius:18px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;text-align:left;cursor:pointer}\n.cc-selector:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.cc-selector:disabled{cursor:default;opacity:.4}\n.cc-selector:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-selectorText{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.cc-selectorCaret{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-bottom:3px;transform:rotate(45deg)}\n/* The search box sits inside the Menu anchor, so typing in it never trips\n * the Menu's outside-click close. */\n.cc-modelSearch{width:100%}\n.cc-modelSearch::-webkit-search-cancel-button{cursor:pointer}\n.cc-checkRow{align-items:center;gap:8px;display:inline-flex;min-width:0}\n.cc-checkRow:hover{cursor:pointer}\n/* A hand-drawn box, not the platform's accent-color checkbox: the native\n * control's colours come from color-scheme, which the theme sets once at BOOT\n * and never re-applies in-session, so a native box can paint light-chrome white\n * on a dark page. The mark rides a brand-primary fill, so it takes the brand\n * foreground (the only pairing that survives dark mode's near-white brand), and\n * the outline is a border-l3 hairline because border-l2 leaves an unchecked box\n * invisible against the menu surface. */\n.cc-check{box-sizing:border-box;appearance:none;flex-shrink:0;width:16px;height:16px;margin:0;border:1px solid var(--dsw-alias-border-l3);border-radius:4px;background:0 0;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:3px;left:5px;width:3px;height:7px;border:solid var(--dsw-alias-label-primary-foreground,#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/* Modelled on the platform's own Switch primitive (ui-primitives\n * Switch.module.css): a 36x20 capsule padding its track by 2px and sliding a\n * 16px thumb across the 32px content box. Three things are load-bearing.\n * (1) corner-shape:round on BOTH track and thumb — the theme sets a global\n * superellipse corner shape, which squares a capsule's ends off around a round\n * thumb. (2) No literal colours: brand-primary INVERTS between the modes, so a\n * hardcoded white thumb vanishes on the checked track in dark mode; the brand\n * foreground is what the platform paints on that fill. (3) border-l3 as the\n * off track — border-l2 leaves it indistinguishable from the page. */\n.cc-toggle{box-sizing:border-box;appearance:none;flex-shrink:0;width:36px;height:20px;margin:0;padding:2px;border:0;border-radius:10px;corner-shape:round;background:var(--dsw-alias-border-l3);cursor:pointer;position:relative}\n.cc-toggle:checked{background:var(--dsw-alias-brand-primary)}\n.cc-toggle::after{content:'';display:block;width:16px;height:16px;border-radius:50%;corner-shape:round;background:var(--dsw-alias-label-primary-foreground);transition:transform .12s ease}\n.cc-toggle:checked::after{transform:translateX(16px)}\n.cc-toggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\n.cc-toggle:disabled{cursor:default;opacity:.5}\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:7px;height:7px;margin-right:6px;margin-bottom:3px;transform:rotate(45deg);transition:transform .15s ease}\n.cc-chevronUp{transform:rotate(-135deg);margin-bottom:-3px}\n.cc-accountMode{align-items:center;gap:4px;display:flex;margin:-4px 0 12px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}\n.cc-accountList{flex-direction:column;gap:8px;display:flex}\n.cc-accountList+.cc-addButton,.cc-accountList+.cc-addPanel{margin-top:8px}\n.cc-accountItem{flex-direction:column;gap:10px;display:flex;padding:12px 14px;border:.5px solid var(--dsw-alias-border-l4);border-radius:16px}\n.cc-accountItemActive{border-color:var(--dsw-static-neutral-bluish-400,var(--dsw-alias-border-l3))}\n.cc-accountHead{align-items:center;gap:4px;display:flex;min-height:28px}\n.cc-accountToggle{align-items:center;gap:8px;display:flex;flex:1;min-width:0;padding:0;background:0 0;border:0;color:inherit;cursor:pointer;font:inherit;text-align:left}\n.cc-accountToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;border-radius:4px}\n.cc-accountName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}\n.cc-iconButton{flex-shrink:0;align-items:center;justify-content:center;display:inline-flex;width:28px;height:28px;padding:0;background:0 0;border:0;border-radius:6px;color:var(--dsw-alias-label-tertiary);cursor:pointer}\n.cc-iconButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.cc-iconButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n/* Three dots from one element: the dot plus two box-shadow copies. */\n.cc-kebab{width:3px;height:3px;border-radius:50%;corner-shape:round;background:currentColor;box-shadow:0 -5px 0 currentColor,0 5px 0 currentColor}\n.cc-tabDot{flex-shrink:0;width:8px;height:8px;border-radius:50%;corner-shape:round}\n.cc-tabDotOk{background:var(--dsw-alias-state-success-primary)}\n.cc-tabDotBlank{background:0 0;border:0}\n.cc-tabDotWarn{background:var(--dsw-alias-state-warn-primary,#d97706)}\n.cc-tabDotError{background:var(--dsw-alias-state-error-primary)}\n.cc-accountMeters{flex-wrap:wrap;gap:6px 20px;display:flex;padding-left:16px}\n.cc-miniMeter{align-items:center;gap:8px;display:inline-flex;font-size:12px;line-height:18px}\n.cc-miniMeterLabel{color:var(--dsw-alias-label-tertiary)}\n.cc-miniMeterTrack{overflow:hidden;background:var(--dsw-alias-bg-module-platform);border-radius:999px;width:64px;height:4px}\n.cc-miniMeterFill{display:block;background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%}\n.cc-miniMeterValue{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums}\n.cc-accountSetup,.cc-loginStatus{flex-direction:column;gap:8px;display:flex;padding-left:16px}\n.cc-loginStatus{flex-direction:row;flex-wrap:wrap;align-items:center;gap:4px 12px}\n.cc-loginStatus>p{margin:0;font-size:12px;line-height:18px}\n.cc-accountDetails{container-type:inline-size;border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:14px;display:flex;padding-top:12px}\n.cc-inlineForm,.cc-confirmBar{flex-direction:column;gap:8px;display:flex}\n.cc-inlineActions{align-items:center;gap:8px;display:flex}\n.cc-confirmBar{border:.5px solid var(--dsw-alias-state-error-primary);border-radius:12px;padding:12px 14px}\n.cc-confirmText{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:22px}\n.cc-dangerButton{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}\n.cc-dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}\n.cc-addButton{box-sizing:border-box;align-items:center;justify-content:center;gap:6px;display:flex;width:100%;height:44px;border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;background:0 0;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;cursor:pointer}\n.cc-addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.cc-addButton:disabled{cursor:default;opacity:.4}\n.cc-addButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-addGlyph{position:relative;width:12px;height:12px}\n.cc-addGlyph::before,.cc-addGlyph::after{content:'';position:absolute;background:currentColor;border-radius:1px}\n.cc-addGlyph::before{left:0;right:0;top:5.25px;height:1.5px}\n.cc-addGlyph::after{top:0;bottom:0;left:5.25px;width:1.5px}\n.cc-addPanel{flex-direction:column;gap:12px;display:flex;padding:14px 16px;border-radius:12px;background:var(--dsw-alias-bg-module-platform)}\n.cc-panelTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}\n.cc-accountReport{flex-direction:column;gap:14px;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:14px;font-weight:500;line-height:22px}\n.cc-usageAccount{max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-usagePlan{flex:none;white-space:nowrap;border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:999px;corner-shape:round;padding:0 7px;font-size:12px;font-weight:500;line-height:17px}\n.cc-usagePlanStatus{flex:none;margin:0;white-space:nowrap;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.cc-usageHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n/* Two fixed grids, not one auto-fit track: auto-fit wrapped the four activity\n * tiles 3 + 1 at the details' width. The activity row folds to 2 × 2 in a\n * narrow details panel. */\n.cc-usageStats{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;display:grid}\n.cc-usageStatsActivity{grid-template-columns:repeat(4,minmax(0,1fr))}\n.cc-usageStatsBalance{grid-template-columns:repeat(3,minmax(0,1fr))}\n@container (max-width:460px){.cc-usageStatsActivity{grid-template-columns:repeat(2,minmax(0,1fr))}}\n.cc-usageStat{min-width:0;flex-direction:column;gap:2px;display:flex;padding:10px 12px;border-radius:12px;background:var(--dsw-alias-bg-module-platform)}\n.cc-usageStatLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-usageStatValue{color:var(--dsw-alias-label-primary);font-size:16px;font-weight:500;line-height:24px;font-variant-numeric:tabular-nums}\n.cc-usageStatSub{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.cc-usageWindows{flex-direction:column;gap:14px;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;line-height:18px}\n.cc-usageWindowValue{color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px;font-variant-numeric:tabular-nums}\n.cc-usageExceeded{color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.cc-usageBar{overflow:hidden;background:var(--dsw-alias-bg-module-platform);border-radius:999px;height:4px}\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-state-error-primary)}\n.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n.cc-usageMeta{align-items:center;gap:8px;display:flex}\n.cc-usageMetaSpacer{flex:1}\n.cc-usageUpdated{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}\n.cc-usagePartial{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}\n.cc-usageBlocked{border:.5px solid var(--dsw-alias-state-error-primary);border-radius:12px;padding:12px 14px;display:flex;flex-direction:column;gap:4px}\n.cc-usageBlockedTitle{color:var(--dsw-alias-state-error-primary);margin:0;font-size:14px;font-weight:500;line-height:22px}\n.cc-usageBlockedHint{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}\n.cc-usageBlockedDetail{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px;word-break:break-word}\n.cc-version{margin:32px 0 0;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}\n.cc-versionLink{color:var(--dsw-alias-state-warn-label,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.cc-providerCard{flex-direction:column;display:flex}\n.cc-footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}\n.cc-failed{display:inline-block;max-width:260px;min-width:0;color:var(--dsw-alias-state-error-primary);margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px}\n.cc-loginLink{color:var(--dsw-alias-link,var(--dsw-alias-brand-primary));text-decoration:none;font-size:12px;line-height:18px}\n.cc-loginLink:hover{text-decoration:underline;text-underline-position:under}\n.cc-loginDone{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary))}\n.cc-loginError{color:var(--dsw-alias-state-error-primary)}\n/* The floating save bar: a centered capsule pinned to the bottom of the\n * settings scrollport. The dock is a zero-height sticky strip at the end of the\n * page, so the bar overlays the scrolling content instead of taking a row of\n * its own; while shown, the section reserves room at its end so the last line\n * can scroll clear. Hidden, it sinks and fades, and visibility (switched after\n * the transition) takes its buttons out of the tab order. Its surface is an\n * elevated layer (bg-layer-1 over the settings panel's layer-2) with the\n * platform's prominent elevation and no stroke, and its corners are concentric\n * (a 44px capsule around 36px buttons inset by 4px) so the gap around each\n * button is even. */\n.cc-sectionWithBar{padding-bottom:80px}\n.cc-saveBarDock{position:sticky;bottom:0;z-index:2;height:0;pointer-events:none}\n.cc-saveBar{--cc-saveBar-tone:var(--dsw-alias-state-warn-primary,#d97706);position:absolute;left:50%;bottom:20px;box-sizing:border-box;width:max-content;max-width:calc(100% - 24px);align-items:center;gap:10px;display:flex;height:44px;padding:4px 4px 4px 16px;border:0;border-radius:22px;corner-shape:round;background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-prominent,0 12px 32px -8px rgba(0,0,0,.24),0 2px 8px rgba(0,0,0,.08));opacity:0;visibility:hidden;transform:translate(-50%,12px);transition:opacity .16s ease,transform .16s ease,visibility 0s linear .16s}\n.cc-saveBarShown{opacity:1;visibility:visible;transform:translate(-50%,0);pointer-events:auto;transition:opacity .2s ease,transform .24s cubic-bezier(.2,.9,.3,1.1),visibility 0s}\n.cc-saveBar-error{--cc-saveBar-tone:var(--dsw-alias-state-error-primary)}\n.cc-saveBar-success{--cc-saveBar-tone:var(--dsw-alias-state-success-primary,#16a34a);padding-right:18px}\n.cc-saveBarIcon{flex-shrink:0;align-items:center;justify-content:center;display:inline-flex;width:16px;height:16px;color:var(--cc-saveBar-tone)}\n.cc-saveBarPulse{width:8px;height:8px;border-radius:50%;corner-shape:round;background:var(--cc-saveBar-tone)}\n.cc-saveBarText{min-width:0;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}\n.cc-saveBar-error .cc-saveBarText{color:var(--dsw-alias-state-error-primary)}\n.cc-saveBarActions{flex-shrink:0;align-items:center;gap:4px;display:flex;margin-left:8px}\n.cc-saveBarButton{box-sizing:border-box;height:36px;padding:0 16px;border:0;border-radius:18px;corner-shape:round;font:inherit;font-size:14px;line-height:22px;white-space:nowrap;cursor:pointer}\n.cc-saveBarButton:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}\n.cc-saveBarButton:disabled{cursor:default;opacity:.4}\n.cc-saveBarGhost{background:0 0;color:var(--dsw-alias-label-primary)}\n.cc-saveBarGhost:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.cc-saveBarPrimary{background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-brand-primary));color:var(--dsw-alias-label-primary-foreground,#fff)}\n.cc-saveBarPrimary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover,var(--dsw-alias-button-primary-fill,var(--dsw-alias-brand-primary)))}\n@media (prefers-reduced-motion:reduce){.cc-chevron,.cc-toggle::after,.cc-usageBarFill,.cc-saveBar,.cc-saveBarShown{transition:none}}\n`\n","/**\n * Stylesheet for the Command Code plans & quota panel (the sidebar footer card\n * and the dashboard it opens).\n *\n * Returned as a string, not injected here, so importing this module has no DOM\n * side effect: `./index.ts` installs it once under {@link PANEL_CSS_ID} and\n * removes it when the fiber unwinds.\n *\n * These rules are GLOBAL CSS, so containment is a contract (issue #48): every\n * selector is qualified by one of our own `ccp-` classes except the sidebar\n * anchor below, which carries its justification in place. `tests/styles.test.ts`\n * audits both stylesheets against the real foreign class stems. Colours are\n * harness theme aliases with neutral fallbacks; the `ccp-` prefix keeps these\n * clear of the settings page's `cc-` set.\n *\n * @module dsh-commandcode-provider/client/panel-styles\n */\n\n/**\n * Stylesheet id — the `data-plugin-css` value that makes injection idempotent.\n *\n * The prefix must match this package's real name and the settings-page sheet's\n * (`PAGE_CSS_ID`); the two ids must also stay DISTINCT, since they key two\n * separate style tags and a shared id would make the second injection a no-op.\n */\nexport const PANEL_CSS_ID = '@mars-sea/dsh-commandcode-provider/CommandCodePanel.module.css'\n\n/** The panel stylesheet. */\nexport const PANEL_CSS = `\n/* ------------------------------------------------- sidebar footer card */\n/* The shell renders this list ABOVE the Settings seat, so the card is the\n sidebar's bottom-most content, and supplies no chrome: the entry IS the\n button. Deliberately quiet — a surface beside Settings should read as part of\n the column — with one hover step and a hairline border.\n\n The shell's container is a flex ROW whose occupants each declare a full-width\n line and shrink-proof flex, so as a row it would overflow the column: this\n card cannot shrink and the neighbouring chip would absorb the overflow and\n collapse to nothing. The first rule is that fix, and THE ANCHOR IS\n LOAD-BEARING (issue #48): \"footerActions\" is not a stem this shell owns alone\n — dsh-client-ui-user-questions renders the ask-user-question dialog's button\n row as Mbwy4a_footerActions, and the unanchored rule stacked THAT row's\n side-by-side buttons on every page. \"footArea\" is declared by\n dsh-client-ui-sidebar alone (audited across every client bundle of the\n 0.1.6-alpha.1 engine, and against our own cc-/ccp- names, which collide with\n no engine class). The DESCENDANT combinator survives a wrapper element\n appearing between the two, so a restructured shell degrades to its own row\n rather than losing the fix. tests/styles.test.ts pins both halves. */\n[class*=\"_footArea\"] [class*=\"_footerActions\"]{flex-direction:column}\n.ccp-foot{box-sizing:border-box;flex:0 0 auto;width:100%;min-width:0;font:inherit;color:var(--dsw-alias-label-secondary);text-align:left;cursor:pointer;background:0 0;border:1px solid transparent;border-radius:10px;flex-direction:column;gap:6px;margin:0 0 4px;padding:8px;display:flex}\n.ccp-foot:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}\n.ccp-foot:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}\n.ccp-footTop{align-items:center;gap:8px;min-width:0;display:flex}\n.ccp-footName{white-space:nowrap;text-overflow:ellipsis;color:var(--dsw-alias-label-primary);min-width:0;overflow:hidden;font-size:13px;font-weight:500;line-height:20px}\n/* One block per quota window: a head line carrying the window's own spend and\n limit, then the FULL-WIDTH bar under it. Stacking the two lets the card show\n the dollar figures — the reason this surface exists — without squeezing the\n bar into what is left beside them. Mirrors the dashboard's window block. */\n.ccp-footRow{flex-direction:column;gap:4px;min-width:0;display:flex}\n.ccp-footHead{align-items:baseline;gap:8px;min-width:0;display:flex}\n.ccp-footLabel{flex:1;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}\n.ccp-footAmount{flex:none;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:16px;font-variant-numeric:tabular-nums;white-space:nowrap}\n/* The card's markup must stay PHRASING content — it renders inside the shell's\n own button — so these bars are spans, which makes display:block load-bearing:\n an inline box ignores width outright, so the fill would collapse to 0x0 and\n the bar would show no usage. */\n.ccp-footBar{display:block;background:var(--dsw-alias-bg-layer-2);border-radius:999px;height:5px;overflow:hidden}\n.ccp-footFill{display:block;background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}\n.ccp-footFillWarn{background:var(--dsw-alias-state-error-primary)}\n.ccp-footPct{flex:none;width:34px;color:var(--dsw-alias-label-secondary);text-align:right;font-size:12px;line-height:16px;font-variant-numeric:tabular-nums}\n\n/* The 56px rail: one icon button on the shell's own 36px rail cell, so the\n collapsed column keeps a single 18px glyph like its siblings. */\n.ccp-railButton{box-sizing:border-box;width:36px;height:36px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:1px solid transparent;border-radius:8px;flex:none;justify-content:center;align-items:center;margin:0 0 4px;padding:0;display:inline-flex}\n.ccp-railButton:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}\n.ccp-railButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}\n\n/* The ring glyph, sized entirely by its own width/height attribute, so the\n footer row, the rail button and the dashboard can each ask for their own. */\n.ccp-glyph{flex:none;justify-content:center;align-items:center;display:inline-flex;color:var(--dsw-alias-brand-primary)}\n\n/* ------------------------------------------------------------ dashboard */\n.ccp-main{background:var(--dsw-alias-bg-layer-1);width:100%;height:100%;overflow:auto;display:block}\n.ccp-mainInner{max-width:760px;margin:0 auto;padding:24px 20px 40px;flex-direction:column;gap:14px;display:flex;color:var(--dsw-alias-label-primary)}\n.ccp-header{align-items:center;gap:10px;display:flex;flex-wrap:wrap}\n.ccp-headerText{flex-direction:column;gap:2px;display:flex;min-width:0}\n.ccp-title{margin:0;font-size:18px;font-weight:600;line-height:1.4}\n.ccp-subtitle{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n.ccp-spacer{flex:1}\n.ccp-meta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;font-variant-numeric:tabular-nums}\n/* 关闭图标沿用原语义与按钮尺寸,线性 SVG 随宿主文字颜色变化。 */\n.ccp-close{min-width:28px;justify-content:center;padding-left:0;padding-right:0}\n.ccp-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n\n.ccp-notice{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:12px 14px;flex-direction:column;gap:4px;display:flex}\n.ccp-noticeError{border-color:var(--dsw-alias-state-error-primary)}\n.ccp-noticeTitle{margin:0;font-size:13px;font-weight:600;line-height:1.5}\n.ccp-noticeError .ccp-noticeTitle{color:var(--dsw-alias-state-error-primary)}\n.ccp-noticeHint{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}\n.ccp-noticeDetail{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;word-break:break-word}\n\n.ccp-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:14px;padding:16px 18px;flex-direction:column;gap:16px;display:flex}\n.ccp-cardHead{align-items:center;gap:10px;display:flex;flex-wrap:wrap}\n.ccp-avatar{flex:none;width:28px;height:28px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-module-platform);border-radius:50%;justify-content:center;align-items:center;font-size:12px;font-weight:600;line-height:1;display:inline-flex}\n.ccp-cardIdentity{flex-direction:column;gap:1px;min-width:0;display:flex}\n.ccp-cardTitle{font-size:13px;font-weight:600;line-height:1.4}\n.ccp-cardOwner{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:220px}\n.ccp-block{flex-direction:column;gap:8px;display:flex}\n.ccp-blockTitle{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:600;line-height:1.5;text-transform:uppercase;letter-spacing:.04em}\n.ccp-planRow{align-items:center;gap:8px;display:flex;flex-wrap:wrap}\n.ccp-fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n.ccp-planName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:1.5}\n\n/* The monthly credits and the usage totals share one grid. */\n.ccp-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}\n.ccp-tile{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;min-width:0}\n.ccp-tileLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}\n.ccp-tileValue{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4;font-variant-numeric:tabular-nums}\n.ccp-tileSub{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n\n/* Quota bars: the monthly bar and the two windows. */\n.ccp-windows{flex-direction:column;gap:14px;display:flex}\n.ccp-window{flex-direction:column;gap:6px;display:flex}\n.ccp-windowHead{align-items:baseline;gap:8px;display:flex}\n.ccp-windowLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:1.5}\n.ccp-windowValue{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;font-variant-numeric:tabular-nums;white-space:nowrap}\n.ccp-windowPct{color:var(--dsw-alias-label-primary);min-width:38px;text-align:right;font-size:12px;font-weight:600;line-height:1.5;font-variant-numeric:tabular-nums}\n.ccp-warnTag{white-space:nowrap;background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary));border-radius:999px;padding:0 8px;font-size:12px;font-weight:600;line-height:17px}\n.ccp-bar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:8px}\n.ccp-barFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}\n.ccp-barFillWarn{background:var(--dsw-alias-state-error-primary)}\n.ccp-windowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n\n.ccp-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:12px;font-weight:600;line-height:17px}\n.ccp-badgeError{background:transparent;color:var(--dsw-alias-state-error-primary)}\n.ccp-badgeWarn{background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary))}\n.ccp-badgeMuted{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:12px;font-weight:500;line-height:17px;max-width:220px;overflow:hidden;text-overflow:ellipsis}\n\n/* Account switch: plain buttons, like the settings page's usage carousel. */\n.ccp-tabs{flex-wrap:wrap;gap:6px;display:flex}\n.ccp-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.ccp-tab:hover:not(.ccp-tabActive){color:var(--dsw-alias-label-primary)}\n.ccp-tabActive{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}\n\n@media (prefers-reduced-motion:reduce){.ccp-footFill,.ccp-barFill{transition:none}}\n/* 分析页继承设置页和宿主控件的语义变量;独立选择器不影响账号额度页面。 */\n.ccp-mainInnerAnalysis{max-width:1040px;box-sizing:border-box}\n/* 宿主侧栏会缩窄中心面板,按实际可用宽度切换列数,而不是仅看浏览器宽度。 */\n.ccp-analysis{font-size:14px;line-height:22px;min-width:0;color:var(--dsw-alias-label-primary);container-type:inline-size;container-name:ccp-analysis}\n.ccp-analysisFilters{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;margin:8px 0 20px}\n.ccp-analysisField{display:flex;flex-direction:column;gap:6px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);min-width:0}\n.ccp-analysisFilters .ccp-analysisField{flex:0 1 158px}\n.ccp-analysisFilters .ccp-analysisScopeField{flex-basis:184px}\n.ccp-analysisFilters .ccp-analysisDateField{flex-basis:166px}\n/* 对齐原生选择器、日期输入与按钮的边框盒;保留独立箭头留白和点击区域。 */\n.ccp-analysisInput{box-sizing:border-box;width:100%;min-width:0;height:36px;padding:0 11px;font:inherit;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:.5px solid var(--dsw-alias-border-l4);border-radius:8px}\n.ccp-analysisSelectShell{position:relative;display:block;width:100%;min-width:0}\n.ccp-analysisSelect{appearance:none;-webkit-appearance:none;padding-inline-end:40px;text-overflow:ellipsis;cursor:pointer;border:0;border-radius:18px;background:var(--dsw-alias-bg-module-platform)}\n.ccp-analysisSelectShell > .ccp-analysisChevron{position:absolute;inset-inline-end:12px;top:50%;transform:translateY(-50%) rotate(90deg);pointer-events:none}\n.ccp-analysisSelect:disabled + .ccp-analysisChevron{opacity:.6}\n.ccp-analysisInput::placeholder{color:var(--dsw-alias-label-tertiary)}\n.ccp-analysisApply{box-sizing:border-box;flex:none;height:36px;font:inherit;font-size:14px;line-height:22px;white-space:nowrap;padding:0 20px;border:0;border-radius:var(--dsw-radius-md,18px);background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);cursor:pointer;margin-left:2px}\n.ccp-analysisApply:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}\n.ccp-analysisApply:disabled{opacity:.4;cursor:wait}\n.ccp-analysisInput:disabled{opacity:.6}\n.ccp-analysisInput:focus-visible,.ccp-analysisApply:focus-visible,.ccp-analysisTab:focus-visible,.ccp-analysisPanel:focus-visible,.ccp-analysisModelSummary:focus-visible,.ccp-analysisScenarioSummary:focus-visible,.ccp-analysisDisclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}\n/* 模型列表会裁切圆角,内收焦点框以保持第一行和最后一行也清晰可见。 */\n.ccp-analysisModelSummary:focus-visible,.ccp-analysisScenarioSummary:focus-visible{outline-offset:-3px;border-radius:6px}\n.ccp-analysisScope{display:flex;justify-content:space-between;gap:8px 18px;flex-wrap:wrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin-bottom:12px}\n.ccp-analysisScope > span:first-child{color:var(--dsw-alias-label-primary);font-weight:500}\n.ccp-analysisOverview{display:grid;grid-template-columns:1.45fr repeat(3,1fr);gap:20px;padding:16px 18px;background:var(--dsw-alias-bg-layer-3);border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;font-variant-numeric:tabular-nums}\n.ccp-analysisMetric{display:flex;flex-direction:column;gap:3px;min-width:0}\n.ccp-analysisLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);font-weight:400}\n.ccp-analysisValue{font-size:14px;line-height:22px;font-weight:500;overflow-wrap:anywhere}\n.ccp-analysisSub{display:block;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;font-weight:400;overflow-wrap:anywhere}\n.ccp-analysisOverview .ccp-analysisMetric{gap:5px}\n.ccp-analysisOverview .ccp-analysisValue{font-size:20px;line-height:28px;font-weight:500}\n.ccp-analysisNote{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);margin:9px 0 0}\n.ccp-analysisMessage{margin:12px 0 0;padding:12px 14px;border:.5px solid var(--dsw-alias-border-l4);border-radius:12px;background:var(--dsw-alias-bg-layer-3);font-size:14px;line-height:22px}\n.ccp-analysisWarning{display:flex;align-items:flex-start;gap:8px}\n.ccp-analysisIcon{flex:none}\n.ccp-analysisWarning > .ccp-analysisIcon{color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-secondary));margin-top:3px}\n.ccp-analysisWarning p{margin:0}\n.ccp-analysisWarning p + p{margin-top:5px}\n.ccp-analysisError{color:var(--dsw-alias-state-error-primary)}\n/* 沿用宿主分段控件的轨道、浮层与胶囊尺寸,保留原有页签键盘语义。 */\n.ccp-analysisTabs{box-sizing:border-box;display:inline-grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:2px;padding:4px;border:0;border-radius:var(--dsw-radius-md,18px);background:var(--dsw-alias-interactive-bg-hover);margin:22px 0 0;max-width:100%}\n.ccp-analysisTab{height:28px;padding:0 16px;border:0;border-radius:var(--dsw-radius-sm,14px);background:transparent;font:inherit;font-size:13px;line-height:20px;font-weight:500;color:var(--dsw-alias-label-secondary);white-space:nowrap;cursor:pointer}\n.ccp-analysisTab:hover,.ccp-analysisTab[aria-selected=\"true\"]{color:var(--dsw-alias-label-primary)}\n.ccp-analysisTab[aria-selected=\"true\"]{background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft)}\n.ccp-analysisTabCount{display:inline-flex;justify-content:center;min-width:16px;padding:0 4px;margin-left:6px;border-radius:999px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}\n.ccp-analysisPanel{padding-top:20px;min-width:0}\n.ccp-analysisPanel[hidden]{display:none}\n.ccp-analysisSectionHead{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:12px}\n.ccp-analysisHeading{font-size:14px;line-height:22px;font-weight:500;margin:0}\n.ccp-analysisSectionHead .ccp-analysisNote{margin:0;max-width:56ch}\n.ccp-analysisModels{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;overflow:hidden}\n.ccp-analysisModelRow + .ccp-analysisModelRow{border-top:.5px solid var(--dsw-alias-border-l2)}\n.ccp-analysisTableHead,.ccp-analysisModelSummary,.ccp-analysisScenarioSummary{position:relative;display:grid;grid-template-columns:minmax(190px,2.1fr) minmax(150px,1.45fr) minmax(90px,.9fr) minmax(90px,.9fr) minmax(100px,1fr) 16px;gap:18px;align-items:center;padding:16px 18px;font-variant-numeric:tabular-nums}\n.ccp-analysisTableHead{padding-top:11px;padding-bottom:11px;background:var(--dsw-alias-interactive-bg-hover);border-bottom:.5px solid var(--dsw-alias-border-l2);font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}\n.ccp-analysisTableHead > span:not(:first-child){text-align:right}\n.ccp-analysisScenarioHead,.ccp-analysisScenarioSummary{grid-template-columns:minmax(190px,2fr) minmax(118px,1.1fr) minmax(155px,1.35fr) minmax(142px,1.15fr) 16px}\n.ccp-analysisScenarioHead > span:nth-child(3),.ccp-analysisScenarioHead > span:nth-child(4){text-align:left}\n.ccp-analysisModelSummary,.ccp-analysisScenarioSummary{cursor:pointer;list-style:none;min-height:60px}\n.ccp-analysisModelSummary::-webkit-details-marker,.ccp-analysisScenarioSummary::-webkit-details-marker,.ccp-analysisDisclosure::-webkit-details-marker{display:none}\n.ccp-analysisModelSummary:hover,.ccp-analysisScenarioSummary:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.ccp-analysisIdentity{display:flex;flex-direction:column;gap:2px;min-width:0}\n.ccp-analysisModelName{font-size:14px;line-height:22px;font-weight:500;overflow-wrap:anywhere}\n.ccp-analysisModelCount{margin-top:3px}\n.ccp-analysisModelSummary > .ccp-analysisMetric,.ccp-analysisScenarioSummary > .ccp-analysisMetric{align-items:flex-end}\n.ccp-analysisScenarioSummary > .ccp-analysisMetric:nth-child(3),.ccp-analysisScenarioSummary > .ccp-analysisMetric:nth-child(4){align-items:flex-start}\n/* 宽表使用集中表头,但保留每个指标的无障碍标签;窄面板恢复可见标签。 */\n.ccp-analysisModelSummary .ccp-analysisMetricLabel,.ccp-analysisScenarioSummary .ccp-analysisMetricLabel,.ccp-analysisSearchLabel{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n.ccp-analysisShare{display:flex;align-items:center;gap:8px;width:100%;max-width:148px;margin-top:3px}\n.ccp-analysisShareTrack{display:block;flex:1;height:4px;overflow:hidden;background:var(--dsw-alias-bg-module-platform);border-radius:999px}\n.ccp-analysisShareFill{display:block;height:100%;background:var(--dsw-alias-label-secondary);border-radius:999px}\n.ccp-analysisShareValue{font-size:12px;line-height:18px;min-width:40px;text-align:right;color:var(--dsw-alias-label-tertiary)}\n.ccp-analysisChevron{flex:none;color:var(--dsw-alias-label-tertiary)}\n.ccp-analysisModelRow[open] > .ccp-analysisModelSummary > .ccp-analysisChevron,.ccp-analysisModelRow[open] > .ccp-analysisScenarioSummary > .ccp-analysisChevron,.ccp-analysisAggregate[open] > .ccp-analysisDisclosure > .ccp-analysisChevron,.ccp-analysisRules[open] > .ccp-analysisDisclosure > .ccp-analysisChevron{transform:rotate(90deg)}\n.ccp-analysisDetails{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:22px;padding:16px 18px;background:var(--dsw-alias-bg-module-platform);border-top:.5px solid var(--dsw-alias-border-l2)}\n.ccp-analysisDetailTitle{font-size:12px;line-height:18px;font-weight:600;margin:0 0 11px}\n.ccp-analysisFacts{margin:0;display:flex;flex-direction:column;gap:8px}\n.ccp-analysisFact{display:flex;align-items:baseline;justify-content:space-between;gap:10px;min-width:0}\n.ccp-analysisFactValue{font-size:14px;line-height:22px;margin:0;text-align:right;font-variant-numeric:tabular-nums;overflow-wrap:anywhere;min-width:0}\n.ccp-analysisFact .ccp-analysisLabel{flex-shrink:0}\n.ccp-analysisFooter{display:flex;justify-content:space-between;gap:12px;align-items:flex-start;flex-wrap:wrap;margin-top:14px}\n.ccp-analysisAggregate{flex:1;min-width:210px}\n.ccp-analysisAggregate > .ccp-analysisDetails{border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;margin-top:6px}\n.ccp-analysisDisclosure{display:flex;gap:7px;align-items:center;cursor:pointer;list-style:none;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);padding:7px 0}\n.ccp-analysisDisclosure > .ccp-analysisChevron{width:14px;height:14px}\n.ccp-analysisMonthly{flex:none;max-width:340px;display:flex;justify-content:flex-end;flex-wrap:wrap;gap:2px 8px;align-items:baseline;text-align:right;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);padding-top:5px}\n.ccp-analysisMonthlyValue{font-size:14px;line-height:22px;font-weight:500;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums}\n.ccp-analysisMonthly .ccp-analysisNote{width:100%;margin:0}\n.ccp-analysisAssumption{font-size:14px;line-height:22px;color:var(--dsw-alias-label-tertiary);margin:0 0 18px;max-width:76ch}\n.ccp-analysisSearch{flex:0 1 270px}\n.ccp-analysisSearchShell{position:relative;display:block}\n.ccp-analysisSearchShell > .ccp-analysisIcon{position:absolute;top:10px;left:11px;color:var(--dsw-alias-label-tertiary);pointer-events:none}\n.ccp-analysisSearch .ccp-analysisInput{padding-left:35px}\n.ccp-analysisScenarioDetails{grid-template-columns:minmax(0,1fr) minmax(0,2fr)}\n.ccp-analysisScenarioDetails .ccp-analysisFactValue{max-width:70%}\n.ccp-analysisEmpty{font-size:14px;line-height:22px;color:var(--dsw-alias-label-tertiary);text-align:center;padding:34px 18px;margin:0;border:1px dashed var(--dsw-alias-border-l4);border-radius:8px}\n.ccp-analysisRules{margin-top:22px;border-top:.5px solid var(--dsw-alias-border-l2);padding-top:8px}\n.ccp-analysisRulesBody{display:grid;grid-template-columns:1fr 1fr;gap:24px;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px;margin-top:9px}\n.ccp-analysisRulesBody p{margin:0 0 10px}\n@container ccp-analysis (max-width:920px){\n.ccp-analysisTableHead{display:none}\n.ccp-analysisModelSummary{grid-template-columns:repeat(4,minmax(0,1fr)) 16px;gap:12px 18px}\n.ccp-analysisScenarioSummary{grid-template-columns:repeat(3,minmax(0,1fr)) 16px;gap:12px 18px}\n.ccp-analysisModelSummary > .ccp-analysisIdentity,.ccp-analysisScenarioSummary > .ccp-analysisIdentity{grid-column:1/-2}\n.ccp-analysisModelSummary > .ccp-analysisChevron{grid-column:5;grid-row:1;justify-self:end}\n.ccp-analysisScenarioSummary > .ccp-analysisChevron{grid-column:4;grid-row:1;justify-self:end}\n.ccp-analysisModelSummary > .ccp-analysisMetric,.ccp-analysisScenarioSummary > .ccp-analysisMetric{align-items:flex-start}\n.ccp-analysisModelSummary .ccp-analysisMetricLabel,.ccp-analysisScenarioSummary .ccp-analysisMetricLabel{position:static;width:auto;height:auto;padding:0;margin:0;overflow:visible;clip:auto;white-space:normal}\n.ccp-analysisDetails{grid-template-columns:repeat(2,minmax(0,1fr))}\n}\n@container ccp-analysis (max-width:588px){\n.ccp-analysisFilters{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}\n.ccp-analysisFilters[data-mode=\"range\"] .ccp-analysisScopeField{grid-column:1/-1}\n.ccp-analysisApply{grid-column:1/-1;margin:0;width:100%}\n.ccp-analysisOverview{grid-template-columns:repeat(2,minmax(0,1fr));gap:20px 18px;padding:16px}\n.ccp-analysisModelSummary,.ccp-analysisScenarioSummary{grid-template-columns:repeat(2,minmax(0,1fr));gap:15px 18px;padding:16px}\n.ccp-analysisModelSummary > .ccp-analysisIdentity,.ccp-analysisScenarioSummary > .ccp-analysisIdentity{grid-column:1/-1;padding-right:24px}\n.ccp-analysisModelSummary > .ccp-analysisChevron,.ccp-analysisScenarioSummary > .ccp-analysisChevron{position:absolute;top:18px;right:16px;grid-column:auto;grid-row:auto}\n.ccp-analysisDetails,.ccp-analysisScenarioDetails{gap:20px;grid-template-columns:1fr;padding:16px}\n.ccp-analysisAggregate{width:100%;min-width:0}\n.ccp-analysisMonthly{width:100%;max-width:none;justify-content:flex-start;text-align:left;padding-top:0}\n.ccp-analysisSectionHead{align-items:flex-start}\n.ccp-analysisSectionHead .ccp-analysisSearch{flex-basis:100%;width:100%;order:2}\n.ccp-analysisRulesBody{grid-template-columns:1fr;gap:12px}\n/* 英文页签带数量时允许换行,避免轨道或文字撑出宿主的窄面板。 */\n.ccp-analysisTabs{margin-top:18px;grid-auto-columns:minmax(0,1fr)}\n.ccp-analysisTab{height:auto;min-height:28px;padding:4px 8px;white-space:normal}\n}\n@media (max-width:640px){.ccp-mainInnerAnalysis{padding:20px 16px 32px}}\n`\n","/** 手动读取历史,旧宿主可降级;查询切换和卸载后不接受过期结果。 */\nimport { parseAnalyticsQuery, parseAnalyticsReport, type AnalyticsQuery, type AnalyticsReport } from '../analytics-wire.ts'\nimport type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'\nexport interface AnalyticsRemote { analytics?(query: AnalyticsQuery): Promise<RemoteResult<AnalyticsReport>> }\nexport interface AnalyticsState { status: 'idle' | 'loading' | 'ready' | 'error'; report?: AnalyticsReport; error?: string }\nexport class AnalyticsController {\n private current: AnalyticsState = { status: 'idle' }\n private listeners = new Set<() => void>()\n private generation = 0\n private disposed = false\n private query: AnalyticsQuery = { mode: 'recent', limit: 20 }\n constructor(private remote: AnalyticsRemote) {}\n state() { return this.current }\n subscribe(listener: () => void) { this.listeners.add(listener); return () => { this.listeners.delete(listener) } }\n dispose() { this.disposed = true; this.generation++; this.listeners.clear() }\n reload() { this.generation++; this.set({ status: 'idle' }) }\n refresh(query = this.query) {\n if (this.disposed) return\n const requested = parseAnalyticsQuery(query)\n this.query = requested\n const generation = ++this.generation\n this.set({ status: 'loading' })\n const call = this.remote.analytics\n if (!call) { this.set({ status: 'error', error: '宿主不支持模型分析,请更新插件' }); return }\n void Promise.resolve().then(() => call(requested)).then(result => {\n if (this.disposed || generation !== this.generation) return\n if (!result.ok) { this.set({ status: 'error', error: result.error.message === '宿主不支持模型分析,请更新插件' ? result.error.message : '模型分析读取失败,请稍后刷新或检查宿主日志' }); return }\n this.set({ status: 'ready', report: parseAnalyticsReport(result.value) })\n }).catch(() => {\n if (!this.disposed && generation === this.generation) this.set({ status: 'error', error: '模型分析读取失败,请稍后刷新或检查宿主日志' })\n })\n }\n private set(state: AnalyticsState) { this.current = state; for (const listener of this.listeners) listener() }\n}\n","/**\n * Browser half of the dsh-commandcode-provider bundle: the \"Command Code\"\n * settings page (`settings.section`, id `commandcode`), the Models-page\n * provider card (`settings.models.provider-card`, key `llm-commandcode`, see\n * `./card.tsx`), the quota/model-analysis panel's `main` cell + gated\n * `sidebar.footer.action` card, and the composer\n * `conversation.composer.dock` cost entry.\n *\n * The API key is written through the credentials domain (the\n * `COMMANDCODE_API_KEY` reference the plugin resolves via\n * `ctx.remote.credentials`), never as a settings value, and every other fact\n * through the `llm-commandcode` namespace — so a saved key or endpoint reaches\n * the very next request and the key literal cannot land in a settings document.\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { createSnapshotStore } from './snapshot-store.ts'\nimport { readableErrorText } from './error-text.ts'\n// Type-only: the client-service augmentations (`slots`/`remote`/`locale` on\n// Context) and the `settings.section` SlotMap entry.\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 { createSettingsScope, type SettingsRemoteNamespace, type SettingsScopeContext } from './settings-scope.ts'\nimport { CommandCodeSettingsController, COMMANDCODE_NS, type SettingsPageState } from './settings.ts'\nimport type { SettingsPageApi } from './settings.ts'\nimport { CommandCodeUsageController, type UsagePageState, type UsageRemote } from './usage.ts'\nimport { CommandCodePricesController, type SessionCostPricesState } from './prices.ts'\nimport { CommandCodeLoginController, type LoginPageState, type LoginRemote } from './login.ts'\nimport { USAGE_REMOTE_CONTRIBUTION, MODELS_REMOTE_CONTRIBUTION, PRICES_REMOTE_CONTRIBUTION } from '../usage-wire.ts'\nimport { LOGIN_REMOTE_CONTRIBUTION } from '../login-wire.ts'\nimport { ENROLLMENT_REMOTE_CONTRIBUTION } from '../enrollment-wire.ts'\nimport { AccountEnrollmentController, type EnrollmentRemote } from './enrollment.ts'\nimport type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { CommandCodeSettingsPage } from './section.tsx'\nimport { CommandCodeProviderCard } from './card.tsx'\nimport { CommandCodePanel, CommandCodeFooterEntry } from './panel-view.tsx'\nimport type { PanelInjected } from './panel-view.tsx'\nimport { CommandCodeSessionCost } from './session-cost-view.tsx'\nimport type { SessionCostInjected } from './session-cost-view.tsx'\nimport { startPanelAutoRefresh } from './panel.ts'\nimport { PAGE_CSS, PAGE_CSS_ID } from './page-styles.ts'\nimport { PANEL_CSS, PANEL_CSS_ID } from './panel-styles.ts'\n// Type-only: pulls in the SlotMap merge for the composer dock\n// (`./session-cost-slots.ts`). The sidebar-foot / center-column merge rides the\n// `./panel-view.tsx` value import above, which imports `./panel-slots.ts`.\nimport type {} from './session-cost-slots.ts'\nimport { zh, en } from './locales.ts'\nimport { PANEL_COPY_EN, PANEL_COPY_ZH, PANEL_LOCALE_NS } from './panel-copy.ts'\nimport { ANALYTICS_REMOTE_CONTRIBUTION } from '../analytics-wire.ts'\nimport { AnalyticsController } from './analytics.ts'\nimport type { AnalyticsQuery } from '../analytics-wire.ts'\n\n\n\n/** Install one stylesheet by id and return a disposer for its owning effect. */\nfunction injectCss(id: string, css: string): () => void {\n if (typeof document === 'undefined') return () => {}\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 = css\n document.head.appendChild(tag)\n return () => tag.remove()\n}\n\n/**\n * Plans & quota panel id. It is the layout's `MainPanelId`: one string shared\n * by the `sidebar.footer.action` card and the `main` slot cell, so the card\n * selects this panel and nothing else. `dsh-client-ui-layout` is not a\n * dependency of this bundle, so its brand is applied at the call site instead\n * of importing the package.\n */\nconst PANEL_ID = 'commandcode-panel'\n\n/**\n * The composer figure's entry id in `conversation.composer.dock`. Its own id,\n * never the shipped `stats` cell's: reusing that id would REPLACE the tokens /\n * cache-hit / throughput readout rather than inject into it, and that readout\n * is the harness's to format.\n */\nconst SESSION_COST_ID = 'commandcode-session-cost'\n\n/**\n * The one shot of the `layout` service this plugin needs, declared\n * structurally: importing the package would make the browser resolve a client\n * module this bundle never calls. Read through the reflective\n * `ctx.get('layout')`, never a bare `ctx.layout` property — `layout` is not in\n * the exported inject list, and cordis throws `cannot get property … without\n * inject` for an undeclared service. (The footer card's own gate below IS a\n * static `ctx.inject(['layout'])`, but it is scoped to that one registration.)\n */\ninterface LayoutSelectionSeam {\n /** `null` shows the Conversation again; a string selects that registered `main` key. */\n selectPanel(id: string | null): void\n}\n\n/**\n * Client plugin body. Gates on `slots`, `locale` and `remote` — never on\n * `settingsScope`, whose wrapper service the 0.1.7 settings rewrite removed\n * (the scope below speaks the `remote.settings` wire directly), because\n * gating on a service 0.1.7 does not provide would park EVERY surface below\n * into silence. `settingsScope` must never reappear in the exported inject\n * list at the bottom of this file.\n */\nexport function apply(ctx: Context): void {\n injectCss(PAGE_CSS_ID, PAGE_CSS)\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; `slots.inject` waits for the declaration, so registration\n // order relative to it does not matter).\n ctx.effect(() => ctx.locale.register('settings.commandcode', { zh, en }), 'dsh-commandcode-provider: page copy')\n\n // The panel's copy is a namespace of its own: the panel is not part of the\n // settings page, but it follows the SAME active language — declaring\n // `PANEL_LOCALE_NS` on both panel registrations is what binds their `t` seat.\n ctx.effect(\n () => ctx.locale.register(PANEL_LOCALE_NS, { zh: PANEL_COPY_ZH, en: PANEL_COPY_EN }),\n 'dsh-commandcode-provider: panel copy',\n )\n\n // Credentials reach the browser as a Typert Remote namespace. This inject is\n // the activation gate for every surface below, so a profile whose Host\n // serves no credentials namespace simply never mounts the page.\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. */\nfunction applyClientSurfaces(\n ctx: Context,\n api: SettingsPageApi,\n): void {\n // This plugin's own binding of the `llm-commandcode` namespace over\n // `remote.settings` (see `./settings-scope.ts`).\n //\n // The namespace object is captured from an INJECT-SCOPED context, never read\n // off `ctx.remote`: `remote.settings` is a Cordis service NESTED under\n // `remote`, and cordis answers a read through a context that does not declare\n // it with `Error: cannot get property \"remote.settings\" without inject` —\n // which lands inside the scope's own `try`/`catch`, so nothing is logged and\n // the page renders read-only with every control disabled (the 0.1.7\n // settings-page report, CHANGELOG 0.11.9; the full incident is in\n // AGENTS.md). The resolver hands the scope the very object the inject\n // resolved, and `refresh()` re-reads once it lands; a profile whose Host\n // serves no settings namespace simply never resolves it, where the page\n // keeps rendering its degraded state instead of crashing.\n let settingsNamespace: SettingsRemoteNamespace | undefined\n const scope = createSettingsScope<Record<string, unknown>>(\n ctx as unknown as SettingsScopeContext,\n COMMANDCODE_NS,\n () => settingsNamespace,\n )\n ctx.effect(() => () => { void scope.dispose() }, 'dsh-commandcode-provider: settings scope')\n ctx.inject(['remote.settings'], (settingsCtx) => {\n settingsNamespace = (settingsCtx.remote as unknown as {\n settings: SettingsRemoteNamespace\n }).settings\n // The first read raced this inject and answered \"not mounted\"; re-read now\n // that the namespace is here (and again whenever it re-mounts).\n scope.refresh()\n settingsCtx.effect(() => () => {\n settingsNamespace = undefined\n }, 'dsh-commandcode-provider: settings namespace')\n })\n // The model catalog for the settings page's model editors is served by the\n // `commandcode/models` Remote mounted below, which happens after this\n // controller is constructed — so it reads the catalog through this mutable\n // seam. Unset until the mount lands; the controller degrades to the\n // 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 )\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 () => {\n const remote = ctx.remote as unknown as {\n $on(\n event: 'credentials/reference-updated' | 'credentials/record-updated',\n listener: (ref: string) => void,\n ): () => void\n }\n const unregisterReference = remote.$on('credentials/reference-updated', () => {\n controller.refreshCredentials()\n })\n const unregisterRecord = remote.$on('credentials/record-updated', () => {\n controller.refreshCredentials()\n })\n return () => {\n unregisterReference()\n unregisterRecord()\n }\n },\n 'dsh-commandcode-provider: credential invalidations',\n )\n\n // One mount carries every endpoint this plugin serves (report, catalog, price\n // table, login), keeping the Client's bookkeeping 1:1 with the Host's single\n // registry registration. Cordis only serves services a fiber declares in\n // `inject`, and the namespace service exists only after the mount — so the\n // `remote.commandcode` inject is registered DYNAMICALLY once the mount\n // lands; a static one would deadlock the plugin, the mounter waiting for its\n // own mount. A Host half that predates the Remote fails the calls instead,\n // and the surfaces render their error branches.\n let usageNamespace: (typeof ctx.remote)['commandcode'] | undefined\n let usageMountError: string | undefined\n // `pricesController` and `refreshUsage` are declared here and assigned below,\n // because the mount effect's inject callback calls them while cordis runs it\n // synchronously — before their own `const` would be initialized. A read in\n // that temporal dead zone THROWS, which `?.` would not save.\n let pricesController: CommandCodePricesController | undefined\n let refreshUsage: (() => void) | undefined\n let analyticsController: AnalyticsController | undefined\n const contribution: TypertRemoteContribution = {\n package: USAGE_REMOTE_CONTRIBUTION.package,\n descriptors: [\n ...USAGE_REMOTE_CONTRIBUTION.descriptors,\n ...MODELS_REMOTE_CONTRIBUTION.descriptors,\n ...PRICES_REMOTE_CONTRIBUTION.descriptors,\n ...ANALYTICS_REMOTE_CONTRIBUTION.descriptors,\n ...LOGIN_REMOTE_CONTRIBUTION.descriptors,\n ...ENROLLMENT_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 model editors,\n // and the price table the composer's cost readout needs — `ensure()` is\n // idempotent, so asking earlier could only fail (the namespace did not\n // exist yet).\n controller.refreshCatalog()\n pricesController?.reload()\n analyticsController?.reload()\n // ...and the usage report. A surface can (and on a boot with the quota\n // card on, always does) ask for it BEFORE this mount lands: the answer\n // then is the synthetic \"remote is not mounted\" failure, which the\n // controller stores as `status: 'error'` — and its `shouldRefresh` only\n // fires from `idle`, so nothing would ever retry it (`usage.ts`). The\n // namespace is live here, so re-read now and replace that stale answer.\n refreshUsage?.()\n namespaceCtx.effect(() => () => {\n usageNamespace = undefined\n analyticsController?.reload()\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 = readableErrorText(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 prices: async () => {\n const namespace = usageNamespace\n if (namespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode/prices remote is not mounted' } }\n }\n const call = namespace.prices\n // A Host half older than the price table mounts no such descriptor, so\n // the namespace member is genuinely missing. Report it as a permanent\n // failure the readout understands rather than throwing.\n if (typeof call !== 'function') {\n return { ok: false, error: { message: 'the Host serves no commandcode/prices endpoint', permanent: true } }\n }\n return call.call(namespace)\n },\n }\n modelsRemote = () => usageRemote.models()\n const usageController = new CommandCodeUsageController(usageRemote)\n refreshUsage = () => void usageController.refresh()\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 composer's session-cost readout prices from a static table, so its\n // controller is a one-shot cache rather than a poll.\n pricesController = new CommandCodePricesController(usageRemote)\n ctx.effect(() => () => pricesController?.dispose(), 'dsh-commandcode-provider: price table')\n const pricesStore = createSnapshotStore<SessionCostPricesState>(pricesController.state())\n pricesController.subscribe(() => pricesStore.set(pricesController.state()))\n\n analyticsController = new AnalyticsController({ analytics: async query => {\n const namespace = usageNamespace\n if (typeof namespace?.analytics !== 'function') return { ok: false, error: { message: '宿主不支持模型分析,请更新插件' } }\n return namespace.analytics(query)\n } })\n const analyticsStore = createSnapshotStore(analyticsController.state())\n analyticsController.subscribe(() => analyticsStore.set(analyticsController!.state()))\n ctx.effect(() => () => analyticsController?.dispose(), 'commandcode analytics controller')\n const panelMode = createSnapshotStore<'quota' | 'analysis'>('quota')\n const openAnalytics = () => {\n panelMode.set('analysis')\n const layout = ctx.get('layout') as LayoutSelectionSeam | undefined\n layout?.selectPanel(PANEL_ID)\n }\n\n // The login panel: same namespace, three endpoints. The key NEVER crosses to\n // 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 (targetRef?: string) => {\n if (usageNamespace === undefined) {\n return { ok: false, error: { message: usageMountError ?? 'commandcode remote is not mounted' } }\n }\n return usageNamespace.loginBegin(targetRef)\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, so 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 refreshUsageOn = (ok: boolean): boolean => {\n const outcome = controller.state().accountResult\n if (ok || outcome?.config === 'confirmed' || outcome?.credential === 'confirmed') void usageController.refresh()\n return ok\n }\n const injected = () => ({\n createEnrollment: () => new AccountEnrollmentController(() => {\n if (!usageNamespace?.enrollmentBegin) throw new Error('宿主不支持账号开通,请更新插件')\n return usageNamespace as EnrollmentRemote\n }, () => { scope.refresh(); controller.refreshCredentials(); void usageController.refresh() }),\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 // 部分完成也可能改变凭据或连接配置,用本次确认结果刷新用量。\n save: () => void controller.save().then(outcome => {\n if (outcome?.config === 'confirmed' || outcome?.credential === 'confirmed') void usageController.refresh()\n }),\n discard: () => controller.discard(),\n refreshCredentials: () => void controller.refreshCredentials(),\n refreshUsage: () => void usageController.refresh(),\n ...(typeof (ctx.get('layout') as LayoutSelectionSeam | undefined)?.selectPanel === 'function' ? { openAnalytics } : {}),\n beginLogin: (targetRef?: string) => void loginController.begin(targetRef),\n cancelLogin: () => void loginController.cancel(),\n // Account operations commit immediately. The ones that change which keys\n // exist refetch the usage report so the account rows follow.\n renameAccount: (ref: string, label: string) => controller.renameAccount(ref, label),\n removeAccount: (ref: string) => controller.removeAccount(ref).then((ok) => {\n // 配置可能已移除、凭据清理仍失败;用量页也应立即跟随新的账户列表。\n if (ok || !controller.state().accounts.some((account) => account.ref === ref)) void usageController.refresh()\n return ok\n }),\n retryCredentialCleanup: (ref: string) => controller.retryCredentialCleanup(ref).then(refreshUsageOn),\n setAccountKey: (target: string, key: string) => controller.setAccountKey(target, key).then(refreshUsageOn),\n clearAccountKey: (target: string) => controller.clearAccountKey(target).then(refreshUsageOn),\n setActiveAccount: (id: string) => controller.setActiveAccount(id).then(refreshUsageOn),\n setAccountModels: (target: string, ids: string[]) => controller.setAccountModels(target, ids),\n editVisibleModels: (ids: string[]) => controller.editVisibleModels(ids),\n clearVisibleModels: () => controller.clearVisibleModels(),\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: a keyed slot the Models section dispatches\n // with `entryKey = settingsNs` on every provider row of an adapter family, so\n // the panel mounts beside the official editor on every Command Code row —\n // including the first-run setup posture, exactly where a user without a key\n // lands. While the official 编辑 toggle is open, the card hides the official\n // editor shell (for this namespace `layoutOf` returns \"unknown\", so that shell\n // carries only a config hint over a disabled apply) and shows the real\n // controls; see card.tsx. The registration carries its own inject face\n // because the declaring entry is ui-settings-models', not ours; the `t` seat\n // comes from the registration's own `locale` namespace.\n //\n // On a build without this slot the declaration never exists and `slots.inject`\n // never fires — the registration silently does not happen. Do not \"harden\"\n // that into an error.\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(outcome => {\n if (outcome?.config === 'confirmed' || outcome?.credential === 'confirmed') void usageController.refresh()\n }),\n discard: () => controller.discard(),\n refreshCredentials: () => void controller.refreshCredentials(),\n beginLogin: () => void loginController.begin(),\n cancelLogin: () => void loginController.cancel(),\n }),\n }, CommandCodeProviderCard))\n\n // The plans & quota panel: a footer card pinned at the bottom of the sidebar,\n // on top of the Settings seat, that opens a dashboard in the center column.\n //\n // Two registrations, ONE navigation entry: `sidebar.footer.action` is the\n // list the sidebar shell renders in its foot area directly above the Settings\n // seat (`footArea` = `footerActions` then `settingsArea`), which is what puts\n // this card at the bottom of the column rather than at the top with the\n // global panel icons of `sidebar.panellist`. The layout's keyed `main` slot\n // holds the panel the card opens — `selectPanel(id)` resolves the id against\n // that registry and throws when no cell occupies it, so BOTH registrations\n // are required, and BOTH need the `inject` face below (an entry without one\n // receives none of the panel's data; see the `hooks` → `useX` rule in\n // panel-view.tsx).\n //\n // Unlike a `sidebar.panellist` row, the shell renders NO chrome around a\n // footer action: our component IS the button, it owns the label (so a title\n // carrying live quota needs no re-registration — that dance exists only\n // because the shell caches a panellist entry's label), and it selects the\n // panel itself through the `open` action below.\n //\n // Both registrations declare the panel's own `locale` namespace\n // (`panel.commandcode`, registered in `apply` above): that is what binds the\n // `t` seat the components feed into `buildPanelView`, so the panel follows\n // the harness's active language and a switch re-renders it.\n //\n // The footer card is gated on the `layout` SERVICE (below), not only on its\n // slot: a profile whose `main` declaration exists but whose layout never\n // mounted would otherwise register a card that renders and does nothing —\n // a dead button. The dashboard cell needs no such gate; registering against\n // a declaration that never arrives is a no-op by construction.\n //\n // Shape notes:\n // * The stylesheet gets its own `ctx.effect` rather than riding an `inject`\n // callback's return value, so the tag's lifetime is the plugin fiber's and\n // is unaffected by a slot declaration collapsing and re-declaring.\n // * Each registration is guarded so a failure in one surface cannot abort\n // `applyClientSurfaces` and take the OTHER surfaces down with it —\n // `slots.inject` rethrows a callback failure synchronously once the\n // declaration exists. The renderer contains a *render* crash by abdicating\n // the entry with no visible error, so a failure that leaves nothing on\n // screen must at least be loud in the console.\n const panelFace = (): PanelInjected => ({\n hooks: { commandCodeUsage: usageStore, commandCodeSettings: store, commandCodeAnalytics: analyticsStore, commandCodePanelMode: panelMode },\n selectPanelMode: (mode) => panelMode.set(mode),\n refreshAnalytics: (query?: AnalyticsQuery) => analyticsController?.refresh(query),\n refresh: () => { pricesController?.ensure(); void usageController.refresh() },\n // The Host resolves every credential source, including CLI auth and\n // literals. A browser credential-reference lookup cannot determine\n // availability.\n startAutoRefresh: () => startPanelAutoRefresh(usageController, () => true),\n // `layout` is read reflectively AT CLICK TIME, never captured at setup:\n // ui-layout is not a dependency of this bundle (its types are not imported\n // and its client module is never resolved), and it is not in the exported\n // inject list. The footer registration below is gated on the same seam, so\n // by the time this runs the method exists; the guard stays as the last line\n // of defence against a layout that renames it.\n open: () => {\n panelMode.set('quota')\n const layout = ctx.get('layout') as LayoutSelectionSeam | undefined\n layout?.selectPanel(PANEL_ID)\n },\n // The dashboard's way out (issue #41). It occupies the center column in\n // place of the Conversation, and `open()` above is the ONLY other panel\n // selection this plugin makes — so without an exit the panel is a one-way\n // door: clicking the sidebar card just re-selects it. `selectPanel(null)`\n // is layout's \"show the Conversation\" selection and leaves the current\n // Session untouched.\n close: () => {\n const layout = ctx.get('layout') as LayoutSelectionSeam | undefined\n layout?.selectPanel(null)\n },\n })\n\n ctx.effect(() => injectCss(PANEL_CSS_ID, PANEL_CSS), 'dsh-commandcode-provider: panel styles')\n\n try {\n ctx.slots.inject('main', () => ctx.slots.register(\n { name: 'main', key: PANEL_ID, locale: PANEL_LOCALE_NS, inject: panelFace },\n CommandCodePanel,\n ))\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] could not register the plans & quota panel:', error)\n }\n\n // The footer card is registered only where the layout can actually open the\n // panel behind it: `ctx.inject(['layout'], …)` runs its body when that service\n // is live and re-runs it if the service is replaced, mirroring how the Remote\n // namespace is mounted — so a profile without ui-layout (the TUI, a headless\n // client) never registers the card at all.\n ctx.inject(['layout'], (layoutCtx) => {\n try {\n layoutCtx.slots.inject('sidebar.footer.action', () => layoutCtx.slots.register(\n // `order` is the only control over position inside a list slot, and the\n // renderer sorts ascending. ui-cordis's footer chip registers at the\n // default 0, so 1 sorts after it — but any sibling passing an order ≥ 1\n // lands between this card and Settings, so \"directly above Settings\" is\n // a preference, not a guarantee.\n { name: 'sidebar.footer.action', id: PANEL_ID, order: 1, locale: PANEL_LOCALE_NS, inject: panelFace },\n CommandCodeFooterEntry,\n ))\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] could not register the sidebar footer card:', error)\n }\n })\n\n // The composer's session-cost figure: an entry in the dock below the input\n // that renders NO surface of its own. The cost is injected into the harness's\n // own token-usage UI — the amount as the last item of the shipped pill's text\n // run, the breakdown as rows inside the usage dialog that pill opens (see\n // `./session-cost-display.ts`).\n //\n // The entry exists for its SEATS, not for a surface: `useProjection` is a\n // standard prop the composer hands every dock occupant, so this registration\n // is the only way to read the session's token accounting. The token buckets\n // and the model selection arrive from the composer itself as standard dock\n // props, so the face carries only the price-table hook.\n //\n // No `locale` namespace and no `t` seat: the figure is English by\n // construction, from `./session-cost.ts`.\n const sessionCostFace = (): SessionCostInjected => ({\n hooks: { commandCodePrices: pricesStore },\n })\n\n try {\n ctx.slots.inject('conversation.composer.dock', () => ctx.slots.register(\n // No `order`: the entry renders nothing, so its position among the dock's\n // rows cannot matter — the sort only ever decides what a reader sees.\n { name: 'conversation.composer.dock', id: SESSION_COST_ID, inject: sessionCostFace },\n CommandCodeSessionCost,\n ))\n } catch (error: unknown) {\n console.error('[dsh-commandcode-provider] could not register the composer session-cost readout:', error)\n }\n}\n\nexport const inject: readonly string[] = [\n 'slots',\n 'locale',\n 'remote',\n]\n"],"mappings":"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"}