@chatcode/cco-llm-chatcode-config 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/README.zh.md +5 -5
- package/lib/client.js +21 -16
- package/lib/index.js +2 -3
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/dsh-llm-pi-ai/src/config.ts +1 -1
- package/vendor/dsh-llm-pi-ai/tests/adapter.spec.ts +10 -1
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["invalid","Config","wait","protocolOf","endpointOf","isRecord","isRecord","errorMessage"],"sources":["../src/update.ts","../src/version-check.ts","../vendor/dsh-llm-pi-ai/src/auth.ts","../vendor/dsh-llm-pi-ai/src/replay.ts","../vendor/dsh-llm-pi-ai/src/catalog.ts","../vendor/dsh-llm-pi-ai/src/provider.ts","../vendor/dsh-llm-pi-ai/src/config.ts","../vendor/dsh-llm-pi-ai/src/context.ts","../vendor/dsh-llm-pi-ai/src/stream.ts","../vendor/dsh-llm-pi-ai/src/adapter.ts","../src/adapter.ts","../src/chatcode-auth.ts","../src/config.ts","../src/managed.ts","../src/reporting/outbox.ts","../src/reporting/code.ts","../src/reporting/payloads.ts","../src/reporting/reporter.ts","../src/reporting/model-kind.ts","../src/reporting/transport.ts","../src/reporting/index.ts","../src/source.ts","../src/index.ts"],"sourcesContent":["/** Self-update for the global ChatCode CLI installation. @module dsh-llm-chatcode-config/update */\n\nimport { spawn, spawnSync, type ChildProcess, type StdioOptions } from 'node:child_process'\nimport { createRequire } from 'node:module'\n\n/**\n * The public ChatCode CLI package owns both browser and terminal surfaces.\n */\nexport const CHATCODE_CLI_PACKAGES = ['@chatcode/chatcode-cli'] as const\n\n/** Bound one npm call so a stalled registry cannot hang the command forever. */\nconst VIEW_TIMEOUT_MS = 20_000\nconst LIST_TIMEOUT_MS = 15_000\nconst INSTALL_TIMEOUT_MS = 120_000\n\n/** Outcome of one update run, shared by `chatcode-cli --update` and `/update`. */\nexport interface UpdateResult {\n status: 'up-to-date' | 'updated' | 'error' | 'aborted'\n /** Human-facing summary shown by both entry points. */\n message: string\n}\n\n/** Progress sink and cancellation for the interactive `/update` path. */\nexport interface UpdateOptions {\n /** Cancel the run: each awaited step checks it and npm children are killed. */\n signal?: AbortSignal\n /** Receive one progress line instead of writing it to stdout. */\n onProgress?: (line: string) => void\n}\n\n/** Print one progress line to the terminal while an update runs. */\nfunction log(message: string): void {\n process.stdout.write(`[update] ${message}\\n`)\n}\n\n/**\n * Run one npm invocation and capture its exit code and combined output.\n * Registry, auth, and proxy resolution are npm's own business: no registry is\n * forced, so a project's `.npmrc` (mirror, scoped registry, token) applies.\n * @param args - npm arguments after the `npm` command word.\n * @param timeoutMs - bound on the whole invocation.\n */\nfunction runNpm(args: readonly string[], timeoutMs: number, signal?: AbortSignal): Promise<{ code: number; output: string }> {\n return new Promise((resolve) => {\n // Windows resolves npm through its .cmd shim, which Node refuses to spawn\n // without a shell since the CVE-2024-27980 hardening. The shell receives a\n // single command string (never an argument array), which also avoids the\n // DEP0190 warning about unescaped shell arguments.\n const win = process.platform === 'win32'\n const stdio: StdioOptions = ['ignore', 'pipe', 'pipe']\n let child: ChildProcess\n if (win) {\n // A single command string, so no argument array is exposed to the shell.\n const spec = args.map(argument => /\\s/.test(argument) ? JSON.stringify(argument) : argument).join(' ')\n child = spawn(`npm ${spec}`, { shell: true, stdio })\n } else {\n child = spawn('npm', args, { stdio })\n }\n let output = ''\n let done = false\n const settle = (code: number): void => {\n if (done) return\n done = true\n clearTimeout(timer)\n if (signal !== undefined) signal.removeEventListener('abort', onAbort)\n resolve({ code, output })\n }\n const timer = setTimeout(() => { child.kill() }, timeoutMs)\n // An interactive cancellation kills the npm child so a stalled install\n // cannot keep running behind the closed panel.\n const onAbort = (): void => {\n clearTimeout(timer)\n child.kill()\n }\n if (signal !== undefined) {\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n const collect = (chunk: Buffer): void => { output += chunk.toString() }\n child.stdout?.on('data', collect)\n child.stderr?.on('data', collect)\n child.on('error', (error) => { output += String(error); settle(-1) })\n child.on('close', (code) => { settle(code ?? -1) })\n })\n}\n\n/** Strip npm's advisory `npm warn` lines from captured combined output. */\nfunction cleanNpmOutput(output: string): string {\n return output.split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== '' && !/^npm warn\\b/i.test(line))\n .join('\\n')\n}\n\n/**\n * Turn npm's noisy combined output into one readable failure line. `--json`\n * errors print `{ \"error\": { \"code\", \"summary\", \"detail\" } }` on stderr,\n * possibly surrounded by `npm error` prose; lift the first brace block and read\n * the summary from it, else fall back to the cleaned raw text.\n */\nfunction describeNpmFailure(output: string, packageName: string): string {\n const start = output.indexOf('{')\n const end = output.lastIndexOf('}')\n if (start !== -1 && end > start) {\n try {\n const parsed = JSON.parse(output.slice(start, end + 1)) as { error?: { code?: unknown; summary?: unknown; detail?: unknown } }\n const code = typeof parsed.error?.code === 'string' ? parsed.error.code : undefined\n const summary = typeof parsed.error?.summary === 'string' ? parsed.error.summary : undefined\n if (code !== undefined || summary !== undefined) {\n return `${summary ?? code}(${packageName})`\n }\n } catch {\n // Not a parseable JSON block; fall through to the cleaned raw text.\n }\n }\n const cleaned = cleanNpmOutput(output)\n return `${cleaned || 'npm view 失败'}(${packageName})`\n}\n\n/**\n * Fetch the latest published version of one package through `npm view`, so the\n * same registry, scoped-registry override, and auth token the installer uses\n * also decide what \"latest\" means.\n */\nexport async function fetchLatestVersion(packageName: string, signal?: AbortSignal): Promise<string> {\n const result = await runNpm(['view', packageName, 'version', '--json'], VIEW_TIMEOUT_MS, signal)\n if (result.code !== 0 || result.output.trim() === '') {\n throw new Error(describeNpmFailure(result.output, packageName))\n }\n const stdout = cleanNpmOutput(result.output)\n try {\n const parsed = JSON.parse(stdout) as unknown\n if (typeof parsed === 'string' && parsed !== '') return parsed\n } catch {\n // npm prints a bare version string on some versions; fall through.\n }\n throw new Error(`无法从 registry 解析最新版本(${packageName})`)\n}\n\n/** Best-effort read of one installed package version from a co-located install. */\nfunction resolveCoLocatedVersion(packageName: string): string | undefined {\n try {\n const require = createRequire(import.meta.url)\n const manifest = require(`${packageName}/package.json`) as { version?: unknown }\n return typeof manifest.version === 'string' ? manifest.version : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Extract the `--json` result from npm's combined output. npm can prefix\n * advisory `npm warn` lines on stderr (e.g. from a pnpm-injected env config),\n * so lift the first brace block and parse just that, not the whole stream.\n */\nfunction parseNpmJson(output: string): unknown {\n const start = output.indexOf('{')\n const end = output.lastIndexOf('}')\n if (start === -1 || end <= start) return undefined\n try {\n return JSON.parse(output.slice(start, end + 1)) as unknown\n } catch {\n return undefined\n }\n}\n\n/** Resolve one installed global package version through npm's own store. */\nasync function resolveGlobalVersion(packageName: string, signal?: AbortSignal): Promise<string | undefined> {\n const result = await runNpm(['list', '-g', packageName, '--json', '--depth=0'], LIST_TIMEOUT_MS, signal)\n // npm ls can exit non-zero for unrelated problems in the global tree; only an\n // empty or unparseable payload counts as \"not found\".\n if (result.output.trim() === '') return undefined\n const parsed = parseNpmJson(result.output) as { dependencies?: Record<string, { version?: unknown }> } | undefined\n const version = parsed?.dependencies?.[packageName]?.version\n return typeof version === 'string' ? version : undefined\n}\n\n/**\n * Best-effort read of one installed package version; `undefined` when it cannot\n * be resolved. The co-located probe first targets a dev tree, then falls back\n * to npm's view of the global install.\n */\nexport async function resolveCurrentVersion(packageName: string, signal?: AbortSignal): Promise<string | undefined> {\n return resolveCoLocatedVersion(packageName) ?? await resolveGlobalVersion(packageName, signal)\n}\n\n/** Run `npm install -g <specs...>`, letting npm pick the registry it would install from. */\nexport function runNpmInstall(packageSpecs: readonly string[], signal?: AbortSignal): Promise<{ code: number; output: string }> {\n return runNpm(['install', '-g', ...packageSpecs], INSTALL_TIMEOUT_MS, signal)\n}\n\n/** One package's installed and published versions. */\ninterface PackageUpdate {\n name: string\n current: string | undefined\n latest: string\n}\n\n/**\n * Check the latest version and, when newer than the running one, install the\n * public ChatCode CLI package. Progress lines go to `options.onProgress` when given (the\n * interactive surface renders them in a panel), else to stdout — so the\n * `chatcode-cli --update` sync entry point keeps printing as before. Every awaited step\n * honors `options.signal`: an abort kills the in-flight npm child and settles\n * with the `aborted` status.\n */\nexport async function runUpdate(options: UpdateOptions = {}): Promise<UpdateResult> {\n const { signal, onProgress } = options\n const progress = (line: string): void => {\n if (onProgress !== undefined) onProgress(line)\n else log(line)\n }\n const aborted = (): UpdateResult | undefined =>\n signal?.aborted === true ? { status: 'aborted', message: '更新已中止' } : undefined\n\n progress(`开始检查更新:${CHATCODE_CLI_PACKAGES.join('、')}`)\n const updates: PackageUpdate[] = []\n for (const name of CHATCODE_CLI_PACKAGES) {\n if (aborted() !== undefined) return aborted()!\n const current = await resolveCurrentVersion(name, signal)\n if (aborted() !== undefined) return aborted()!\n progress(`当前版本 ${name}:${current ?? '(未安装或未解析)'}`)\n let latest: string\n try {\n latest = await fetchLatestVersion(name, signal)\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error)\n progress(`检查 ${name} 最新版本失败:${detail}`)\n return {\n status: 'error',\n message: `检查更新失败:${detail}`,\n }\n }\n if (aborted() !== undefined) return aborted()!\n progress(`最新版本 ${name}:${latest}`)\n updates.push({ name, current, latest })\n }\n\n const needsUpdate = updates.some(update => update.current !== update.latest)\n if (!needsUpdate) {\n const summary = updates.map(update => `${update.name} ${update.latest}`).join(',')\n progress('ChatCode CLI 已是最新版本,无需更新')\n return { status: 'up-to-date', message: `ChatCode CLI 已是最新版本(${summary})` }\n }\n\n const packageSpecs = updates.map(update => `${update.name}@${update.latest}`)\n progress(`检测到新版本,开始安装:${packageSpecs.join(' ')}`)\n const result = await runNpmInstall(packageSpecs, signal)\n if (aborted() !== undefined) return aborted()!\n if (result.code !== 0) {\n const detail = cleanNpmOutput(result.output) || '未知错误'\n progress(`安装失败(exit ${result.code})`)\n return {\n status: 'error',\n message: `更新失败:${detail}\\n请手动执行:npm install -g ${packageSpecs.join(' ')}`,\n }\n }\n\n progress('安装完成')\n const summary = updates.map(update => `${update.name} ${update.current ?? '(未知)'} → ${update.latest}`).join(',')\n return { status: 'updated', message: `已更新:${summary},请重启 ChatCode CLI 以生效` }\n}\n\n/** Run one npm invocation synchronously and capture its exit code and output. */\nfunction syncRunNpm(args: readonly string[], timeoutMs: number): { code: number; output: string } {\n const win = process.platform === 'win32'\n const spec = args.map(argument => /\\s/.test(argument) ? JSON.stringify(argument) : argument).join(' ')\n const result = win\n ? spawnSync(`npm ${spec}`, { shell: true, encoding: 'utf8', timeout: timeoutMs, stdio: ['ignore', 'pipe', 'pipe'] })\n : spawnSync('npm', args, { encoding: 'utf8', timeout: timeoutMs, stdio: ['ignore', 'pipe', 'pipe'] })\n if (result.error !== undefined) return { code: -1, output: String(result.error) }\n return { code: result.status ?? -1, output: `${result.stdout ?? ''}${result.stderr ?? ''}` }\n}\n\n/**\n * Print one progress line without yielding the event loop. On a Windows\n * console `process.stdout.write` still issues the console write immediately\n * (libuv calls WriteConsoleW synchronously), so the bytes are on screen before\n * the caller's hard exit — and because we never yield, the concurrently booting\n * profile stays frozen and cannot print its own logs.\n */\nfunction syncLog(message: string): void {\n process.stdout.write(`[update] ${message}\\n`)\n}\n\n/** Resolve one installed global package version synchronously through npm's store. */\nfunction resolveGlobalVersionSync(packageName: string): string | undefined {\n const result = syncRunNpm(['list', '-g', packageName, '--json', '--depth=0'], LIST_TIMEOUT_MS)\n if (result.output.trim() === '') return undefined\n const parsed = parseNpmJson(result.output) as { dependencies?: Record<string, { version?: unknown }> } | undefined\n const version = parsed?.dependencies?.[packageName]?.version\n return typeof version === 'string' ? version : undefined\n}\n\n/**\n * Synchronous twin of {@link runUpdate} for `chatcode-cli --update`. Blocking the event\n * loop on purpose: the profile's other plugins boot concurrently with this one,\n * and `chatcode-cli --update` must finish — and exit — before any of them can print.\n * The final message is returned, not logged, so the caller writes it once and\n * picks the exit code.\n */\nexport function runUpdateSync(): UpdateResult {\n syncLog(`开始检查更新:${CHATCODE_CLI_PACKAGES.join('、')}`)\n const updates: PackageUpdate[] = []\n for (const name of CHATCODE_CLI_PACKAGES) {\n const current = resolveCoLocatedVersion(name) ?? resolveGlobalVersionSync(name)\n syncLog(`当前版本 ${name}:${current ?? '(未安装或未解析)'}`)\n const view = syncRunNpm(['view', name, 'version', '--json'], VIEW_TIMEOUT_MS)\n let latest: string\n if (view.code !== 0 || view.output.trim() === '') {\n const detail = describeNpmFailure(view.output, name)\n syncLog(`检查 ${name} 最新版本失败:${detail}`)\n return { status: 'error', message: `检查更新失败:${detail}` }\n }\n try {\n const parsed = JSON.parse(cleanNpmOutput(view.output)) as unknown\n if (typeof parsed !== 'string' || parsed === '') throw new Error('invalid version payload')\n latest = parsed\n } catch {\n const detail = `无法从 registry 解析最新版本(${name})`\n syncLog(`检查 ${name} 最新版本失败:${detail}`)\n return { status: 'error', message: `检查更新失败:${detail}` }\n }\n syncLog(`最新版本 ${name}:${latest}`)\n updates.push({ name, current, latest })\n }\n\n const needsUpdate = updates.some(update => update.current !== update.latest)\n if (!needsUpdate) {\n const summary = updates.map(update => `${update.name} ${update.latest}`).join(',')\n syncLog('ChatCode CLI 已是最新版本,无需更新')\n return { status: 'up-to-date', message: `ChatCode CLI 已是最新版本(${summary})` }\n }\n\n const packageSpecs = updates.map(update => `${update.name}@${update.latest}`)\n syncLog(`检测到新版本,开始安装:${packageSpecs.join(' ')}`)\n const install = syncRunNpm(['install', '-g', ...packageSpecs], INSTALL_TIMEOUT_MS)\n if (install.code !== 0) {\n const detail = cleanNpmOutput(install.output) || '未知错误'\n syncLog(`安装失败(exit ${install.code})`)\n return { status: 'error', message: `更新失败:${detail}\\n请手动执行:npm install -g ${packageSpecs.join(' ')}` }\n }\n\n syncLog('安装完成')\n const summary = updates.map(update => `${update.name} ${update.current ?? '(未知)'} → ${update.latest}`).join(',')\n return { status: 'updated', message: `已更新:${summary},请重启 ChatCode CLI 以生效` }\n}\n","/**\n * Startup version admission against the CVP version-validate endpoint.\n *\n * Mirrors the `yuanjing-wanma-cli` startup flow: after launch, ask CVP whether\n * the installed ChatCode CLI package is still usable. When the server reports a newer\n * enabled version (status 1) or a disabled current version with a rollback\n * (status -1), present a keyboard dialog and either install the server-selected\n * version or leave the program before the interactive surface mounts.\n * @module dsh-llm-chatcode-config/version-check\n */\n\nimport { emitKeypressEvents, type Key } from 'node:readline'\nimport { stdin, stdout } from 'node:process'\nimport type { Config } from './config.ts'\nimport { CHATCODE_CLI_PACKAGES, resolveCurrentVersion, runNpmInstall } from './update.ts'\n\nexport type VersionCheckAction = 'upgrade' | 'rollback'\n\n/** One ChatCode CLI package the server asked us to move. */\nexport interface VersionCheckPackage {\n name: string\n /** Version currently installed on this machine. */\n currentVersion: string\n /** Version the server wants us to install. */\n targetVersion: string\n}\n\n/** A startup decision that requires user interaction. */\nexport interface VersionCheckDecision {\n action: VersionCheckAction\n packages: VersionCheckPackage[]\n}\n\nexport interface VersionCheckOptions {\n request?: typeof fetch\n resolveVersion?: (packageName: string) => Promise<string | undefined>\n timeoutMs?: number\n}\n\n/** Union of the endpoint's two status envelopes plus the 500 error fallback. */\ninterface ValidateBody {\n code?: unknown\n data?: unknown\n status?: unknown\n version?: unknown\n}\n\nconst ERROR_CODE = 500\n\nfunction validateUrl(cvpChatCodeApiUrl: string): URL {\n const base = cvpChatCodeApiUrl.replace(/\\/+$/u, '')\n return new URL(`${base}/chatcode/api/v1/cli/version/validate`)\n}\n\n/**\n * Interpret one 200 JSON body. Returns nothing when the server said \"valid\",\n * \"unknown package/version\", or errored — every such case leaves startup alone,\n * matching the reference's fail-open behavior.\n */\nfunction decide(body: ValidateBody): { action: VersionCheckAction; version: string } | undefined {\n if (body.code === ERROR_CODE) return undefined\n const data = body.data\n const payload = data !== null && typeof data === 'object' ? data as ValidateBody : body\n if (typeof payload.version === 'string' && payload.version !== '') {\n if (payload.status === 1) return { action: 'upgrade', version: payload.version }\n if (payload.status === -1) return { action: 'rollback', version: payload.version }\n }\n return undefined\n}\n\nasync function validatePackage(\n config: Config,\n packageName: string,\n options: VersionCheckOptions,\n): Promise<{ action: VersionCheckAction; currentVersion: string; version: string } | undefined> {\n const resolveVersion = options.resolveVersion ?? resolveCurrentVersion\n let versionNum: string | undefined\n try {\n versionNum = await resolveVersion(packageName)\n } catch {\n return undefined\n }\n if (versionNum === undefined || versionNum === '') return undefined\n\n const url = validateUrl(config.cvpChatCodeApiUrl)\n url.searchParams.set('packageName', packageName)\n url.searchParams.set('versionNum', versionNum)\n\n console.log(`[version-check] 开始校验 ${packageName}@${versionNum}`)\n const request = options.request ?? fetch\n let response: Response\n try {\n response = await request(url, { signal: AbortSignal.timeout(options.timeoutMs ?? 10_000) })\n } catch (err) {\n console.log(`[version-check] 请求失败 (${packageName}): ${(err as Error)?.message ?? err}`)\n return undefined\n }\n if (!response.ok) return undefined\n const body = await response.json().catch(() => undefined) as ValidateBody | undefined\n if (body === null || typeof body !== 'object') return undefined\n const wrapped = decide(body)\n return wrapped === undefined ? undefined : { ...wrapped, currentVersion: versionNum }\n}\n\n/**\n * Validate the ChatCode CLI package and collapse results into one decision.\n * A disabled version wins over an available upgrade: an unusable install must\n * be replaced before any forward update matters.\n */\nexport async function checkVersions(config: Config, options: VersionCheckOptions = {}): Promise<VersionCheckDecision | undefined> {\n const outcomes = (await Promise.all(CHATCODE_CLI_PACKAGES.map(async (name): Promise<VersionCheckPackage & { action: VersionCheckAction } | undefined> => {\n const outcome = await validatePackage(config, name, options)\n return outcome === undefined ? undefined : { name, action: outcome.action, currentVersion: outcome.currentVersion, targetVersion: outcome.version }\n }))).filter((entry): entry is VersionCheckPackage & { action: VersionCheckAction } => entry !== undefined)\n\n const rollbacks = outcomes.filter(entry => entry.action === 'rollback')\n if (rollbacks.length > 0) return { action: 'rollback', packages: rollbacks.map(({ name, currentVersion, targetVersion }) => ({ name, currentVersion, targetVersion })) }\n const upgrades = outcomes.filter(entry => entry.action === 'upgrade')\n if (upgrades.length > 0) return { action: 'upgrade', packages: upgrades.map(({ name, currentVersion, targetVersion }) => ({ name, currentVersion, targetVersion })) }\n return undefined\n}\n\n/** Install the server-selected versions for one decision. */\nexport async function runDecisionInstall(decision: VersionCheckDecision): Promise<{ ok: boolean; message: string }> {\n const specs = decision.packages.map(pkg => `${pkg.name}@${pkg.targetVersion}`)\n const result = await runNpmInstall(specs)\n if (result.code !== 0) {\n const detail = result.output.trim() || '未知错误'\n return { ok: false, message: `安装失败:${detail}\\n请手动执行:npm install -g ${specs.join(' ')}` }\n }\n const summary = decision.packages.map(pkg => `${pkg.name} ${pkg.targetVersion}`).join('、')\n const verb = decision.action === 'upgrade' ? '升级' : '更换'\n return { ok: true, message: `已${verb}到 ${summary},请重启 ChatCode CLI 以生效` }\n}\n\nexport interface VersionPrompt {\n title: string\n message: string\n performLabel: string\n cancelLabel: string\n}\n\n/** Localize one decision into the terminal dialog copy. */\nexport function decisionPrompt(decision: VersionCheckDecision): VersionPrompt {\n const targets = decision.packages.map(pkg => `${pkg.name} ${pkg.targetVersion}`).join('、')\n if (decision.action === 'upgrade') {\n return {\n title: '版本升级提醒',\n message: `新版本已发布(${targets}),请升级后再使用。`,\n performLabel: '升级',\n cancelLabel: '不升级(退出程序)',\n }\n }\n const current = decision.packages.map(pkg => `${pkg.name} ${pkg.currentVersion}`).join('、')\n return {\n title: '版本禁用提醒',\n message: `当前版本已禁用(${current}),请更换到(${targets})后再使用。`,\n performLabel: '更换',\n cancelLabel: '不更换(退出程序)',\n }\n}\n\n/**\n * Show a two-option keyboard dialog: up/down arrows move the cursor, Enter\n * chooses. Selecting the first option returns `perform`; the second option or\n * Ctrl+C returns `exit`. Without a TTY there is no menu to read, so it fails\n * open to `exit` and the caller leaves startup untouched.\n */\nexport function promptVersionAction(prompt: VersionPrompt): Promise<'perform' | 'exit'> {\n if (stdin.isTTY !== true) return Promise.resolve('exit')\n\n const labels = [prompt.performLabel, prompt.cancelLabel]\n return new Promise(resolve => {\n let selected = 0\n let drawn = 0\n\n const computeDrawn = (lines: string[]): number => {\n const cols = stdout.columns || 80\n return lines.reduce((total, ln) => {\n if (ln === '') return total + 1\n const width = [...ln].reduce((sum, ch) => sum + (/^[\\u1100-\\u11ff\\u2e80-\\ua4cf\\uf900-\\ufaff\\uff00-\\uffef]/u.test(ch) ? 2 : 1), 0)\n return total + Math.max(1, Math.ceil(width / cols))\n }, 0)\n }\n\n const render = (): void => {\n const lines = [prompt.title, prompt.message, '', ...labels.map((label, index) => index === selected ? `> ${label}` : ` ${label}`)]\n if (drawn > 0) {\n // Move to the real first physical row of the previously drawn block and\n // wipe everything below. Line count must account for terminal wrapping\n // (long dialog text wraps into several physical rows); using the logical\n // line count leaves the top row uncleared, so every redraw stacks a new\n // copy of the title.\n stdout.write(`\\x1b[${drawn}A\\x1b[0J`)\n }\n stdout.write(`${lines.join('\\n')}\\n`)\n drawn = computeDrawn(lines)\n }\n\n const finish = (value: 'perform' | 'exit'): void => {\n if (stdin.isTTY === true) stdin.setRawMode(false)\n stdin.pause()\n stdin.off('keypress', onKeypress)\n stdout.write('\\n')\n resolve(value)\n }\n\n const onKeypress = (_chunk: string, key: Key): void => {\n if (key.ctrl && key.name === 'c') { finish('exit'); return }\n if (key.name === 'up') { selected = selected === 0 ? labels.length - 1 : selected - 1; render(); return }\n if (key.name === 'down') { selected = selected === labels.length - 1 ? 0 : selected + 1; render(); return }\n if (key.name === 'return') finish(selected === 0 ? 'perform' : 'exit')\n }\n\n emitKeypressEvents(stdin)\n stdin.setRawMode(true)\n stdin.resume()\n stdin.on('keypress', onKeypress)\n render()\n })\n}\n","/**\n * The three adapters between pi-ai's auth model and the harness credential\n * plane. Every pi-ai-specific concept stays on this side of them: the harness\n * seams they consume — `ctx.credentials` records and `ctx.authorization` flows —\n * name nothing from this library, so another adapter family can arrive with a\n * different auth model and share the same two seams.\n *\n * @module dsh-llm-pi-ai/auth\n */\n\nimport { homedir } from 'node:os'\nimport { access } from 'node:fs/promises'\nimport { resolve as resolvePath } from 'node:path'\nimport type { AuthContext, Credential, CredentialInfo, CredentialStore } from '@earendil-works/pi-ai'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { defaultProviderAuthContext, InMemoryCredentialStore } from '@earendil-works/pi-ai'\nimport type { PiAiAuthInjection } from './adapter.ts'\nimport {\n credentialKey, credentialKeyId, credentialKeyScope, credentialRef, isCredentialKeySegment, isCredentialRefName,\n} from '@deepseek-ai/dsh-credentials'\nimport type { CredentialKey, CredentialProvider, CredentialRecord } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\nimport { LlmError } from '@deepseek-ai/dsh-llm'\n\n/**\n * The record scope every credential this adapter family stores is written\n * under. It is the plugin's registered name, which is what tells a later\n * reader — a configuration UI, or a second adapter family serving the same\n * provider name — that this plugin owns the format inside the record.\n */\nexport const RECORD_SCOPE = 'llm-pi-ai'\n\n/**\n * The record address for one pi-ai provider id.\n * @param providerId - pi-ai's own provider id, which is also the harness route key.\n * @returns the scoped credential key this adapter family reads and writes.\n */\nexport function recordKeyFor(providerId: string): CredentialKey {\n return credentialKey(RECORD_SCOPE, providerId)\n}\n\n/**\n * The JSON image of one grant payload: plain objects lose their\n * explicitly-undefined members and array entries JSON cannot hold become\n * null, exactly as `JSON.stringify` would render them. pi-ai credentials\n * idiomatically carry optional members as explicit `undefined` (a github.com\n * Copilot grant holds `enterpriseUrl: undefined`), which the credential\n * store's strict validator refuses as unrepresentable. Everything else —\n * non-finite numbers and foreign prototypes included — passes through\n * untouched, so a genuinely unstorable value still fails loud at the store.\n * @param value - the value to render.\n * @returns the value's JSON image.\n */\nfunction jsonImage(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(entry => entry === undefined ? null : jsonImage(entry))\n if (typeof value === 'object' && value !== null && Object.getPrototypeOf(value) === Object.prototype) {\n const image: Record<string, unknown> = {}\n for (const [key, member] of Object.entries(value)) {\n if (member !== undefined) image[key] = jsonImage(member)\n }\n return image\n }\n return value\n}\n\n/**\n * Translate a stored record into the credential pi-ai expects.\n *\n * An `api-key` record is structural on both sides, so it is rebuilt field by\n * field. A `grant` payload is pi-ai's own OAuth credential, stored verbatim:\n * the seam treats it as opaque JSON precisely so a library that owns a token\n * format keeps owning it, refresh fields and all.\n * @param record - the stored record, or undefined when nothing is stored.\n * @returns the pi-ai credential, or undefined for an absent record.\n */\nfunction toPiCredential(record: CredentialRecord | undefined): Credential | undefined {\n if (record === undefined) return undefined\n if (record.kind === 'api-key') {\n return {\n type: 'api_key',\n ...record.key === undefined ? {} : { key: record.key },\n ...record.env === undefined ? {} : { env: { ...record.env } },\n }\n }\n return record.payload as Credential\n}\n\n/**\n * Translate a pi-ai credential into the record to store.\n * @param credential - what a login or refresh produced.\n * @returns the record to commit, in the union the credential seam stores.\n */\nfunction toRecord(credential: Credential): CredentialRecord {\n if (credential.type === 'api_key') {\n return {\n kind: 'api-key',\n ...credential.key === undefined ? {} : { key: credential.key },\n ...credential.env === undefined ? {} : { env: { ...credential.env } },\n }\n }\n return { kind: 'grant', payload: jsonImage(credential) }\n}\n\n/**\n * The credential service, or the failure that names what is missing. Reads\n * answer \"nothing stored\" without a service, because a composition with no\n * credential plane genuinely holds no credential; writes refuse, because a\n * login whose grant silently evaporated would report success and then fail\n * every request.\n * @param ctx - the plugin context.\n * @returns the live service.\n * @throws {LlmError} code `NO_CREDENTIAL_STORE` when none is mounted.\n */\nfunction writableStore(ctx: Context): CredentialProvider {\n const credentials = ctx.get('credentials')\n if (credentials === undefined) {\n throw new LlmError(\n 'llm-pi-ai: this composition mounts no credentials service, so there is nowhere to store the'\n + ' credential a sign-in produces; mount one (dsh-credentials-local) to sign in',\n 'NO_CREDENTIAL_STORE',\n )\n }\n return credentials\n}\n\n/**\n * A pi-ai `CredentialStore` over the harness credential records.\n *\n * pi-ai runs OAuth refresh *inside* `modify()`, so this store's exclusion has\n * to cover a network round trip rather than a file rename — which is why the\n * record write path takes a wait limit of its own rather than the short one a\n * local write would need.\n *\n * pi-ai asks this store about every provider in the collection, hand-declared\n * routes included, and a route key is an arbitrary settings dict key while a\n * record id is not. An id outside the record grammar can never have stored a\n * record, so reads answer \"nothing stored\" and a delete has nothing to remove;\n * only `modify` refuses it, because a write that cannot land must not report\n * that it did.\n * @param ctx - the plugin context carrying the optional `ctx.credentials`.\n * @returns the store to hand `createModels()`.\n */\nexport function credentialStoreFrom(ctx: Context): CredentialStore {\n return {\n async read(providerId) {\n const credentials = ctx.get('credentials')\n if (credentials === undefined) return undefined\n if (!isCredentialKeySegment(providerId)) return undefined\n return toPiCredential(await credentials.readRecord(recordKeyFor(providerId)))\n },\n async list(): Promise<readonly CredentialInfo[]> {\n const stored = await ctx.get('credentials')?.listRecords() ?? []\n const mine: CredentialInfo[] = []\n for (const entry of stored) {\n // Records another plugin owns are not this collection's to report:\n // their payloads are written in a format pi-ai never agreed to.\n if (credentialKeyScope(entry.key) !== RECORD_SCOPE) continue\n mine.push({\n providerId: credentialKeyId(entry.key),\n type: entry.kind === 'api-key' ? 'api_key' : 'oauth',\n })\n }\n return mine\n },\n async modify(providerId, mutate) {\n if (!isCredentialKeySegment(providerId)) {\n throw new LlmError(\n `llm-pi-ai: provider id \"${providerId}\" cannot address a stored credential record (a record id is a`\n + ' lowercase hyphenated identifier); authenticate this route through apiKeyEnv instead of a stored'\n + ' credential',\n 'UNSTORABLE_PROVIDER_ID',\n )\n }\n const stored = await writableStore(ctx).modifyRecord(recordKeyFor(providerId), async (current) => {\n const next = await mutate(toPiCredential(current))\n return next === undefined ? undefined : toRecord(next)\n })\n return toPiCredential(stored)\n },\n // `async` so a missing service reaches the caller as a rejection: pi-ai's\n // store contract is promise-returning, and a synchronous throw would\n // escape the `ModelsError` wrapper every other storage failure gets.\n async delete(providerId) {\n if (!isCredentialKeySegment(providerId)) return\n await writableStore(ctx).deleteRecord(recordKeyFor(providerId))\n },\n }\n}\n\n/**\n * A pi-ai `AuthContext` over the harness credential plane and the host\n * filesystem.\n *\n * `env()` answers from the credential seam first, so a value a deployment\n * stored through the harness is found by a provider's own ambient discovery —\n * without this, that discovery reads only the process environment and a stored\n * `AWS_ACCESS_KEY_ID` is invisible to it. `fileExists()` answers about the host\n * process's own filesystem rather than the workspace `ctx.fs` seam, because the\n * paths it is asked about (`~/.aws/credentials`, application-default\n * credentials) are facts about where this process runs, not about the project\n * under edit.\n * @param ctx - the plugin context carrying the optional `ctx.credentials`.\n * @returns the auth context to hand `createModels()`.\n */\nexport function authContextFrom(ctx: Context): AuthContext {\n return {\n async env(name) {\n // pi-ai asks about arbitrary provider-declared names; one that is not a\n // POSIX identifier can never have been stored as a reference, and asking\n // the seam would throw instead of answering \"not set\".\n if (isCredentialRefName(name)) {\n const credentials = ctx.get('credentials')\n const hit = await credentials?.resolve(credentialRef(name))\n if (hit !== undefined) return hit.value\n }\n return launchEnvironmentOf(ctx).get(name)?.value\n },\n async fileExists(path) {\n const expanded = path.startsWith('~/') || path === '~'\n ? resolvePath(homedir(), path.slice(1).replace(/^\\//, ''))\n : path\n try {\n await access(expanded)\n return true\n } catch {\n // Absent, unreadable, or a broken symlink — every one of which means\n // this ambient credential source cannot be used, which is the only\n // distinction the caller makes.\n return false\n }\n },\n }\n}\n\n/**\n * Create private auth storage for adapters whose explicit source owns every credential.\n * @returns an empty in-memory store and provider auth context, independent of ChatCode CLI login records.\n */\nexport function isolatedPiAiAuth(): PiAiAuthInjection {\n return { credentials: new InMemoryCredentialStore(), authContext: defaultProviderAuthContext() }\n}\n","/**\n * Durable pi-ai replay metadata and assistant-history reconstruction.\n *\n * ChatCode CLI content remains the durable source for text and tool calls. This\n * module stores only the provider-native metadata needed to reconstruct a\n * pi-ai assistant message on a later request.\n *\n * @module dsh-llm-pi-ai/replay\n */\n\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { Message, ModelMessageSource, ReplayEnvelope } from '@deepseek-ai/dsh-llm'\nimport type { Api, AssistantMessage, Usage as PiUsage } from '@earendil-works/pi-ai'\n\n/** Per-block half of the pi-ai replay envelope, one entry per content block. */\nexport type PiAiReplayBlock =\n | { type: 'text'; textSignature?: string }\n | { type: 'reasoning'; thinkingSignature?: string; redacted?: boolean }\n | { type: 'tool-call'; thoughtSignature?: string }\n\n/** Versioned response-level half of the pi-ai replay envelope. */\nexport interface PiAiReplayResponse {\n kind: 'pi-ai'\n version: 2\n api: Api\n provider: string\n model: string\n responseModel?: string\n responseId?: string\n stopReason: AssistantMessage['stopReason']\n}\n\n/** The validated halves of one pi-ai replay envelope. */\ninterface PiAiReplayState {\n response: PiAiReplayResponse\n blocks: PiAiReplayBlock[]\n}\n\n/** Parse tool-call argument JSON; tolerate model malformations with {}. */\nfunction parseArguments(raw: string): Record<string, unknown> {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n // fall through\n }\n return {}\n}\n\n/** Construct the zero usage value required by historical pi-ai messages. */\nfunction emptyPiUsage(): PiUsage {\n return {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n }\n}\n\n/**\n * Project a successful pi-ai response into the minimal durable replay state.\n * The per-block half is index-aligned with the streamed blocks (pi-ai content\n * order), so `BlockAssembler` prunes an entry with its block whenever assembly\n * removes one.\n * @param message - completed native pi-ai assistant response.\n * @returns the versioned lossless-JSON replay projection.\n */\nexport function toPiReplayState(message: AssistantMessage): ReplayEnvelope {\n const response: PiAiReplayResponse = {\n kind: 'pi-ai',\n version: 2,\n api: message.api,\n provider: message.provider,\n model: message.model,\n ...message.responseModel === undefined ? {} : { responseModel: message.responseModel },\n ...message.responseId === undefined ? {} : { responseId: message.responseId },\n stopReason: message.stopReason,\n }\n return {\n response,\n blocks: message.content.map((block): PiAiReplayBlock => {\n switch (block.type) {\n case 'text': return {\n type: 'text',\n ...block.textSignature === undefined ? {} : { textSignature: block.textSignature },\n }\n case 'thinking': return {\n type: 'reasoning',\n ...block.thinkingSignature === undefined ? {} : { thinkingSignature: block.thinkingSignature },\n ...block.redacted === undefined ? {} : { redacted: block.redacted },\n }\n case 'toolCall': return {\n type: 'tool-call',\n ...block.thoughtSignature === undefined ? {} : { thoughtSignature: block.thoughtSignature },\n }\n }\n }),\n }\n}\n\nfunction invalidReplay(message: string): never {\n throw new LlmError(`invalid pi-ai replay state: ${message}`, 'INVALID_REPLAY_STATE')\n}\n\n/** Validate the durable adapter-private envelope before it reaches pi-ai. */\nfunction readReplayState(value: unknown): PiAiReplayState {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return invalidReplay('expected a replay envelope')\n const envelope = value as Record<string, unknown>\n const rawResponse = envelope['response']\n if (typeof rawResponse !== 'object' || rawResponse === null || Array.isArray(rawResponse)) return invalidReplay('expected a response object')\n const response = rawResponse as Record<string, unknown>\n if (response['kind'] !== 'pi-ai') return invalidReplay('unknown state kind')\n if (response['version'] !== 2) return invalidReplay(`unsupported version ${String(response['version'])}`)\n for (const key of ['api', 'provider', 'model'] as const) {\n if (typeof response[key] !== 'string' || response[key].length === 0) return invalidReplay(`${key} must be a non-empty string`)\n }\n if (!['stop', 'length', 'toolUse', 'error', 'aborted'].includes(String(response['stopReason']))) {\n return invalidReplay('unknown stopReason')\n }\n if (response['responseModel'] !== undefined && typeof response['responseModel'] !== 'string') return invalidReplay('responseModel must be a string')\n if (response['responseId'] !== undefined && typeof response['responseId'] !== 'string') return invalidReplay('responseId must be a string')\n const blocks = envelope['blocks']\n if (!Array.isArray(blocks)) return invalidReplay('blocks must be an array')\n for (const [index, value] of blocks.entries()) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return invalidReplay(`block ${index} must be an object`)\n const block = value as Record<string, unknown>\n if (!['text', 'reasoning', 'tool-call'].includes(String(block['type']))) return invalidReplay(`block ${index} has an unknown type`)\n for (const signature of ['textSignature', 'thinkingSignature', 'thoughtSignature'] as const) {\n if (block[signature] !== undefined && typeof block[signature] !== 'string') return invalidReplay(`block ${index} ${signature} must be a string`)\n }\n if (block['redacted'] !== undefined && typeof block['redacted'] !== 'boolean') return invalidReplay(`block ${index} redacted must be boolean`)\n }\n return {\n response: response as unknown as PiAiReplayResponse,\n blocks: blocks as PiAiReplayBlock[],\n }\n}\n\n/** Convert provider-neutral blocks without trusting them as same-model replay. */\nfunction foreignAssistant(message: Message): AssistantMessage {\n const source = message.source.kind === 'model' ? message.source : undefined\n const content: AssistantMessage['content'] = []\n for (const block of message.content) {\n switch (block.type) {\n case 'text': content.push({ type: 'text', text: block.text }); break\n case 'reasoning': content.push({ type: 'thinking', thinking: block.text }); break\n case 'tool-call': content.push({\n type: 'toolCall',\n id: block.id,\n name: block.name,\n arguments: parseArguments(block.arguments),\n }); break\n case 'image':\n throw new LlmError('pi-ai chat history cannot represent structured assistant image output', 'UNSUPPORTED_CONTENT')\n default:\n // plugin-added block types are not representable in pi-ai.\n break\n }\n }\n return {\n role: 'assistant',\n content,\n // Deliberately never equals a catalog API: absent replay state is foreign\n // even if source names the same provider/model as this request.\n api: 'dsh-foreign',\n provider: source?.provider ?? 'dsh-foreign',\n model: source?.model ?? 'dsh-foreign',\n usage: emptyPiUsage(),\n stopReason: content.some(piece => piece.type === 'toolCall') ? 'toolUse' : 'stop',\n timestamp: 0,\n }\n}\n\n/** Recombine durable ChatCode CLI content with validated pi-ai replay metadata. */\nfunction replayedAssistant(message: Message, source: ModelMessageSource, rawState: unknown): AssistantMessage {\n const state = readReplayState(rawState)\n if (state.response.provider !== source.provider) return invalidReplay('provider does not match assistant source')\n if (state.response.model !== source.model) return invalidReplay('model does not match assistant source')\n if (state.blocks.length !== message.content.length) return invalidReplay('block count does not match assistant content')\n const content: AssistantMessage['content'] = message.content.map((block, index) => {\n const replay = state.blocks[index]\n if (replay === undefined || replay.type !== block.type) return invalidReplay(`block ${index} does not match assistant content`)\n switch (block.type) {\n case 'text': return {\n type: 'text',\n text: block.text,\n ...replay.type === 'text' && replay.textSignature !== undefined ? { textSignature: replay.textSignature } : {},\n }\n case 'reasoning': return {\n type: 'thinking',\n thinking: block.text,\n ...replay.type === 'reasoning' && replay.thinkingSignature !== undefined ? { thinkingSignature: replay.thinkingSignature } : {},\n ...replay.type === 'reasoning' && replay.redacted !== undefined ? { redacted: replay.redacted } : {},\n }\n case 'tool-call': return {\n type: 'toolCall',\n id: block.id,\n name: block.name,\n arguments: parseArguments(block.arguments),\n ...replay.type === 'tool-call' && replay.thoughtSignature !== undefined ? { thoughtSignature: replay.thoughtSignature } : {},\n }\n /* v8 ignore next -- readReplayState rejects unknown replay tags, so an equal plugin-added ChatCode CLI tag cannot reach this switch */\n default: return invalidReplay(`block ${index} has an unsupported ChatCode CLI type`)\n }\n })\n return {\n role: 'assistant',\n content,\n api: state.response.api,\n provider: state.response.provider,\n model: state.response.model,\n ...state.response.responseModel === undefined ? {} : { responseModel: state.response.responseModel },\n ...state.response.responseId === undefined ? {} : { responseId: state.response.responseId },\n usage: emptyPiUsage(),\n stopReason: state.response.stopReason,\n timestamp: 0,\n }\n}\n\n/**\n * Convert one durable ChatCode CLI assistant message into pi-ai history.\n *\n * Durable content is the authoritative record; replay metadata only restores\n * native fidelity (ids, signatures). A replay state this build cannot use —\n * another adapter's kind, another version, a malformed value, or metadata that\n * no longer matches the content — therefore degrades the one message to\n * provider-neutral history instead of failing the request.\n * @param message - assistant content with required source and optional adapter-owned replay metadata.\n * @param onDegrade - called with the diagnostic reason when an unusable replay\n * state falls back to provider-neutral conversion.\n * @returns a native pi-ai assistant message reconstructed from durable content.\n */\nexport function toPiAssistant(message: Message, onDegrade?: (reason: string) => void): AssistantMessage {\n const source = message.source\n if (source.kind !== 'model' || source.replayState === undefined) return foreignAssistant(message)\n try {\n return replayedAssistant(message, source, source.replayState)\n } catch (error: unknown) {\n /* v8 ignore next -- replayedAssistant throws only INVALID_REPLAY_STATE LlmErrors; the\n guard keeps a future non-replay failure loud instead of silently degrading it */\n if (!(error instanceof LlmError) || error.code !== 'INVALID_REPLAY_STATE') throw error\n onDegrade?.(error.message)\n return foreignAssistant(message)\n }\n}\n","/**\n * Materialization of one provider route's model catalog. The installed pi-ai\n * catalog supplies defaults keyed by model id, and a profile's own model\n * entries override them field by field, so a route naming a catalog provider\n * stays configuration-free while a route pi-ai has never heard of is fully\n * describable from `settings.yaml`.\n *\n * Every pi-ai `Model` field the harness cannot default is required here rather\n * than at request time: an unserviceable route fails while its configuration is\n * being resolved, which is the earliest point that can name the offending key.\n *\n * @module dsh-llm-pi-ai/catalog\n */\n\nimport { builtinProviders, getBuiltinModels, getBuiltinProviders } from '@earendil-works/pi-ai/providers/all'\nimport type { BuiltinProvider } from '@earendil-works/pi-ai/providers/all'\nimport type {\n AnthropicMessagesCompat,\n Api,\n BedrockCompat,\n ChatTemplateKwargValue,\n KnownApi,\n Model,\n ModelCost,\n ModelThinkingLevel,\n OpenAICompletionsCompat,\n OpenAIResponsesCompat,\n Provider,\n ThinkingLevelMap,\n} from '@earendil-works/pi-ai'\n\n/**\n * Pricing for a model the installed catalog does not describe. The harness\n * never reads pi-ai's cost metadata — `replay.ts` zeroes it and no consumer\n * reports spend — so this is the absence of a fact, not a configurable rate.\n */\nconst NO_COST: ModelCost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }\n\n/** One request modality a pi-ai model may accept. */\nexport type PiAiModality = Model<Api>['input'][number]\n\n/**\n * Every pi-ai request modality. The `Record` key type is a drift gate: a pi-ai\n * upgrade that adds or removes a modality fails compilation here naming the\n * drifted key, instead of silently narrowing what a profile may declare.\n */\nconst MODALITY_GATE: Record<PiAiModality, true> = {\n text: true,\n image: true,\n}\n\n/** Every request modality a profile may declare. */\nexport const MODALITIES = Object.keys(MODALITY_GATE) as readonly PiAiModality[]\n\n/**\n * One entry's modality list, or `undefined` when it states no answer. Absent\n * and empty mean the same thing — `[]` describes a model that accepts nothing\n * and could serve no request — which is what makes an entry naming a catalog\n * model without declaring modalities keep the catalog's, since the config\n * schema materializes `[]` for an absent array.\n * @param configured - the list a `models` or `modelOverrides` entry supplied.\n * @returns the declared modalities, or `undefined` to ask the next level.\n */\nfunction declaredInput(configured: readonly PiAiModality[] | undefined): Model<Api>['input'] | undefined {\n return configured === undefined || configured.length === 0 ? undefined : [...configured]\n}\n\n/**\n * Every pi-ai thinking level, in pi-ai's canonical escalation order. The\n * `Record` key type is a drift gate: a pi-ai upgrade that adds or removes a\n * level fails compilation here naming the drifted key, instead of silently\n * narrowing what a profile may declare.\n */\nconst THINKING_LEVEL_GATE: Record<ModelThinkingLevel, true> = {\n off: true,\n minimal: true,\n low: true,\n medium: true,\n high: true,\n xhigh: true,\n max: true,\n}\n\n/** Every pi-ai thinking level a profile may declare, in escalation order. */\nexport const THINKING_LEVELS = Object.keys(THINKING_LEVEL_GATE) as readonly ModelThinkingLevel[]\n\n/** One reasoning-dispatch wire format a profile may name. */\nexport type PiAiThinkingFormat = NonNullable<OpenAICompletionsCompat['thinkingFormat']>\n\n/**\n * The nameable reasoning-dispatch formats, most-reached first. The `Record`\n * key type is a drift gate: an upstream format addition fails compilation\n * here until it is named, so the offer never silently lags the upstream set.\n * The two `chat-template` variants are nameable because\n * {@link PiAiCompatProfile.chatTemplateKwargs} carries their kwargs;\n * `baseten` is nameable because {@link PiAiCompatProfile.chatTemplateArgs}\n * carries its arguments.\n */\nconst THINKING_FORMAT_GATE: Record<PiAiThinkingFormat, true> = {\n 'openai': true,\n 'deepseek': true,\n 'openrouter': true,\n 'together': true,\n 'baseten': true,\n 'zai': true,\n 'qwen': true,\n 'chat-template': true,\n 'qwen-chat-template': true,\n 'string-thinking': true,\n 'ant-ling': true,\n}\n\n/** Reasoning-dispatch wire formats a profile may name, most-reached first. */\nexport const SUPPORTED_THINKING_FORMATS = Object.keys(THINKING_FORMAT_GATE) as readonly PiAiThinkingFormat[]\n\n/** The output-cap field spellings pi-ai accepts. */\nexport type PiAiMaxTokensField = NonNullable<OpenAICompletionsCompat['maxTokensField']>\n\n/** Drift gate over {@link PiAiMaxTokensField}; an upstream spelling added here fails compilation until named. */\nconst MAX_TOKENS_FIELD_GATE: Record<PiAiMaxTokensField, true> = {\n max_completion_tokens: true,\n max_tokens: true,\n}\n\n/** The output-cap field spellings a profile may name. */\nexport const MAX_TOKENS_FIELDS = Object.keys(MAX_TOKENS_FIELD_GATE) as readonly PiAiMaxTokensField[]\n\n/** The prompt-cache marker conventions pi-ai accepts. */\nexport type PiAiCacheControlFormat = NonNullable<OpenAICompletionsCompat['cacheControlFormat']>\n\n/** Drift gate over {@link PiAiCacheControlFormat}; a new upstream convention fails compilation until named. */\nconst CACHE_CONTROL_FORMAT_GATE: Record<PiAiCacheControlFormat, true> = {\n anthropic: true,\n}\n\n/** The prompt-cache marker conventions a profile may name. */\nexport const CACHE_CONTROL_FORMATS = Object.keys(CACHE_CONTROL_FORMAT_GATE) as readonly PiAiCacheControlFormat[]\n\n/** The request-state placeholders a `chat_template_kwargs` value may name. */\nexport type PiAiChatTemplateVar = Extract<ChatTemplateKwargValue, { $var: string }>['$var']\n\n/** Drift gate over {@link PiAiChatTemplateVar}; a new upstream placeholder fails compilation until named. */\nconst CHAT_TEMPLATE_VAR_GATE: Record<PiAiChatTemplateVar, true> = {\n 'thinking.enabled': true,\n 'thinking.effort': true,\n}\n\n/** The request-state placeholders a profile may name. */\nexport const CHAT_TEMPLATE_VARS = Object.keys(CHAT_TEMPLATE_VAR_GATE) as readonly PiAiChatTemplateVar[]\n\nlet providerIndex: Map<string, Provider> | undefined\n\n/**\n * Installed catalog providers by id, constructed once. Each entry owns the API\n * implementations for its own models, which is why a catalog route reuses this\n * provider instead of being rebuilt from parts.\n * @returns the catalog provider index.\n */\nfunction catalogProviders(): Map<string, Provider> {\n providerIndex ??= new Map(builtinProviders().map(provider => [provider.id, provider]))\n return providerIndex\n}\n\n/**\n * The installed catalog provider for one route, when pi-ai ships one.\n * @param provider - provider route key.\n * @returns the catalog provider, or `undefined` for a route pi-ai does not ship.\n */\nexport function catalogProvider(provider: string): Provider | undefined {\n return catalogProviders().get(provider)\n}\n\n/**\n * Every provider route the installed pi-ai catalog ships.\n * @returns the catalog provider ids.\n */\nexport function catalogProviderIds(): readonly string[] {\n return getBuiltinProviders()\n}\n\n/**\n * The installed catalog models for one route, indexed by model id.\n * @param provider - provider route key.\n * @returns catalog models by id; empty for a route pi-ai does not ship.\n */\nexport function catalogModels(provider: string): Map<string, Model<Api>> {\n if (!catalogProviders().has(provider)) return new Map()\n const models = getBuiltinModels(provider as BuiltinProvider) as Model<Api>[]\n return new Map(models.map(model => [model.id, model]))\n}\n\n/**\n * Selectable reasoning efforts for one model: each key is a level the model\n * offers (and selectors show), and its value is the wire spelling dispatch\n * sends for it. `off` alone may leave its value empty — \"supported, send\n * nothing\" — because for most providers not thinking is the parameter's\n * absence; every other declared level must name a wire value. A level absent\n * from the dict is not offered.\n */\nexport type PiAiReasoningEfforts = Partial<Record<ModelThinkingLevel, string | null>>\n\n/**\n * Whether one pi-ai compat field is configurable on a profile.\n *\n * `withhold` is the disposition for a field pi-ai's installed catalog already\n * sets for a named vendor. Reaching for one of those on a hand-declared route\n * means configuring a provider that should have been named as a catalog route\n * instead, where the installed entry carries the right value already.\n */\ntype CompatDisposition = 'offer' | 'withhold'\n\n/**\n * Disposition of every `OpenAICompletionsCompat` field. The `Record` key type\n * is a drift gate: a pi-ai upgrade that adds a field fails compilation here\n * until it is classified, so the offer never silently lags the upstream set.\n */\nconst COMPLETIONS_COMPAT_GATE = {\n supportsStore: 'offer',\n supportsDeveloperRole: 'offer',\n supportsReasoningEffort: 'offer',\n supportsUsageInStreaming: 'offer',\n supportsFinishReason: 'offer',\n maxTokensField: 'offer',\n requiresToolResultName: 'offer',\n requiresAssistantAfterToolResult: 'offer',\n requiresThinkingAsText: 'offer',\n requiresReasoningContentOnAssistantMessages: 'offer',\n thinkingFormat: 'offer',\n chatTemplateKwargs: 'offer',\n chatTemplateArgs: 'offer',\n supportsThinkingTokenBudget: 'offer',\n supportsStrictMode: 'offer',\n cacheControlFormat: 'offer',\n supportsLongCacheRetention: 'offer',\n openRouterRouting: 'withhold',\n vercelGatewayRouting: 'withhold',\n zaiToolStream: 'withhold',\n supportsOpenAIGrammarTools: 'withhold',\n sendSessionAffinityHeaders: 'withhold',\n deferredToolsMode: 'withhold',\n sessionAffinityFormat: 'withhold',\n} as const satisfies Record<keyof OpenAICompletionsCompat, CompatDisposition>\n\n/** Disposition of every `OpenAIResponsesCompat` field; a drift gate like the one above. */\nconst RESPONSES_COMPAT_GATE = {\n supportsDeveloperRole: 'offer',\n supportsStrictMode: 'offer',\n supportsLongCacheRetention: 'offer',\n sessionAffinityFormat: 'withhold',\n supportsOpenAIGrammarTools: 'withhold',\n supportsAdditionalTools: 'withhold',\n supportsToolSearch: 'withhold',\n supportsExplicitPromptCacheMode: 'withhold',\n} as const satisfies Record<keyof OpenAIResponsesCompat, CompatDisposition>\n\n/** Disposition of every `AnthropicMessagesCompat` field; a drift gate like the one above. */\nconst ANTHROPIC_COMPAT_GATE = {\n supportsEagerToolInputStreaming: 'offer',\n supportsLongCacheRetention: 'offer',\n supportsCacheControlOnTools: 'offer',\n supportsTemperature: 'offer',\n forceAdaptiveThinking: 'offer',\n allowEmptySignature: 'offer',\n supportsStrictTools: 'offer',\n sendSessionAffinityHeaders: 'withhold',\n supportsToolReferences: 'withhold',\n} as const satisfies Record<keyof AnthropicMessagesCompat, CompatDisposition>\n\n/** Disposition of every `BedrockCompat` field; a drift gate like the one above. */\nconst BEDROCK_COMPAT_GATE = {\n supportsStrictMode: 'offer',\n} as const satisfies Record<keyof BedrockCompat, CompatDisposition>\n\n/**\n * Every wire protocol pi-ai gives a compat type. Derived from `Model.compat`'s\n * own conditional rather than listed by hand, so a pi-ai release that gives a\n * further protocol a compat type fails the {@link COMPAT_GATES} entry list\n * until someone classifies its fields. A protocol pi-ai gives no compat type\n * resolves away here and takes no configured compat at all.\n */\ntype ApiWithCompat = { [K in KnownApi]: NonNullable<Model<K>['compat']> extends never ? never : K }[KnownApi]\n\n/**\n * The compat gate of every wire protocol a profile may configure.\n *\n * Keyed by protocol, but grouped by pi-ai's compat *type*: the three Responses\n * protocols share `OpenAIResponsesCompat`, so a switch settable on one is\n * settable on all three. Keying by protocol alone would refuse\n * `azure-openai-responses` and `openai-codex-responses` the fields their own\n * models declare.\n */\nconst COMPAT_GATES: Readonly<Record<ApiWithCompat, Readonly<Record<string, CompatDisposition>>>> = {\n 'openai-completions': COMPLETIONS_COMPAT_GATE,\n 'openai-responses': RESPONSES_COMPAT_GATE,\n 'azure-openai-responses': RESPONSES_COMPAT_GATE,\n 'openai-codex-responses': RESPONSES_COMPAT_GATE,\n 'anthropic-messages': ANTHROPIC_COMPAT_GATE,\n 'bedrock-converse-stream': BEDROCK_COMPAT_GATE,\n}\n\n/**\n * The compat gate of one resolved protocol. A `string` lookup rather than a\n * keyed read: a route's `api` is configuration, so it may name a protocol\n * pi-ai gives no compat type — or none at all.\n * @param api - resolved wire protocol.\n * @returns that protocol's field gate, or `undefined` when it takes no compat.\n */\nfunction compatGate(api: string): Readonly<Record<string, CompatDisposition>> | undefined {\n return (COMPAT_GATES as Readonly<Record<string, Readonly<Record<string, CompatDisposition>>>>)[api]\n}\n\n/** The field names one gate offers. */\ntype OfferedIn<G> = { [K in keyof G]: G[K] extends 'offer' ? K : never }[keyof G]\n\n/** Every compat field name a profile may set, on whichever protocol takes it. */\ntype OfferedCompatField =\n | OfferedIn<typeof COMPLETIONS_COMPAT_GATE>\n | OfferedIn<typeof RESPONSES_COMPAT_GATE>\n | OfferedIn<typeof ANTHROPIC_COMPAT_GATE>\n | OfferedIn<typeof BEDROCK_COMPAT_GATE>\n\n/**\n * pi-ai wire-compatibility switches, set on the route (its models' default) or\n * per model (winning over the route, field by field).\n *\n * pi-ai decides each of these from the provider id and baseURL when no layer\n * sets it, and a private gateway's URL says nothing: for an endpoint it does\n * not recognize the detection answers as though it were OpenAI itself, which\n * is wrong for most OpenAI-compatible gateways. So every field here is one a\n * deployment must be able to state because nothing can infer it, while the\n * fields pi-ai's catalog sets for a named vendor stay withheld.\n *\n * A field belongs to the protocols whose upstream compat type declares it: a\n * model-level switch its protocol does not take fails resolution, and a\n * route-level one skips past models it cannot fit. \"The three Responses\n * protocols\" below means `openai-responses`, `azure-openai-responses`, and\n * `openai-codex-responses`, which pi-ai gives one shared compat type, so a\n * switch settable on one is settable on all three.\n */\nexport interface PiAiCompatProfile {\n /** Whether the endpoint accepts `store`; `openai-completions`. */\n supportsStore?: boolean\n /**\n * Whether the endpoint accepts the `developer` role for the system prompt,\n * which pi-ai sends only to a reasoning model; `false` keeps `system`.\n * `openai-completions` and the three Responses protocols.\n */\n supportsDeveloperRole?: boolean\n /** Whether the endpoint accepts `reasoning_effort`; `openai-completions`. */\n supportsReasoningEffort?: boolean\n /** Whether the endpoint accepts `stream_options: {include_usage: true}`; `openai-completions`. */\n supportsUsageInStreaming?: boolean\n /**\n * Whether streams include `finish_reason`; `false` lets pi-ai infer the\n * terminal reason when the stream ends; `openai-completions`.\n */\n supportsFinishReason?: boolean\n /** Which output-cap field the endpoint reads; `openai-completions`. */\n maxTokensField?: NonNullable<OpenAICompletionsCompat['maxTokensField']>\n /** Whether tool results must carry `name`; `openai-completions`. */\n requiresToolResultName?: boolean\n /** Whether a user message after tool results needs an assistant message between; `openai-completions`. */\n requiresAssistantAfterToolResult?: boolean\n /** Whether thinking blocks must travel as text in `<thinking>` delimiters; `openai-completions`. */\n requiresThinkingAsText?: boolean\n /** Whether replayed assistant messages need an empty `reasoning_content` while reasoning is on; `openai-completions`. */\n requiresReasoningContentOnAssistantMessages?: boolean\n /** Reasoning parameter format the endpoint expects; `openai-completions`. */\n thinkingFormat?: PiAiThinkingFormat\n /**\n * Kwargs sent as `chat_template_kwargs`, which pi-ai reads only under the\n * two `chat-template` thinking formats; `openai-completions`. Nothing checks\n * that pairing: the format in force may come from the installed catalog\n * entry or from pi-ai's own baseURL detection, neither of which resolution\n * can read, so kwargs set beside another format are sent nowhere.\n */\n chatTemplateKwargs?: NonNullable<OpenAICompletionsCompat['chatTemplateKwargs']>\n /** Arguments sent as `chat_template_args` under the `baseten` thinking format; `openai-completions`. */\n chatTemplateArgs?: NonNullable<OpenAICompletionsCompat['chatTemplateArgs']>\n /** Whether the endpoint accepts `thinking_token_budget` to cap vLLM reasoning; `openai-completions`. */\n supportsThinkingTokenBudget?: boolean\n /**\n * Whether the endpoint accepts `strict` in tool definitions;\n * `openai-completions`, the three Responses protocols, `bedrock-converse-stream`.\n */\n supportsStrictMode?: boolean\n /** Prompt-cache marker convention; `openai-completions`. */\n cacheControlFormat?: NonNullable<OpenAICompletionsCompat['cacheControlFormat']>\n /**\n * Whether the endpoint accepts long prompt-cache retention;\n * `openai-completions`, the three Responses protocols, `anthropic-messages`.\n */\n supportsLongCacheRetention?: boolean\n /** Whether the endpoint accepts per-tool `eager_input_streaming`; `anthropic-messages`. */\n supportsEagerToolInputStreaming?: boolean\n /** Whether the endpoint accepts `cache_control` on tool definitions; `anthropic-messages`. */\n supportsCacheControlOnTools?: boolean\n /** Whether the endpoint accepts the `temperature` request field; `anthropic-messages`. */\n supportsTemperature?: boolean\n /** Whether to force adaptive thinking regardless of model id; `anthropic-messages`. */\n forceAdaptiveThinking?: boolean\n /** Whether to replay an empty thinking signature instead of converting thinking to text; `anthropic-messages`. */\n allowEmptySignature?: boolean\n /** Whether the endpoint accepts Anthropic strict tool schemas; `anthropic-messages`. */\n supportsStrictTools?: boolean\n}\n\n/** Compile-time constraint that `T` is `never`. */\ntype AssertNever<T extends never> = T\n\n/**\n * Proof that every documented field is one a gate offers. A field the profile\n * declares past the gates fails compilation with its own name in the error.\n */\nexport type EveryProfileFieldIsOffered = AssertNever<Exclude<keyof PiAiCompatProfile, OfferedCompatField>>\n\n/**\n * Proof that every offered field is documented. A gate entry flipped to\n * `offer` without a profile field fails compilation with its own name in the\n * error, which is the half a schema alone cannot catch.\n */\nexport type EveryOfferedFieldIsDocumented = AssertNever<Exclude<OfferedCompatField, keyof PiAiCompatProfile>>\n\n/** Compile-time constraint that `T` is `true`. */\ntype AssertTrue<T extends true> = T\n\n/** Every compat type a gate classifies, merged so one `Pick` reaches all offered fields. */\ntype UpstreamCompat = OpenAICompletionsCompat & OpenAIResponsesCompat & AnthropicMessagesCompat & BedrockCompat\n\n/**\n * Proof that each documented field carries its upstream type, not a hand-copied\n * restatement of it. The name gates above pin *which* fields exist; this pins\n * their types, in both directions because each catches a different drift. A\n * profile field wider than upstream accepts a value the provider rejects, and\n * `resolveModelCompat`'s cast to `ModelCompat` would hide it; a narrower one\n * refuses a value the provider accepts, which is how an upgrade that widens a\n * union would otherwise leave configuration silently behind.\n */\nexport type EveryProfileFieldMatchesUpstream = AssertTrue<\n PiAiCompatProfile extends Partial<Pick<UpstreamCompat, OfferedCompatField>>\n ? Partial<Pick<UpstreamCompat, OfferedCompatField>> extends PiAiCompatProfile ? true : false\n : false\n>\n\n/**\n * The compat entries a profile actually set.\n *\n * schemastery materializes an absent dict as `{}` — the behavior\n * `reasoningEfforts` works around with a union — so every parsed profile\n * carries both template-argument keys whether or not anyone wrote them. An\n * empty one states nothing here: it would send no arguments, which is exactly\n * what leaving the field out does, so absent and empty are the same request\n * and neither may make a route look like it configured a switch. A valueless\n * scalar is the other thing schemastery lets through, and it is refused by\n * {@link assertOfferedCompatFields} before this runs rather than filtered.\n * @param compat - the configured switches, when any.\n * @returns the entries carrying a value, in declaration order.\n */\nfunction configuredCompatEntries(compat: PiAiCompatProfile | undefined): readonly (readonly [string, unknown])[] {\n return Object.entries(compat ?? {}).flatMap(([field, value]) => {\n const empty = typeof value === 'object' && value !== null && !Array.isArray(value)\n && Object.keys(value as object).length === 0\n return empty ? [] : [[field, value] as const]\n })\n}\n\n/**\n * The protocols offering one compat field, in {@link COMPAT_GATES} order.\n * @param field - configured compat field name.\n * @returns the protocols whose compat takes it; empty when none does, which\n * is either a withheld field or a name no upstream compat type declares.\n */\nfunction compatProtocols(field: string): readonly string[] {\n return Object.entries(COMPAT_GATES).flatMap(([api, gate]) => gate[field] === 'offer' ? [api] : [])\n}\n\n/**\n * The compat fields one protocol offers, for a diagnostic that has to show\n * what was available instead of the name that missed.\n * @param api - wire protocol.\n * @returns the offered field names, or an empty list for a protocol taking no compat.\n */\nfunction offeredCompatFields(api: string): readonly string[] {\n return Object.entries(compatGate(api) ?? {}).flatMap(([field, disposition]) => disposition === 'offer' ? [field] : [])\n}\n\n/**\n * Every offered field name, deduplicated, for the one diagnostic that cannot\n * narrow by protocol: the vocabulary check runs before any protocol resolves,\n * which is what lets it refuse a misspelling on a route whose models would\n * never have reached the protocol that declares the intended field.\n * @returns the offered field names across every protocol, in gate order.\n */\nfunction allOfferedCompatFields(): readonly string[] {\n const fields = new Set<string>()\n for (const api of Object.keys(COMPAT_GATES)) {\n for (const field of offeredCompatFields(api)) fields.add(field)\n }\n return [...fields]\n}\n\n/**\n * Reject a compat key no protocol offers. Runs before any protocol is\n * resolved, so a withheld field or a misspelling fails even on a route whose\n * models never reach the protocol that would have taken it — the alternative\n * being the silent drop that let an unreadable switch look applied.\n * @param provider - provider route key, for diagnostics.\n * @param site - the configuration site, for diagnostics.\n * @param compat - the configured switches, when any.\n * @throws Error naming the offending key.\n */\nfunction assertOfferedCompatFields(\n provider: string,\n site: string,\n compat: PiAiCompatProfile | undefined,\n): void {\n // Every key, not only the ones carrying a value: a withheld or undeclared\n // name is never in the schema, so schemastery cannot have materialized it —\n // whatever its value, a person wrote it and expects it to do something.\n for (const [field, value] of Object.entries(compat ?? {})) {\n // The name is judged before the value, so a withheld or misspelled key\n // written bare is refused for being that name rather than for being empty:\n // the other order sends someone to supply a value the key would be refused\n // with anyway.\n if (compatProtocols(field).length === 0) {\n const declared = Object.values(COMPAT_GATES).some(gate => gate[field] !== undefined)\n if (declared) {\n invalid(provider, `${site} sets compat \"${field}\", which is not configurable here: pi-ai's installed`\n + ' catalog sets it for the vendors that need it, so name that provider as the route instead')\n }\n invalid(provider, `${site} sets compat \"${field}\", which no wire protocol declares; the configurable`\n + ` switches are ${allOfferedCompatFields().join(', ')}`)\n }\n // A valueless key (`supportsDeveloperRole:`) survives schemastery, which\n // passes nullable data through before any member schema runs — the same\n // behavior `reasoningEfforts` documents — and a `cordis.yml` entry may\n // reach the same state through `!!js undefined`. Either way the key is\n // kept, so carrying it forward writes nothing over whatever the next layer\n // resolved, leaving pi-ai's `??` at its baseURL detection: the \"written but\n // not applied\" outcome this surface exists to refuse.\n if (value == null) {\n invalid(provider, `${site} sets compat \"${field}\" with no value; give it one, or remove the key to`\n + ' leave the field to the next layer — the installed catalog entry, then pi-ai\\'s own detection')\n }\n }\n}\n\n/** One configured model entry: an id plus the catalog fields it overrides. */\nexport interface PiAiModelProfile {\n /** Model id sent to the provider and accepted by {@link GenerateOptions.model}. */\n id: string\n /** Display name for selectors; defaults to the catalog name, then the id. */\n name?: string\n /** Maximum combined request and response context in tokens. */\n contextWindow?: number\n /**\n * Maximum output tokens. Configuring one also makes it this model's\n * per-request default; a value inherited from the installed catalog, or the\n * route's fallback, is the model's capability and never becomes a request\n * default on its own.\n */\n maxTokens?: number\n /**\n * Request modalities this model accepts. Absent — or empty, which describes\n * a model that accepts nothing and so states no answer either — keeps the\n * installed catalog entry's modalities, then the route's `defaultInput`.\n * Declaring images is what makes a hand-declared vision model usable, and\n * declaring text alone corrects a catalog model whose gateway does not serve\n * what the catalog records. This is a claim about the endpoint, not a check\n * of it: nothing interrogates a gateway for what it accepts, so a model\n * claiming images its endpoint refuses is refused by the provider instead,\n * mid-turn.\n */\n input?: PiAiModality[]\n /**\n * Selectable reasoning efforts. Absent inherits the installed catalog\n * entry's capability (a hand-declared model has none and does not reason);\n * `false` declares a non-reasoning model, which is how a profile strips\n * reasoning from a catalog model its gateway cannot serve; a non-empty dict\n * declares the offered levels and their wire spellings.\n */\n reasoningEfforts?: false | PiAiReasoningEfforts\n /** pi-ai wire-compatibility switches for this model, winning over the route's per field; one its protocol does not declare is refused. */\n compat?: PiAiCompatProfile\n}\n\n/**\n * Customization of one installed catalog model, keyed by its id in the\n * route's `modelOverrides` dict — the same fields a `models` entry may set,\n * with the id living in the key. Unlike a `models` list, overrides leave the\n * rest of the catalog serving untouched, which is what makes \"correct one\n * model, keep the other thirty-seven\" a three-line edit.\n */\nexport type PiAiModelOverride = Omit<PiAiModelProfile, 'id'>\n\n/** The route-level facts model materialization reads. */\nexport interface RouteCatalogRequest {\n /** Provider route key, stamped onto every materialized model. */\n provider: string\n /** Wire protocol override; absent defers to each catalog model's own API. */\n api?: string\n /** Endpoint override; absent defers to the catalog model, then the catalog provider. */\n baseURL?: string\n /** Configured catalog; absent means the whole installed catalog for this route. */\n models?: readonly PiAiModelProfile[]\n /** Installed-catalog customizations by model id; only meaningful while `models` is absent. */\n modelOverrides?: Readonly<Record<string, PiAiModelOverride>>\n /** Route-level wire-compatibility switches, landing on each model whose protocol declares them; entries override per field. */\n compat?: PiAiCompatProfile\n /** Context capacity for a model neither the entry nor the catalog sizes. */\n defaultContextWindow: number\n /** Output capability for a model neither the entry nor the catalog sizes. */\n defaultMaxTokens: number\n /** Modalities for a model neither the entry nor the catalog declares. */\n defaultInput: Model<Api>['input']\n}\n\n/** Report a route the deployment cannot serve, naming the settings key at fault. */\nfunction invalid(provider: string, detail: string): never {\n throw new Error(`llm-pi-ai: provider \"${provider}\" ${detail}`)\n}\n\n/**\n * The one wire protocol a catalog route's shipped models agree on. This is what\n * lets a deployment add a model the installed catalog has not caught up with —\n * a provider's newest release — without restating the protocol its siblings\n * already use. A route whose shipped models disagree (an OpenAI-style catalog\n * spanning Responses and Chat Completions) has no such answer, so a model it\n * does not describe must name its protocol at the route.\n */\nfunction sharedCatalogApi(defaults: ReadonlyMap<string, Model<Api>>): string | undefined {\n const apis = new Set<string>()\n for (const model of defaults.values()) apis.add(model.api)\n return apis.size === 1 ? [...apis][0] : undefined\n}\n\n/** The reasoning fields one materialized model carries. */\ninterface ModelReasoning {\n /** Whether the model reasons at all; `false` makes pi-ai ignore the map. */\n reasoning: boolean\n /** The map dispatch reads; absent only when the installed entry's (or none) applies. */\n thinkingLevelMap?: ThinkingLevelMap\n}\n\n/**\n * Resolve one model's reasoning capability from its declared efforts.\n *\n * A declared dict translates to pi-ai's `thinkingLevelMap` with every level\n * decided explicitly: declared levels carry their wire spelling, undeclared\n * levels are pinned to `null` (unsupported). Pinning matters because pi-ai's\n * own defaulting is asymmetric — an absent key means \"supported\" for the five\n * base levels but \"unsupported\" for `xhigh`/`max` — and a profile author\n * should not need to know that. A declared `off` with no value is the one\n * exception: it stays absent from the map, which pi-ai reads as \"supported,\n * send nothing\" — the correct dispatch where not thinking is the parameter's\n * absence — while `off` with a value sends that value.\n * @param provider - provider route key, for diagnostics.\n * @param entry - the configured model entry.\n * @param base - the installed catalog entry of the same id, when one exists.\n * @returns the reasoning fields the materialized model carries.\n */\nfunction resolveModelReasoning(\n provider: string,\n entry: PiAiModelProfile,\n base: Model<Api> | undefined,\n): ModelReasoning {\n const efforts = entry.reasoningEfforts\n if (efforts === undefined) {\n // Reasoning rides the installed entry or is absent: a bare capability flag\n // would make pi-ai advertise effort levels with no `thinkingLevelMap` to\n // spell them, and no listing endpoint reports a model's reasoning\n // protocol. The entry's map (when any) arrives through the `...base`\n // spread in the model literal.\n return { reasoning: base?.reasoning ?? false }\n }\n // The installed entry's map may ride along through `...base`; pi-ai never\n // reads it on a non-reasoning model, so stripping it is not worth a field\n // enumeration here.\n if (efforts === false) return { reasoning: false }\n // A YAML `reasoningEfforts:` left valueless arrives as null through the\n // schema union — outside the field's declared type, hence the widening —\n // while an explicit `{}` arrives as an empty dict. Both declare nothing,\n // and neither is a spelling of \"inherit\" or \"disable\".\n if ((efforts as unknown) === null || Object.keys(efforts).length === 0) {\n invalid(provider, `model \"${entry.id}\" has an empty reasoningEfforts; declare the offered levels, set`\n + ' false for a non-reasoning model, or omit the field to keep the installed catalog\\'s capability')\n }\n const declared = THINKING_LEVELS.flatMap((level) => {\n const wire = efforts[level]\n return wire === undefined ? [] : [[level, wire] as const]\n })\n for (const [level, wire] of declared) {\n if (wire === null) {\n if (level !== 'off') {\n invalid(provider, `model \"${entry.id}\" reasoningEfforts.${level} needs the wire value dispatch`\n + ' should send; only \"off\" may leave it empty')\n }\n } else if (wire.length === 0) {\n invalid(provider, `model \"${entry.id}\" reasoningEfforts.${level} must not be an empty string`)\n }\n }\n if (!declared.some(([level]) => level !== 'off')) {\n invalid(provider, `model \"${entry.id}\" reasoningEfforts offers no level beyond \"off\"; declare a thinking`\n + ' level, or set reasoningEfforts to false for a non-reasoning model')\n }\n const map: ThinkingLevelMap = {}\n for (const level of THINKING_LEVELS) {\n const wire = efforts[level]\n if (wire === undefined) {\n map[level] = null\n } else if (wire !== null) {\n map[level] = wire\n }\n }\n return { reasoning: true, thinkingLevelMap: map }\n}\n\n/** The compat block a materialized model carries, whichever protocol it speaks. */\ntype ModelCompat = OpenAICompletionsCompat | OpenAIResponsesCompat | AnthropicMessagesCompat | BedrockCompat\n\n/**\n * Resolve one model's compat block from the profile's switches.\n *\n * A model switch wins over the route switch field by field; whatever neither\n * sets keeps the installed entry's value, and a field no layer decides falls\n * through to pi-ai's own detection. A model-level switch its protocol does not\n * take fails resolution — about one named model it can only be a mistake —\n * while a route-level one skips past such models, since a route default must\n * stay settable on a route whose models do not all speak one protocol. Every\n * field reaching here is offered by some protocol; {@link\n * assertOfferedCompatFields} has already refused the rest.\n * @param provider - provider route key, for diagnostics.\n * @param entry - the configured model entry.\n * @param route - the route-level switches, when any.\n * @param base - the installed catalog entry of the same id, when one exists.\n * @param api - the model's resolved wire protocol.\n * @returns a `compat` field to spread into the model, or nothing.\n */\nfunction resolveModelCompat(\n provider: string,\n entry: PiAiModelProfile,\n route: PiAiCompatProfile | undefined,\n base: Model<Api> | undefined,\n api: string,\n): { compat: ModelCompat } | Record<string, never> {\n const gate = compatGate(api)\n const configured: Record<string, unknown> = {}\n for (const [field, value] of configuredCompatEntries(route)) {\n if (gate?.[field] !== 'offer') continue\n configured[field] = value\n }\n for (const [field, value] of configuredCompatEntries(entry.compat)) {\n if (gate?.[field] !== 'offer') {\n const offered = offeredCompatFields(api)\n invalid(provider, `model \"${entry.id}\" sets compat \"${field}\", but its api is \"${api}\", which does not`\n + ` take it; that switch exists on ${compatProtocols(field).join(', ')}, and \"${api}\" offers`\n + ` ${offered.length === 0 ? 'no configurable compat' : offered.join(', ')}`)\n }\n configured[field] = value\n }\n if (Object.keys(configured).length === 0) return {}\n // The installed entry's compat matches the entry's OWN api — a route-level\n // `api` repoint (an anthropic catalog served through an OpenAI-compatible\n // gateway) leaves `base.compat` in the other protocol's shape, so it is\n // inherited only while the resolved api still is the entry's. A repointed\n // model starts from pi-ai's baseURL-derived detection instead, which is\n // what a protocol change means for every other compat field too.\n const inherited = base?.api === api ? base.compat : undefined\n return { compat: { ...inherited, ...configured } as ModelCompat }\n}\n\n/** One route's materialized catalog, plus the request caps its profile chose. */\nexport interface RouteCatalog {\n /** The materialized models in configuration order. */\n models: readonly Model<Api>[]\n /**\n * Per-request output caps this profile explicitly configured, by model id.\n *\n * Separate from `Model.maxTokens` because the two answer different\n * questions: pi-ai requires `maxTokens` as the model's output *capability*,\n * while the harness seam's `defaultMaxTokens` is a cap the deployment chose\n * to send on requests that name none. Materializing a catalog capability as\n * a request default would start capping every request at a number nobody\n * picked, so only an explicit configuration lands here.\n */\n configuredMaxTokens: ReadonlyMap<string, number>\n}\n\n/**\n * Materialize one route's catalog by merging the installed catalog defaults\n * under the configured entries. A route with no configured `models` serves the\n * installed catalog unchanged, which is what keeps an existing\n * `providers: { deepseek: { apiKeyEnv: … } }` profile working untouched.\n * @param request - the route-level catalog facts.\n * @returns the materialized models and the explicitly configured request caps.\n */\nexport function resolveRouteModels(request: RouteCatalogRequest): RouteCatalog {\n const { provider } = request\n const defaults = catalogModels(provider)\n const providerBaseUrl = catalogProvider(provider)?.baseUrl\n // An absent `models` key and an empty one are the same request: the config\n // schema materializes `[]` for the absent case, and an empty catalog could\n // serve no request anyway, so both mean \"serve the installed catalog\".\n const configured = request.models ?? []\n const overrides = request.modelOverrides ?? {}\n // Every miss is refused, never skipped: an override that lands nowhere is a\n // typo someone would otherwise hunt for in a silently unchanged model.\n for (const [id, override] of Object.entries(overrides)) {\n if (id.length === 0) invalid(provider, 'has a modelOverrides entry with an empty model id')\n if (defaults.size === 0) {\n invalid(provider, `sets modelOverrides for \"${id}\", but the installed catalog does not describe this route;`\n + ' a declared route spells every model out in its models list')\n }\n if (configured.length > 0) {\n invalid(provider, `sets modelOverrides for \"${id}\" beside a models list; models already replaces the served`\n + ' catalog, so declare the fields on its entries')\n }\n if (!defaults.has(id)) {\n invalid(provider, `modelOverrides names \"${id}\", which the installed catalog does not describe`)\n }\n // The id lives in the dict key; a value carrying its own would quietly\n // rename the model it meant to customize. The static shape already omits\n // it — this guards the schema boundary, which passes unknown keys through.\n if ('id' in override) {\n invalid(provider, `modelOverrides entry \"${id}\" sets \"id\", which is the dict key`)\n }\n }\n // An override becomes the catalog entry's configuration, so everything a\n // models entry may declare — capacities, efforts, compat — resolves through\n // the same path with the same diagnostics and request-default semantics.\n const entries: readonly PiAiModelProfile[] = configured.length > 0\n ? configured\n : [...defaults.values()].map(model => ({ id: model.id, ...overrides[model.id] }))\n if (entries.length === 0) {\n invalid(provider, 'resolves no models; the installed catalog does not describe this route, so its models'\n + ' must be listed in configuration')\n }\n const routeApi = sharedCatalogApi(defaults)\n // Vocabulary before protocols: a withheld or undeclared switch is refused\n // wherever it is written, so it cannot look applied on a route whose models\n // never reach the protocol that would have taken it.\n assertOfferedCompatFields(provider, 'route', request.compat)\n for (const entry of entries) {\n assertOfferedCompatFields(provider, `model \"${entry.id}\"`, entry.compat)\n }\n const seen = new Set<string>()\n const configuredMaxTokens = new Map<string, number>()\n const models = entries.map((entry) => {\n if (entry.id.length === 0) invalid(provider, 'has a model with an empty id')\n if (seen.has(entry.id)) invalid(provider, `lists model \"${entry.id}\" more than once`)\n seen.add(entry.id)\n const base = defaults.get(entry.id)\n const api = request.api ?? base?.api ?? routeApi\n if (api === undefined) {\n invalid(provider, `model \"${entry.id}\" needs an api; the installed catalog does not describe it, so set the`\n + ' route\\'s api to the wire protocol its endpoint speaks')\n }\n const baseUrl = request.baseURL ?? base?.baseUrl ?? providerBaseUrl\n if (baseUrl === undefined) {\n invalid(provider, `model \"${entry.id}\" needs a baseURL; the installed catalog does not describe this route`)\n }\n // Capacities fall back to the route's own defaults, so a model listing that\n // discloses nothing but ids still yields a serviceable route. The fallback\n // is a guess by construction, which is why it is a configurable route field\n // rather than a constant buried here.\n const contextWindow = entry.contextWindow ?? base?.contextWindow ?? request.defaultContextWindow\n if (!Number.isInteger(contextWindow) || contextWindow <= 0) {\n invalid(provider, `model \"${entry.id}\" contextWindow must be a positive integer`)\n }\n const maxTokens = entry.maxTokens ?? base?.maxTokens ?? request.defaultMaxTokens\n if (!Number.isInteger(maxTokens) || maxTokens <= 0) {\n invalid(provider, `model \"${entry.id}\" maxTokens must be a positive integer`)\n }\n // Only a value the profile named is a deployment choice; the catalog's is\n // the model's capability and stays out of request defaults.\n if (entry.maxTokens !== undefined) configuredMaxTokens.set(entry.id, entry.maxTokens)\n return {\n // The installed entry lays the floor, and the fields below override it.\n // Enumerating instead would silently drop every `Model` field this\n // package does not model — reasoning-level spellings, compatibility\n // quirks, model headers, and whatever a pi-ai upgrade adds next. Spread,\n // never enumerate.\n ...base,\n id: entry.id,\n name: entry.name ?? base?.name ?? entry.id,\n api,\n provider,\n baseUrl,\n input: declaredInput(entry.input) ?? base?.input ?? [...request.defaultInput],\n cost: base?.cost ?? NO_COST,\n contextWindow,\n maxTokens,\n ...resolveModelReasoning(provider, entry, base),\n ...resolveModelCompat(provider, entry, request.compat, base, api),\n }\n })\n // Per field, not per block: a route may default a switch its completions\n // models take beside one only its anthropic models do, and neither should\n // fail for the other's sake. What is refused is a route default no model on\n // the route could ever read, which is a route that will not behave as written.\n for (const [field] of configuredCompatEntries(request.compat)) {\n const takers = compatProtocols(field)\n if (models.some(model => takers.includes(model.api))) continue\n invalid(provider, `sets compat \"${field}\", but no model on the route speaks a protocol that takes it;`\n + ` it exists on ${takers.join(', ')}`)\n }\n return { models, configuredMaxTokens }\n}\n","/**\n * Construction of the pi-ai `Provider` that one configured route registers into\n * the adapter's `Models` collection.\n *\n * Two constructions, one decision: a route the installed catalog ships, whose\n * profile does not override the wire protocol, **reuses that catalog provider**\n * with its models replaced — the catalog provider owns API implementations this\n * package cannot reconstruct (Bedrock loads its Smithy module through a\n * separate entry point), so rebuilding it from parts would silently narrow\n * which providers work. Every other route — one pi-ai has never heard of, or a\n * catalog route pointed at a different protocol — is built by `createProvider`\n * over the protocol table below.\n *\n * Credentials never reach this module's storage: the harness resolves a route's\n * key through `ctx.credentials` before the request enters pi-ai and hands it\n * over as a stream option, which `Models` presents to `resolve()` as the\n * credential key.\n *\n * @module dsh-llm-pi-ai/provider\n */\n\nimport { createProvider } from '@earendil-works/pi-ai'\nimport type { Api, ApiKeyAuth, Model, Provider, ProviderStreams } from '@earendil-works/pi-ai'\nimport { anthropicMessagesApi } from '@earendil-works/pi-ai/api/anthropic-messages.lazy'\nimport { openAICompletionsApi } from '@earendil-works/pi-ai/api/openai-completions.lazy'\nimport { openAIResponsesApi } from '@earendil-works/pi-ai/api/openai-responses.lazy'\nimport { catalogProvider } from './catalog.ts'\n\n/**\n * Wire protocols a configured route may name, mapped to pi-ai's lazily loaded\n * implementations. Each entry is the factory that pi-ai's matching provider\n * factory uses, so a hand-declared route reaches exactly the implementation a\n * catalog route would.\n *\n * The table is deliberately narrow: the protocols a hand-declared route\n * actually reads, each completely describable with a key, an\n * endpoint, and headers. Bedrock signs with SigV4 over AWS credentials and a\n * region, Vertex needs a project, a location, and application-default\n * credentials, Azure needs provider environment plus an api-version, and Codex\n * authenticates through OAuth — none of which this configuration shape can\n * express, so offering them would hand back a provider that cannot\n * authenticate. The remainder are absent for want of a consumer rather than a\n * blocker: each is one line here once a deployment needs it. Catalog routes\n * still reach every protocol through their own provider; only an explicit\n * override is refused.\n */\nconst PROTOCOLS: Readonly<Record<string, () => ProviderStreams>> = {\n 'openai-completions': openAICompletionsApi,\n 'openai-responses': openAIResponsesApi,\n 'anthropic-messages': anthropicMessagesApi,\n}\n\n/**\n * Every wire protocol a configured route may name, most-reached first. The\n * order is the table's and therefore stable; a configuration surface offering\n * a choice presents the first as its default, which is why the protocol a\n * hand-declared gateway most often speaks — and the one endpoint interrogation\n * can read — leads.\n * @returns the supported protocol identifiers.\n */\nexport function supportedProtocols(): readonly string[] {\n return Object.keys(PROTOCOLS)\n}\n\n/**\n * Api-key auth for a route the harness authenticates itself. `Models` calls\n * this after the adapter has already resolved the route's credential, so a\n * missing key here is not this layer's failure: a named-but-unresolvable\n * reference has already failed the request with `MISSING_CREDENTIAL`, and a\n * route naming no credential at all is deliberately unauthenticated. Reporting\n * it as configured hands the decision to the protocol, which is where the\n * requirement actually lives — pi-ai's OpenAI-compatible implementation, for\n * one, still insists on a key or an `Authorization` header of its own.\n * @param name - display name used as the resolution's status label.\n * @returns the api-key auth for a harness-authenticated route.\n */\nfunction harnessApiKeyAuth(name: string): ApiKeyAuth {\n return {\n name,\n resolve: ({ credential }) => Promise.resolve({\n auth: credential?.key === undefined ? {} : { apiKey: credential.key },\n source: name,\n }),\n }\n}\n\n/** The resolved route facts provider construction reads. */\nexport interface ProviderSpec {\n /** Provider route key; also the `Models` collection key and each model's `provider`. */\n provider: string\n /** Display name for selectors and status labels. */\n displayName: string\n /** Wire protocol override; absent means each model keeps its catalog protocol. */\n api?: string\n /** Endpoint override already applied to {@link models}; kept for provider-level display. */\n baseURL?: string\n /** The route's materialized models, in configuration order. */\n models: readonly Model<Api>[]\n /**\n * Whether the profile names a credential, which it does through `apiKeyEnv`\n * alone: configuration carries the reference, never the secret. Only that\n * decides whether {@link routeAuth} adds the harness's own api-key method to\n * a catalog provider that offers none; the key itself still arrives per\n * request, never at construction.\n */\n namesCredential: boolean\n}\n\n/**\n * The auth one route resolves its credential through.\n *\n * A catalog route keeps the installed provider's own auth, which is what\n * preserves provider-native ambient discovery for a profile naming no\n * credential. That holds even when the profile repoints the protocol: which\n * environment a provider reads is a property of the provider, not of the wire\n * format its models speak.\n *\n * The single addition covers a catalog provider that offers no api-key method\n * at all. pi-ai resolves a request's `apiKey` override only when the provider\n * declares one (`resolveProviderAuth` checks `provider.auth.apiKey` before\n * honouring the override), so an OAuth-only provider — `openai-codex` is the\n * one the installed catalog ships — would refuse a profile's explicit key with\n * `Provider is not configured` before any request went out. Adding the harness\n * method beside the provider's own restores that route. A keyless profile adds\n * nothing and still reports the honest refusal, because this adapter resolves\n * credentials through its own seam and holds no OAuth store to fall back on.\n * @param spec - the resolved route facts.\n * @param catalog - the installed catalog provider, when pi-ai ships one.\n * @returns the auth to construct this route's provider with.\n */\nfunction routeAuth(spec: ProviderSpec, catalog: Provider | undefined): Provider['auth'] {\n if (catalog === undefined) return { apiKey: harnessApiKeyAuth(spec.displayName) }\n if (catalog.auth.apiKey !== undefined || !spec.namesCredential) return catalog.auth\n return { ...catalog.auth, apiKey: harnessApiKeyAuth(spec.displayName) }\n}\n\n/**\n * Reuse an installed catalog provider with this route's models and identity.\n * Model dispatch stays with the catalog provider, so its API implementations,\n * compatibility quirks, and ambient credential discovery are preserved exactly.\n * Catalog-owned dynamic refresh is dropped: this route's catalog is the\n * settings document, and a background refresh would contradict it.\n */\nfunction reuseCatalogProvider(base: Provider, spec: ProviderSpec): Provider {\n // Provider-level `baseUrl` is display metadata: pi-ai routes every request\n // through `Model.baseUrl`, which model resolution has already overridden.\n const baseUrl = spec.baseURL ?? base.baseUrl\n return {\n id: spec.provider,\n name: spec.displayName,\n ...baseUrl === undefined ? {} : { baseUrl },\n auth: routeAuth(spec, base),\n getModels: () => spec.models,\n // Delegated rather than copied: the catalog provider stays the receiver, so\n // an implementation holding state on itself keeps working.\n stream: (model, context, options) => base.stream(model, context, options),\n streamSimple: (model, context, options) => base.streamSimple(model, context, options),\n }\n}\n\n/**\n * Build the pi-ai provider for one resolved route.\n * @param spec - the resolved route facts.\n * @returns the provider to register in the adapter's `Models` collection.\n * @throws Error when the route names a wire protocol this build cannot serve.\n */\nexport function buildProvider(spec: ProviderSpec): Provider {\n const catalog = catalogProvider(spec.provider)\n // A catalog route keeping its catalog protocol reuses the catalog provider;\n // an explicit protocol means the deployment is repointing the route at a\n // different wire format, which only the protocol table can serve.\n if (catalog !== undefined && spec.api === undefined) return reuseCatalogProvider(catalog, spec)\n\n // Every model on this path carries the route's protocol: model resolution\n // requires one for a route the catalog cannot default, and an explicit one\n // replaces each catalog model's own. So the route has a single API.\n const factory = spec.api === undefined ? undefined : PROTOCOLS[spec.api]\n if (factory === undefined) {\n throw new Error(\n `llm-pi-ai: provider \"${spec.provider}\" names api \"${spec.api}\", which this build cannot serve;`\n + ` supported protocols are ${supportedProtocols().join(', ')}`,\n )\n }\n return createProvider({\n id: spec.provider,\n name: spec.displayName,\n ...spec.baseURL === undefined ? {} : { baseUrl: spec.baseURL },\n auth: routeAuth(spec, catalog),\n models: spec.models,\n api: factory(),\n })\n}\n","/**\n * Configuration schema and provider-profile validation for the pi-ai adapter.\n * Profiles are a dict keyed by provider route, so the composition base and a\n * user-settings layer merge per provider and the route set is structural.\n *\n * A route key is not required to name an installed pi-ai provider. When it does,\n * that provider's endpoint, protocol, display name, and model catalog are the\n * profile's defaults and the profile overrides them field by field; when it does\n * not, the profile is the whole provider declaration. Resolution therefore ends\n * in a built pi-ai `Provider` per route: everything a request needs is decided\n * once, while the configuration key that made a route unserviceable can still be\n * named in the failure.\n *\n * @module dsh-llm-pi-ai/config\n */\n\nimport type { CacheRetention, ChatTemplateKwargValue, ModelThinkingLevel, Provider, ThinkingBudgets, Transport } from '@earendil-works/pi-ai'\nimport z from '@deepseek-ai/schemastery'\nimport { credentialRef } from '@deepseek-ai/dsh-credentials'\nimport type { CredentialRef } from '@deepseek-ai/dsh-credentials'\nimport { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'\nimport { resolveRetryPolicy, RetryPolicySchema } from '@deepseek-ai/dsh-llm'\nimport type { ResolvedRetryPolicy, RetryPolicyConfig } from '@deepseek-ai/dsh-llm'\nimport {\n CACHE_CONTROL_FORMATS,\n CHAT_TEMPLATE_VARS,\n MAX_TOKENS_FIELDS,\n MODALITIES,\n resolveRouteModels,\n SUPPORTED_THINKING_FORMATS,\n THINKING_LEVELS,\n} from './catalog.ts'\nimport type {\n PiAiCompatProfile,\n PiAiModality,\n PiAiModelOverride,\n PiAiModelProfile,\n PiAiReasoningEfforts,\n} from './catalog.ts'\nimport { buildProvider, supportedProtocols } from './provider.ts'\n\n/** Default maximum idle interval while an adapter stream read is outstanding. */\nexport const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000\n\n/**\n * Default request-level bound on base64-encoded image payload. Every image in\n * history is re-encoded into every request body, so an unbounded conversation\n * eventually exceeds a provider or gateway request-size cap and the session\n * can never complete another request. The 20MiB default admits fifteen 1MiB\n * request versions after base64 expansion and reserves request capacity for\n * system prompts, history, tools, and JSON.\n * Deployments behind stricter gateways lower it per route.\n */\nexport const DEFAULT_MAX_REQUEST_IMAGE_BYTES = 20 * 1024 * 1024\n/** Default total-pixel budget preserves the complete 2048px normalized attachment. */\nexport const DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET = 2048 * 2048\n/** Default raw encoded-byte target before inline base64 expansion; the smallest quality-ladder output is used when no quality fits. */\nexport const DEFAULT_REQUEST_IMAGE_MAX_BYTES = 1024 * 1024\n\n/** Context capacity assumed for a model neither configuration nor the catalog sizes. */\nexport const DEFAULT_CONTEXT_WINDOW = 262_144\n\n/** Output capability assumed for a model neither configuration nor the catalog sizes. */\nexport const DEFAULT_MAX_TOKENS = 32_768\n\n/**\n * Modalities assumed for a model neither configuration nor the catalog\n * declares. Text is the floor every supported protocol certainly carries, so\n * this is the absence of a declaration rather than a guess at the endpoint:\n * nothing can interrogate a gateway for its modalities, and the two wrong\n * answers do not cost the same. Under-claiming refuses the image before it is\n * attached, naming the model. Over-claiming admits one the provider then\n * rejects mid-turn, after the message is durable, leaving the session\n * repeating a request that cannot succeed.\n */\nexport const DEFAULT_INPUT: readonly PiAiModality[] = ['text']\n\nexport type {\n PiAiCompatProfile,\n PiAiModality,\n PiAiModelOverride,\n PiAiModelProfile,\n PiAiReasoningEfforts,\n PiAiThinkingFormat,\n} from './catalog.ts'\n\n/** Configuration for one pi-ai provider route; the `providers` dict key IS the route. */\nexport interface PiAiProviderProfile {\n /** Credential reference (environment-variable name) resolved per request through `ctx.credentials`. */\n apiKeyEnv?: string\n /** Name shown by configuration surfaces; defaults to the route key. */\n displayName?: string\n /**\n * Wire protocol every model on this route speaks. Omission keeps each\n * installed catalog model's own protocol, which is why a catalog route needs\n * no protocol at all; a route the catalog does not ship must name one.\n */\n api?: string\n /** Endpoint for this route's models; defaults to the installed catalog's endpoint. */\n baseURL?: string\n /**\n * This route's model catalog. Omission serves the installed catalog for the\n * route unchanged; an explicit list replaces it, each entry defaulting its\n * unset fields from the installed model of the same id.\n */\n models?: PiAiModelProfile[]\n /**\n * Installed-catalog customizations by model id: each entry reshapes that\n * one model with the same fields a {@link models} entry takes, while the\n * rest of the catalog keeps serving untouched. Only meaningful on a catalog\n * route with no `models` list — `models` already replaces the catalog, so\n * an override beside it, on a route the catalog does not ship, or naming a\n * model the catalog does not describe is refused rather than skipped.\n */\n modelOverrides?: Record<string, PiAiModelOverride>\n /**\n * pi-ai wire-compatibility switches defaulting every model on this route\n * whose protocol declares them; each model's own `compat` overrides per\n * field. What neither sets keeps the installed catalog entry's value, then\n * pi-ai's own detection. A switch no model on the route could read is\n * refused rather than left looking applied.\n */\n compat?: PiAiCompatProfile\n /**\n * Context capacity for a model this route lists that neither the entry nor\n * the installed catalog sizes (default 262,144). A guess by construction, so\n * a deployment whose gateway serves smaller models corrects it here.\n */\n defaultContextWindow?: number\n /**\n * Output capability for a model this route lists that neither the entry nor\n * the installed catalog sizes (default 32,768). This sizes the model; it\n * never becomes a per-request cap on its own.\n */\n defaultMaxTokens?: number\n /**\n * Request modalities for a model this route lists that neither its entry's\n * {@link PiAiModelProfile.input} nor the installed catalog declares (default\n * `[text]`). A fallback like the capacities above, not an override: a\n * catalog model keeps the modalities the catalog records for it, and this\n * value never narrows one. A gateway serving vision models the catalog does\n * not describe declares `[text, image]` once here instead of on every entry.\n * Unlike an entry's list, this one may not be empty — nothing sits below it\n * to answer instead.\n */\n defaultInput?: PiAiModality[]\n /** Provider request headers; host attribution wins reserved names. */\n headers?: Record<string, string>\n /** Provider-neutral pi-ai reasoning level. */\n reasoning?: ModelThinkingLevel\n /** Send reasoning_split to an OpenAI Chat Completions gateway; omission leaves its response format unchanged. */\n reasoningSplit?: boolean\n /** Token budgets used by reasoning providers that support them. */\n thinkingBudgets?: ThinkingBudgets\n /** Prompt-cache retention preference. */\n cacheRetention?: CacheRetention\n /** Streaming transport preference. */\n transport?: Transport\n /** HTTP/provider SDK timeout in milliseconds. */\n timeoutMs?: number\n /** WebSocket connection timeout in milliseconds. */\n websocketConnectTimeoutMs?: number\n /** Maximum provider idle time while one stream read is outstanding. */\n streamIdleTimeoutMs?: number\n /**\n * Maximum base64-encoded image payload per request. When a request's\n * accumulated images exceed it, the oldest images are replaced by text\n * placeholders until the request fits, so a long session keeps completing\n * requests instead of being rejected by a request-size cap.\n */\n maxRequestImageBytes?: number\n /** Total-pixel budget for each deterministic inline request version. */\n requestImagePixelBudget?: number\n /**\n * Raw encoded-byte target for each deterministic inline request version;\n * the smallest quality-ladder output is used when no quality fits.\n */\n requestImageMaxBytes?: number\n /** Provider-owned model-request retry policy; omission uses normal mode with five retries. */\n retryPolicy?: RetryPolicyConfig\n}\n\n/** Validated profile with its route stamped and every adapter-owned default resolved. */\nexport interface ResolvedPiAiProviderProfile\n extends Omit<PiAiProviderProfile, 'apiKeyEnv' | 'retryPolicy' | 'models' | 'displayName'> {\n /** ChatCode CLI route key and the `Models` collection key (the configuration dict key). */\n provider: string\n /** Resolved display name for selectors and configuration surfaces. */\n displayName: string\n /** Validated credential reference, when one is configured. */\n apiKeyEnv?: CredentialRef\n /** Positive finite provider-idle interval after defaulting. */\n streamIdleTimeoutMs: number\n /** Positive request-level base64 image payload bound after defaulting. */\n maxRequestImageBytes: number\n /** Positive total-pixel request-version budget after defaulting. */\n requestImagePixelBudget: number\n /** Positive raw request-version byte target after defaulting; the smallest quality-ladder output is used when no quality fits. */\n requestImageMaxBytes: number\n /** Immutable retry policy captured with this provider route. */\n retryPolicy: ResolvedRetryPolicy\n /**\n * The pi-ai provider this route registers, built from the resolved models.\n * Construction happens here so an unserviceable protocol or an underspecified\n * model fails with the rest of resolution, leaving the last good route set\n * serving requests.\n */\n piProvider: Provider\n /**\n * Per-request output caps this profile explicitly configured, by model id.\n * The seam materializes one only into a request that names no cap of its\n * own, so a catalog capability must not appear here.\n */\n configuredMaxTokens: ReadonlyMap<string, number>\n}\n\n/** Plugin configuration: the provider routes this instance owns. */\nexport interface Config {\n /**\n * pi-ai provider routes, keyed by provider. An empty (or omitted) dict is\n * the dormant settings-driven posture: the adapter mounts with no routes\n * and registers them the moment a settings section supplies profiles.\n */\n providers?: Record<string, PiAiProviderProfile>\n}\n\nconst thinkingBudgets = z.object({\n minimal: z.number(),\n low: z.number(),\n medium: z.number(),\n high: z.number(),\n})\n\n/**\n * One `chat_template_kwargs` or `chat_template_args` value. The `$var` member\n * is pi-ai's placeholder for a value dispatch fills from the request's\n * thinking state, which makes a template-driven gateway configurable without\n * restating its template.\n */\nconst chatTemplateKwarg: z<ChatTemplateKwargValue> = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.const(null),\n z.object({\n $var: z.union(CHAT_TEMPLATE_VARS).required(),\n omitWhenOff: z.boolean(),\n }),\n])\n\nconst compatProfile: z<PiAiCompatProfile> = z.object({\n supportsStore: z.boolean(),\n supportsDeveloperRole: z.boolean(),\n supportsReasoningEffort: z.boolean(),\n supportsUsageInStreaming: z.boolean(),\n supportsFinishReason: z.boolean(),\n maxTokensField: z.union(MAX_TOKENS_FIELDS),\n requiresToolResultName: z.boolean(),\n requiresAssistantAfterToolResult: z.boolean(),\n requiresThinkingAsText: z.boolean(),\n requiresReasoningContentOnAssistantMessages: z.boolean(),\n thinkingFormat: z.union(SUPPORTED_THINKING_FORMATS),\n chatTemplateKwargs: z.dict(chatTemplateKwarg),\n chatTemplateArgs: z.dict(chatTemplateKwarg),\n supportsThinkingTokenBudget: z.boolean(),\n supportsStrictMode: z.boolean(),\n cacheControlFormat: z.union(CACHE_CONTROL_FORMATS),\n supportsLongCacheRetention: z.boolean(),\n supportsEagerToolInputStreaming: z.boolean(),\n supportsCacheControlOnTools: z.boolean(),\n supportsTemperature: z.boolean(),\n forceAdaptiveThinking: z.boolean(),\n allowEmptySignature: z.boolean(),\n supportsStrictTools: z.boolean(),\n})\n\n/**\n * Keys are the offered levels, values their wire spellings. A valueless key\n * (`off:`) survives validation because schemastery passes nullable data\n * through before any member schema runs — `z.const(null)` only controls the\n * error for non-null wrong values and what a configuration UI renders.\n * Only resolution decides which levels may leave the value empty, so the\n * diagnostic can name the route and model. The assertion narrows\n * schemastery's `Dict`, which types every literal key as required; dict\n * validation checks only present keys, so the runtime value is a partial record.\n */\nconst reasoningEfforts = z.dict(\n z.union([z.string(), z.const(null)]),\n z.union(THINKING_LEVELS),\n) as unknown as z<PiAiReasoningEfforts>\n\n/** The fields a `models` entry and a `modelOverrides` value share; only the id's home differs. */\nconst modelFields = {\n name: z.string(),\n contextWindow: z.number().step(1).min(1),\n maxTokens: z.number().step(1).min(1),\n // No explicit default, unlike the route's `defaultInput`: schemastery\n // materializes `[]` for an absent array, and resolution reads that as \"no\n // answer here\" so the catalog entry below still applies.\n input: z.array(z.union(MODALITIES)),\n // The union, not a bare dict: schemastery materializes an absent dict as\n // `{}`, and absent must stay distinguishable — it means \"inherit the\n // installed catalog's capability\", while `false` disables reasoning.\n reasoningEfforts: z.union([z.const(false), reasoningEfforts]),\n compat: compatProfile,\n}\n\nconst modelProfile: z<PiAiModelProfile> = z.object({\n id: z.string().required(),\n ...modelFields,\n})\n\n/** A {@link modelProfile} whose id lives in the `modelOverrides` dict key. */\nconst modelOverride: z<PiAiModelOverride> = z.object(modelFields)\n\nconst profile = z.object({\n apiKeyEnv: z.string().role('credential-ref'),\n displayName: z.string(),\n api: z.union(supportedProtocols()),\n baseURL: z.string(),\n models: z.array(modelProfile),\n modelOverrides: z.dict(modelOverride),\n compat: compatProfile,\n defaultContextWindow: z.number().step(1).min(1).default(DEFAULT_CONTEXT_WINDOW),\n defaultMaxTokens: z.number().step(1).min(1).default(DEFAULT_MAX_TOKENS),\n defaultInput: z.array(z.union(MODALITIES)).default([...DEFAULT_INPUT]),\n headers: z.dict(z.string()),\n reasoning: z.union(THINKING_LEVELS),\n reasoningSplit: z.boolean(),\n thinkingBudgets,\n cacheRetention: z.union(['none', 'short', 'long']),\n transport: z.union(['sse', 'websocket', 'websocket-cached', 'auto']),\n timeoutMs: z.natural(),\n websocketConnectTimeoutMs: z.natural(),\n streamIdleTimeoutMs: z.number().min(Number.MIN_VALUE).max(MAX_TIMER_DELAY_MS).default(DEFAULT_STREAM_IDLE_TIMEOUT_MS),\n maxRequestImageBytes: z.number().step(1).min(1).default(DEFAULT_MAX_REQUEST_IMAGE_BYTES),\n requestImagePixelBudget: z.number().step(1).min(1).default(DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET),\n requestImageMaxBytes: z.number().step(1).min(1).default(DEFAULT_REQUEST_IMAGE_MAX_BYTES),\n retryPolicy: RetryPolicySchema,\n})\n\n/** Runtime schema for {@link Config}. */\nexport const Config: z<Config> = z.object({\n providers: z.dict(profile).default({}),\n})\n\n/**\n * Reject a section this adapter could not serve. Registered as the settings\n * namespace's validator, so an unserviceable profile is refused where it is\n * *written* — `settings.mutate` answers `settings-rejected` with the offending\n * route and model named — instead of being stored and then quietly disabling\n * every route in the namespace. It stays a validator rather than a schema\n * transform because the schema is also the shape a configuration surface\n * renders and the value an absent section resolves to; wrapping it would break\n * both.\n * @param config - the resolved section to check.\n * @throws Error naming the route and model that cannot be served.\n */\nexport function assertServiceable(config: Config): void {\n resolveProfiles(config.providers)\n}\n\n/** Reject removed pre-release profile fields and name their replacements. */\nfunction rejectRemovedFields(provider: string, source: PiAiProviderProfile): void {\n const legacy = source as PiAiProviderProfile & {\n provider?: unknown\n maxRetries?: unknown\n maxRetryDelayMs?: unknown\n }\n if ('provider' in legacy) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" sets \"provider\", which moved to the providers dict key`)\n }\n if ('maxRetries' in legacy || 'maxRetryDelayMs' in legacy) {\n throw new Error(\n `llm-pi-ai: provider \"${provider}\" sets maxRetries or maxRetryDelayMs, which were removed;`\n + ' compose agent recovery with dsh-llm-retry',\n )\n }\n}\n\n/**\n * Validate profiles and return a detached route-keyed map suitable for\n * per-request reads. This is the one explicit resolve step, so an omitted dict\n * resolves to the empty (dormant) route set here rather than through a hidden\n * fallback, and each route's models and pi-ai provider are materialized once.\n * @param providers - configured provider profiles keyed by route.\n * @returns validated profiles in configuration order.\n */\nexport function resolveProfiles(\n providers: Readonly<Record<string, PiAiProviderProfile>> | undefined,\n): Map<string, ResolvedPiAiProviderProfile> {\n if (Array.isArray(providers)) {\n throw new Error('llm-pi-ai: providers is now a dict keyed by provider route, not an array of profiles')\n }\n const entries = Object.entries(providers ?? {})\n const resolved = new Map<string, ResolvedPiAiProviderProfile>()\n for (const [provider, source] of entries) {\n rejectRemovedFields(provider, source)\n if (provider.length === 0) throw new Error('llm-pi-ai: provider names must be non-empty')\n if (source.baseURL !== undefined && source.baseURL.length === 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" has an empty baseURL`)\n }\n if (source.displayName !== undefined && source.displayName.length === 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" has an empty displayName`)\n }\n const streamIdleTimeoutMs = source.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS\n if (!Number.isFinite(streamIdleTimeoutMs)\n || streamIdleTimeoutMs <= 0\n || streamIdleTimeoutMs > MAX_TIMER_DELAY_MS) {\n throw new Error(\n `llm-pi-ai: provider \"${provider}\" streamIdleTimeoutMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`,\n )\n }\n const maxRequestImageBytes = source.maxRequestImageBytes ?? DEFAULT_MAX_REQUEST_IMAGE_BYTES\n if (!Number.isInteger(maxRequestImageBytes) || maxRequestImageBytes <= 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" maxRequestImageBytes must be a positive integer`)\n }\n const requestImagePixelBudget = source.requestImagePixelBudget ?? DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET\n if (!Number.isSafeInteger(requestImagePixelBudget) || requestImagePixelBudget <= 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" requestImagePixelBudget must be a positive safe integer`)\n }\n const requestImageMaxBytes = source.requestImageMaxBytes ?? DEFAULT_REQUEST_IMAGE_MAX_BYTES\n if (!Number.isSafeInteger(requestImageMaxBytes) || requestImageMaxBytes <= 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" requestImageMaxBytes must be a positive safe integer`)\n }\n // Detached from the configuration object because pi-ai types `Model.input`\n // mutable. The schema's explicit default covers an absent key, so an empty\n // list here is always one someone typed — and unlike an entry's, nothing\n // below it can answer instead — so it is refused rather than read as \"no\n // answer\".\n const defaultInput = [...source.defaultInput ?? DEFAULT_INPUT]\n if (defaultInput.length === 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" defaultInput must name at least one modality`)\n }\n // The route key, not the installed provider's own name: the directory has\n // always shown route keys, and a catalog route must not silently rename\n // itself on every configuration surface just because it gained a profile.\n const displayName = source.displayName ?? provider\n const catalog = resolveRouteModels({\n provider,\n ...source.api === undefined ? {} : { api: source.api },\n ...source.baseURL === undefined ? {} : { baseURL: source.baseURL },\n ...source.models === undefined ? {} : { models: source.models },\n ...source.modelOverrides === undefined ? {} : { modelOverrides: source.modelOverrides },\n ...source.compat === undefined ? {} : { compat: source.compat },\n defaultInput,\n defaultContextWindow: source.defaultContextWindow ?? DEFAULT_CONTEXT_WINDOW,\n defaultMaxTokens: source.defaultMaxTokens ?? DEFAULT_MAX_TOKENS,\n })\n if (source.reasoningSplit !== undefined && catalog.models.some(model => model.api !== 'openai-completions')) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" reasoningSplit requires every model to use openai-completions`)\n }\n const { apiKeyEnv, retryPolicy, models: _models, displayName: _displayName, ...rest } = source\n resolved.set(provider, {\n ...rest,\n provider,\n displayName,\n ...apiKeyEnv === undefined ? {} : { apiKeyEnv: credentialRef(apiKeyEnv) },\n streamIdleTimeoutMs,\n maxRequestImageBytes,\n requestImagePixelBudget,\n requestImageMaxBytes,\n retryPolicy: resolveRetryPolicy(retryPolicy, `llm-pi-ai: provider \"${provider}\" retryPolicy`),\n ...rest.headers === undefined ? {} : { headers: { ...rest.headers } },\n ...rest.thinkingBudgets === undefined ? {} : { thinkingBudgets: { ...rest.thinkingBudgets } },\n configuredMaxTokens: catalog.configuredMaxTokens,\n piProvider: buildProvider({\n provider,\n displayName,\n ...source.api === undefined ? {} : { api: source.api },\n ...source.baseURL === undefined ? {} : { baseURL: source.baseURL },\n models: catalog.models,\n namesCredential: apiKeyEnv !== undefined,\n }),\n })\n }\n return resolved\n}\n","/**\n * ChatCode CLI request-history conversion into pi-ai's Context vocabulary.\n *\n * @module dsh-llm-pi-ai/context\n */\n\nimport { brandString } from '@deepseek-ai/dsh-brand'\nimport { contentHasImage, IMAGE_OFFLOAD_REQUIRED_CODE, LlmError, offloadedImageText, projectOffloadedImages, requestImageHandleText, requiredImageOffload } from '@deepseek-ai/dsh-llm'\nimport type { ContentBlock, GenerateOptions, ImageAttachmentAccessResolver, Message, ToolCallId } from '@deepseek-ai/dsh-llm'\nimport type {\n AttachmentId,\n AttachmentStore,\n ImageAttachmentRef,\n ImageRequestTarget,\n RequestImageAttachment,\n} from '@deepseek-ai/dsh-attachment'\nimport type { Context as PiContext, ImageContent, Message as PiMessage, TextContent, Tool as PiTool } from '@earendil-works/pi-ai'\nimport { toPiAssistant } from './replay.ts'\nimport { requestImageDimensions } from '@deepseek-ai/dsh-attachment'\nimport { DEFAULT_REQUEST_IMAGE_MAX_BYTES, DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET } from './config.ts'\n\n/** Join the text blocks of a harness message. */\nfunction flattenText(message: Message): string {\n return message.content\n .filter(block => block.type === 'text')\n .map(block => block.text)\n .join('')\n}\n\n\n/** Flatten text recursively inside one tool result. */\nfunction toolResultText(blocks: readonly ContentBlock[]): string {\n return blocks.map(block => block.type === 'text'\n ? block.text\n : block.type === 'tool-result' ? toolResultText(block.content) : '').join('')\n}\n\n/** Reject image roles that pi-ai cannot replay before request-size offloading can replace them. */\nfunction assertSupportedImageRoles(messages: readonly Message[]): void {\n for (const message of messages) {\n if (message.role !== 'user' && contentHasImage(message.content)) {\n throw new LlmError(\n `pi-ai cannot represent an image in an in-history ${message.role} message`,\n 'UNSUPPORTED_CONTENT',\n )\n }\n }\n}\n\nasync function userContent(\n blocks: readonly ContentBlock[],\n requestImages: ReadonlyMap<AttachmentId, RequestImageAttachment>,\n resolveImageAccess: ImageAttachmentAccessResolver,\n): Promise<string | (TextContent | ImageContent)[]> {\n const content: (TextContent | ImageContent)[] = []\n for (const block of blocks) {\n switch (block.type) {\n case 'text':\n if (block.text.length > 0) content.push({ type: 'text', text: block.text })\n break\n case 'image': {\n const version = requestImages.get(block.attachment.attachmentId) as RequestImageAttachment\n content.push({\n type: 'text',\n text: requestImageHandleText(block.attachment, version, resolveImageAccess(block.attachment)),\n })\n content.push({\n type: 'image',\n data: Buffer.from(version.data).toString('base64'),\n mimeType: version.mediaType,\n })\n break\n }\n case 'tool-result':\n {\n const nested = await userContent(block.content, requestImages, resolveImageAccess)\n if (typeof nested === 'string') {\n if (nested.length > 0) content.push({ type: 'text', text: nested })\n } else {\n content.push(...nested)\n }\n }\n break\n default:\n // Other merge-extensible blocks are not user-input vocabulary for pi-ai.\n break\n }\n }\n if (content.every(block => block.type === 'text')) return content.map(block => block.text).join('')\n return content\n}\n\nfunction collectImageRefs(\n blocks: readonly ContentBlock[],\n refs: Map<AttachmentId, ImageAttachmentRef>,\n): void {\n for (const block of blocks) {\n if (block.type === 'image') {\n if (block.offloaded !== true) refs.set(block.attachment.attachmentId, block.attachment)\n } else if (block.type === 'tool-result') {\n collectImageRefs(block.content, refs)\n }\n }\n}\n\nasync function prepareRequestImages(\n messages: readonly Message[],\n attachments: AttachmentStore,\n budget: PiImageRequestBudget,\n signal?: AbortSignal,\n): Promise<Map<AttachmentId, RequestImageAttachment>> {\n const refs = new Map<AttachmentId, ImageAttachmentRef>()\n for (const message of messages) collectImageRefs(message.content, refs)\n const orderedRefs = [...refs.values()]\n const prepared = await Promise.all(orderedRefs.map(\n ref => attachments.readImageRequest(ref, requestImageTarget(ref, budget), signal),\n ))\n const versions = new Map<AttachmentId, RequestImageAttachment>()\n for (const [index, ref] of orderedRefs.entries()) {\n versions.set(ref.attachmentId, prepared[index] as RequestImageAttachment)\n }\n return versions\n}\n\nfunction toolsOf(options: GenerateOptions): PiTool[] | undefined {\n return options.tools?.map(tool => ({\n name: tool.name,\n description: tool.description,\n // ToolSchema.parameters is a JSON Schema object; pi-ai's TSchema\n // (TypeBox) is structurally JSON Schema, so it assigns directly.\n parameters: tool.parameters,\n }))\n}\n\n/** The request split into pi-ai's single `systemPrompt` slot and the history that converts to `messages`. */\ninterface SystemPromptSplit {\n /** Text for pi-ai's `systemPrompt`; `undefined` sends no system prompt. */\n systemPrompt: string | undefined\n /** History messages that convert to pi-ai `messages`. */\n messages: readonly Message[]\n}\n\n/** Select the pi-ai system prompt source shared by both conversion paths. */\nfunction splitSystemPrompt(options: GenerateOptions): SystemPromptSplit {\n if (options.system !== undefined) return { systemPrompt: options.system, messages: options.messages }\n const [first, ...rest] = options.messages\n if (first?.role !== 'system') return { systemPrompt: undefined, messages: options.messages }\n const text = flattenText(first)\n return { systemPrompt: text.length > 0 ? text : undefined, messages: rest }\n}\n\n/** Assemble the request-level pi-ai context envelope shared by both conversion paths. */\nfunction piContext(systemPrompt: string | undefined, options: GenerateOptions, messages: PiMessage[]): PiContext {\n const tools = toolsOf(options)\n return {\n ...systemPrompt !== undefined ? { systemPrompt } : {},\n messages,\n ...tools !== undefined && tools.length > 0 ? { tools } : {},\n }\n}\n\nfunction appendAssistant(\n message: Message,\n messages: PiMessage[],\n toolNames: Map<ToolCallId, string>,\n onReplayDegrade?: (reason: string) => void,\n): void {\n const assistant = toPiAssistant(message, onReplayDegrade)\n for (const block of assistant.content) {\n if (block.type === 'toolCall') toolNames.set(brandString<ToolCallId>(block.id), block.name)\n }\n messages.push(assistant)\n}\n\nfunction textOnlyContext(options: GenerateOptions, onReplayDegrade?: (reason: string) => void): PiContext {\n assertSupportedImageRoles(options.messages)\n const split = splitSystemPrompt(options)\n const toolNames = new Map<ToolCallId, string>()\n const messages: PiMessage[] = []\n for (const message of split.messages) {\n if (contentHasImage(message.content)) {\n throw new LlmError('pi-ai image conversion requires the durable attachment service', 'UNSUPPORTED_CONTENT')\n }\n if (message.role === 'system') {\n messages.push({ role: 'user', content: flattenText(message), timestamp: 0 })\n continue\n }\n if (message.role === 'assistant') {\n appendAssistant(message, messages, toolNames, onReplayDegrade)\n continue\n }\n const text = flattenText(message)\n const results = message.content.filter(block => block.type === 'tool-result')\n if (text.length > 0 || results.length === 0) messages.push({ role: 'user', content: text, timestamp: 0 })\n for (const result of results) {\n messages.push({\n role: 'toolResult',\n toolCallId: result.toolCallId,\n toolName: toolNames.get(result.toolCallId) ?? 'unknown',\n content: [{\n type: 'text',\n text: toolResultText(result.content) || '(no output)',\n }],\n isError: result.isError ?? false,\n timestamp: 0,\n })\n }\n }\n return piContext(split.systemPrompt, options, messages)\n}\n\n/** Inputs that bind deterministic request images to one current tool execution world. */\nexport interface PiImageRequestContext {\n /** Durable provider that resolves request-image bytes and provider-owned host objects. */\n attachments: AttachmentStore\n /** Resolve current tool access separately from deterministic request-image versions. */\n resolveImageAccess: ImageAttachmentAccessResolver\n /** Request-level bound on the base64-encoded payload of retained images; omission leaves the bound unchecked. */\n maxRequestImageBytes?: number\n /** Route pixel and raw encoded-byte budgets. */\n requestImagePolicy?: PiImageRequestBudget\n}\n\n/** Per-route budgets from which each request image's target is derived. */\nexport interface PiImageRequestBudget {\n /** Total-pixel budget; larger sources are downscaled proportionally. */\n maxPixels: number\n /** Encoded-byte target for one request image. */\n maxBytes: number\n}\n\n/** Deterministic request target for one source under the route budgets. */\nfunction requestImageTarget(ref: ImageAttachmentRef, budget: PiImageRequestBudget): ImageRequestTarget {\n return { ...requestImageDimensions(ref.width, ref.height, budget.maxPixels), maxBytes: budget.maxBytes }\n}\n\n/**\n * Convert text-only harness history to a synchronous pi-ai Context. Tool\n * result names are recovered from preceding assistant tool calls.\n * @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.\n * @param images - absent; selects the synchronous conversion.\n * @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.\n * @returns the pi-ai context; `tools` is omitted when the request declares none.\n * @throws {LlmError} `UNSUPPORTED_CONTENT` for images in any history role, including a leading system message.\n */\nexport function toPiContext(\n options: GenerateOptions,\n images?: undefined,\n onReplayDegrade?: (reason: string) => void,\n): PiContext\n/**\n * Convert harness history to a pi-ai Context while resolving durable images.\n * Tool result names are recovered from preceding assistant tool calls. Image\n * occurrences the surface marks offloaded become text placeholders; when the\n * retained occurrences' exact base64 payload still exceeds\n * `maxRequestImageBytes`, the call fails with `IMAGE_OFFLOAD_REQUIRED` naming\n * how many more oldest occurrences must be offloaded.\n * @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.\n * @param images - attachment provider, current path resolver, and request limits.\n * @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.\n * @returns the asynchronously resolved pi-ai context.\n */\nexport function toPiContext(\n options: GenerateOptions,\n images: PiImageRequestContext,\n onReplayDegrade?: (reason: string) => void,\n): Promise<PiContext>\nexport function toPiContext(\n options: GenerateOptions,\n images?: PiImageRequestContext,\n onReplayDegrade?: (reason: string) => void,\n): PiContext | Promise<PiContext> {\n return images === undefined\n ? textOnlyContext(options, onReplayDegrade)\n : toPiContextWithImages(options, images, onReplayDegrade)\n}\n\nasync function toPiContextWithImages(\n options: GenerateOptions,\n images: PiImageRequestContext,\n onReplayDegrade?: (reason: string) => void,\n): Promise<PiContext> {\n const { attachments, resolveImageAccess, maxRequestImageBytes } = images\n const requestImagePolicy = images.requestImagePolicy ?? {\n maxPixels: DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET,\n maxBytes: DEFAULT_REQUEST_IMAGE_MAX_BYTES,\n }\n assertSupportedImageRoles(options.messages)\n const split = splitSystemPrompt(options)\n const requestImages = await prepareRequestImages(split.messages, attachments, requestImagePolicy, options.signal)\n if (maxRequestImageBytes !== undefined) {\n const offloadImages = requiredImageOffload(\n split.messages,\n { representation: 'base64', maxBytes: maxRequestImageBytes },\n block => (requestImages.get(block.attachment.attachmentId) as RequestImageAttachment).bytes,\n )\n if (offloadImages > 0) {\n throw new LlmError(\n `pi-ai request images exceed the ${maxRequestImageBytes}-byte base64 bound; ${offloadImages} more oldest occurrence(s) must be offloaded.`,\n IMAGE_OFFLOAD_REQUIRED_CODE,\n { offloadImages },\n )\n }\n }\n const exactMessages = projectOffloadedImages(\n split.messages,\n ref => offloadedImageText(ref, resolveImageAccess(ref)),\n )\n const toolNames = new Map<ToolCallId, string>()\n const messages: PiMessage[] = []\n\n for (const message of exactMessages) {\n if (message.role === 'system') {\n // pi-ai has a single systemPrompt slot; in-history system messages are\n // folded into user messages to preserve order (rare in practice — the\n // harness sends the system prompt via options.system).\n messages.push({ role: 'user', content: flattenText(message), timestamp: 0 })\n continue\n }\n if (message.role === 'assistant') {\n appendAssistant(message, messages, toolNames, onReplayDegrade)\n continue\n }\n // user role: text + tool results (each result becomes its own message).\n const regular = message.content.filter(block => block.type !== 'tool-result')\n const content = await userContent(regular, requestImages, resolveImageAccess)\n const results = message.content.filter((block): block is Extract<ContentBlock, { type: 'tool-result' }> => (\n block.type === 'tool-result'\n ))\n if (content.length > 0 || results.length === 0) {\n messages.push({ role: 'user', content, timestamp: 0 })\n }\n for (const result of results) {\n const resultContent = await userContent(result.content, requestImages, resolveImageAccess)\n messages.push({\n role: 'toolResult',\n toolCallId: result.toolCallId,\n toolName: toolNames.get(result.toolCallId) ?? 'unknown',\n content: typeof resultContent === 'string'\n ? [{ type: 'text', text: resultContent || '(no output)' }]\n : resultContent,\n isError: result.isError ?? false,\n timestamp: 0,\n })\n }\n }\n\n return piContext(split.systemPrompt, options, messages)\n}\n","/**\n * pi-ai assistant event translation into the ChatCode CLI streaming protocol.\n *\n * pi-ai tool-call arguments are parsed objects while ChatCode CLI keeps their\n * raw JSON representation. pi-ai also reports failures as terminal stream\n * events, which this module maps into ChatCode CLI finish chunks.\n *\n * @module dsh-llm-pi-ai/stream\n */\n\nimport { brandString } from '@deepseek-ai/dsh-brand'\nimport { CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError, QUOTA_EXCEEDED_CODE } from '@deepseek-ai/dsh-llm'\nimport type { FinishReason, StreamChunk, TokenUsage, ToolCallId } from '@deepseek-ai/dsh-llm'\nimport { isContextOverflow } from '@earendil-works/pi-ai'\nimport type { AssistantMessage, AssistantMessageEvent, Usage as PiUsage } from '@earendil-works/pi-ai'\nimport { toPiReplayState } from './replay.ts'\n\n/**\n * Map pi-ai usage (reasoning folded into output by pi-ai).\n * @param usage - cumulative usage from the terminal pi-ai event.\n * @returns harness counts with pi-ai's exact total; cache fields appear only\n * when non-zero (pi-ai reports zeros, not absence).\n */\nexport function mapUsage(usage: PiUsage): TokenUsage {\n return {\n inputTokens: usage.input,\n outputTokens: usage.output,\n totalTokens: usage.totalTokens,\n ...usage.cacheRead > 0 ? { cacheReadTokens: usage.cacheRead } : {},\n ...usage.cacheWrite > 0 ? { cacheWriteTokens: usage.cacheWrite } : {},\n }\n}\n\n// XXX(pi-ai upstream): pi-ai flattens the caught error to `error.message`\n// (api/anthropic-messages.js: `errorMessage = error instanceof Error ?\n// error.message : JSON.stringify(error)`), discarding the original Error and its\n// `cause` chain before it reaches us. undici carries the actionable transport\n// detail on `cause` (e.g. `SocketError: other side closed`) but hands the fetch\n// wrapper a bare `terminated`, so we are left pattern-matching terse words here.\n// If pi-ai ever forwards the original Error (or a fetch/dispatcher hook that lets\n// us capture the cause ourselves), classify on `code`/`cause` instead of text.\nfunction classifyPiAiError(message: string): string {\n if (/\\b(?:401|403)\\b/.test(message)) return 'AUTH'\n if (isQuotaExceededError(message)) return QUOTA_EXCEEDED_CODE\n if (/\\b429\\b|rate.?limit/i.test(message)) return 'RATE_LIMIT'\n // A rejected request body (gateway or provider size cap): resending the\n // same request cannot succeed, so it is invalid, not transient.\n if (/\\b413\\b|failed to buffer the request body:\\s*length limit exceeded|payload too large|request body too large/i.test(message)) return 'INVALID_REQUEST'\n if (/\\b400\\b|invalid.?request/i.test(message)) return 'INVALID_REQUEST'\n if (/\\b5\\d\\d\\b/.test(message)) return 'SERVER'\n if (/\\btime(?:d)?\\s*out\\b|timeout/i.test(message)) return 'TIMEOUT'\n // A stream truncated before the provider's terminal event: each pi-ai provider\n // throws its own wording when the wire closes mid-response without a terminal\n // event (`… stream ended before message_stop`, `… before a terminal response\n // event`, `… ended without a terminal event`, `Stream ended without\n // finish_reason`). The connection dropped mid-response, so this is a transport\n // truncation, not a model-level error.\n if (/stream ended (?:before|without)\\b/i.test(message)) return 'TRANSPORT'\n if (/\\b(?:network|connection|socket|fetch)\\b|\\bECONN[A-Z]+\\b/i.test(message)\n || /\\b(?:other side closed|HTTP2 request did not get a response|WebSocket closed unexpectedly)\\b/i.test(message)\n // undici renders a mid-stream socket drop as a bare `terminated` (its\n // `cause` — the real SocketError — was flattened away upstream); Node's\n // stream layer says `Premature close`.\n || /\\bterminated\\b|premature close/i.test(message)) {\n return 'TRANSPORT'\n }\n return 'PI_AI_ERROR'\n}\n\n/**\n * Map a terminal pi-ai event to the harness finish reason.\n * @param message - the assistant message carried by the `done` or `error` event.\n * @param contextWindow - resolved catalog capacity for usage-based overflow detection.\n * @returns the mapped harness reason. Recognized error text, `stop` usage above\n * `contextWindow`, and zero-output `length` usage that fills the window map\n * to `CONTEXT_WINDOW_EXCEEDED`; a `stop` with no content blocks maps to an\n * `EMPTY_RESPONSE` error, while terminal `pending` and `deferred` states map\n * to non-retryable `PI_AI_ERROR` failures.\n */\nexport function mapStopReason(message: AssistantMessage, contextWindow?: number): FinishReason {\n const piAiOverflow = isContextOverflow(message, contextWindow)\n const harnessOverflow = message.stopReason === 'error'\n && message.errorMessage !== undefined\n && isContextWindowExceededError(message.errorMessage)\n if (piAiOverflow || harnessOverflow) {\n return {\n kind: 'error',\n failure: {\n message: message.errorMessage ?? `pi-ai detected context overflow for model \"${message.model}\"`,\n code: CONTEXT_WINDOW_EXCEEDED_CODE,\n },\n }\n }\n\n switch (message.stopReason) {\n case 'stop':\n // A terminal stop that produced no content blocks is a degenerate\n // provider completion, not a successful (empty) assistant message.\n if (message.content.length === 0) {\n return {\n kind: 'error',\n failure: {\n message: `model \"${message.model}\" returned a completed response with no content`,\n code: EMPTY_RESPONSE_CODE,\n },\n }\n }\n return { kind: 'stop' }\n case 'length': return { kind: 'max-tokens' }\n case 'toolUse': return { kind: 'tool-calls' }\n case 'pending': return {\n kind: 'error',\n failure: { message: `pi-ai stream for model \"${message.model}\" ended pending`, code: 'PI_AI_ERROR' },\n }\n case 'deferred': return {\n kind: 'error',\n failure: { message: `pi-ai deferred response for model \"${message.model}\" is not supported`, code: 'PI_AI_ERROR' },\n }\n case 'aborted': return {\n kind: 'aborted',\n failure: { message: message.errorMessage ?? 'pi-ai stream aborted', code: 'ABORTED' },\n }\n case 'error': {\n const text = message.errorMessage ?? 'pi-ai stream error'\n return { kind: 'error', failure: { message: text, code: classifyPiAiError(text) } }\n }\n }\n}\n\n/**\n * Translate the pi-ai event stream into StreamChunks. pi-ai never throws\n * mid-stream — failures arrive as `error` events, which become error/aborted\n * `finish` chunks (the harness protocol's other error-delivery style).\n * @param events - one assistant turn's pi-ai event stream.\n * @param contextWindow - resolved catalog capacity for usage-based overflow detection.\n * @param callerSignal - caller cancellation state; an aborted caller makes any\n * in-band terminal error an aborted finish.\n * @returns the harness chunks, ending with `usage` then `finish`; throws\n * `LlmError` (`STREAM_CLOSED`) if the source ends without a terminal event.\n */\nexport async function* toStreamChunks(\n events: AsyncIterable<AssistantMessageEvent>,\n contextWindow?: number,\n callerSignal?: AbortSignal,\n): AsyncGenerator<StreamChunk> {\n // pi-ai contentIndex ↔ our block index map 1:1 (both count blocks from 0\n // in stream order), but we track ids per index for tool calls.\n const toolIds = new Map<number, { id: string; name: string }>()\n\n for await (const event of events) {\n switch (event.type) {\n case 'start':\n break\n case 'text_start':\n yield { type: 'block-start', index: event.contentIndex, blockType: 'text' }\n break\n case 'text_delta':\n yield { type: 'text-delta', index: event.contentIndex, text: event.delta }\n break\n case 'text_end':\n yield { type: 'block-end', index: event.contentIndex, block: { type: 'text', text: event.content } }\n break\n case 'thinking_start':\n yield { type: 'block-start', index: event.contentIndex, blockType: 'reasoning' }\n break\n case 'thinking_delta':\n yield { type: 'reasoning-delta', index: event.contentIndex, text: event.delta }\n break\n case 'thinking_end':\n yield { type: 'block-end', index: event.contentIndex, block: { type: 'reasoning', text: event.content } }\n break\n case 'toolcall_start': {\n // The id/name live on the partial's content at this index.\n const partial = event.partial.content[event.contentIndex]\n const id = partial?.type === 'toolCall' ? partial.id : ''\n const name = partial?.type === 'toolCall' ? partial.name : ''\n toolIds.set(event.contentIndex, { id, name })\n yield { type: 'block-start', index: event.contentIndex, blockType: 'tool-call' }\n break\n }\n case 'toolcall_delta': {\n const known = toolIds.get(event.contentIndex)\n yield {\n type: 'tool-call-delta',\n index: event.contentIndex,\n id: brandString<ToolCallId>(known?.id ?? ''),\n ...known?.name !== undefined && known.name.length > 0 ? { name: known.name } : {},\n argumentsDelta: event.delta,\n }\n break\n }\n case 'toolcall_end':\n yield {\n type: 'block-end',\n index: event.contentIndex,\n block: {\n type: 'tool-call',\n id: brandString<ToolCallId>(event.toolCall.id),\n name: event.toolCall.name,\n // pi-ai hands back the PARSED arguments; the harness vocabulary\n // keeps the raw string.\n arguments: JSON.stringify(event.toolCall.arguments),\n },\n }\n break\n case 'done':\n yield { type: 'usage', usage: mapUsage(event.message.usage) }\n yield {\n type: 'finish',\n reason: mapStopReason(event.message, contextWindow),\n replayState: toPiReplayState(event.message),\n }\n return\n case 'error':\n // In-stream error delivery (pi-ai's style) → error finish chunk\n // (the harness's other sanctioned error path besides throwing).\n yield { type: 'usage', usage: mapUsage(event.error.usage) }\n yield {\n type: 'finish',\n reason: mapStopReason(\n callerSignal?.aborted ? { ...event.error, stopReason: 'aborted' } : event.error,\n contextWindow,\n ),\n }\n return\n // no default: AssistantMessageEvent is pi-ai's closed union; a new\n // event type should fail compilation here via tsc's exhaustiveness\n // when one is added (switch covers all current variants).\n }\n }\n throw new LlmError('pi-ai event stream ended without done/error', 'STREAM_CLOSED')\n}\n","/**\n * Generic pi-ai-backed implementation of the ChatCode CLI LLM seam.\n *\n * Each resolution produces one **immutable** snapshot — the profiles plus a\n * `Models` collection holding the `Provider` each route built — and an\n * operation captures a whole snapshot before its first `await`. A\n * configuration change builds a *new* collection rather than mutating the one\n * in use, because `Models.streamSimple()` is lazy: it resolves the provider\n * when the stream is first consumed, which is after the credential await, so a\n * mutated collection would let a request that started under one configuration\n * finish under another — or fail with a provider that no longer exists. This is\n * what makes the seam's per-step call freeze (`llm.prepareCall()`) hold all the\n * way down: switching models mid-reply takes effect on the next step, never\n * inside the one in flight.\n *\n * A route naming a credential reference still resolves it through the harness\n * seam and passes it as the request's `apiKey` option, which pi-ai treats as\n * the highest-priority auth override — that is what keeps the fail-loud\n * reference semantics. Everything that override does not cover reaches pi-ai\n * through the collection's own auth: the credential store holds the records a\n * login wrote and a refresh rotates, and the auth context answers the ambient\n * questions a provider asks while resolving. Both are stable across snapshots,\n * so a configuration change rebuilds the collection without forgetting who is\n * signed in.\n *\n * @module dsh-llm-pi-ai/adapter\n */\n\nimport { createModels, getSupportedThinkingLevels } from '@earendil-works/pi-ai'\nimport type {\n Api,\n AuthContext,\n CredentialStore,\n Model,\n Models,\n ModelThinkingLevel,\n MutableModels,\n SimpleStreamOptions,\n ThinkingLevel,\n} from '@earendil-works/pi-ai'\nimport {\n attributionHeaders,\n contentHasImage,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\n} from '@deepseek-ai/dsh-llm'\nimport type {\n GenerateOptions,\n ImageAttachmentAccess,\n LlmModelInfo,\n LlmProviderInfo,\n LlmResolvedModelInfo,\n PreparedAdapterCall,\n ReasoningEffortId as ReasoningEffortIdType,\n ResolvedRetryPolicy,\n StreamChunk,\n} from '@deepseek-ai/dsh-llm'\nimport type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\nimport { idleWatchdog, timeoutOf } from '@deepseek-ai/dsh-timeout'\nimport type { ResolvedPiAiProviderProfile } from './config.ts'\nimport { toPiContext } from './context.ts'\nimport { toStreamChunks } from './stream.ts'\n\n/** One resolution's frozen view: the profiles and the collection built from them. */\ninterface PiAiSnapshot {\n /** The resolved profiles this collection was built from, used as its identity. */\n profiles: ReadonlyMap<string, ResolvedPiAiProviderProfile>\n /** Providers for exactly those profiles; never mutated once published. */\n models: Models\n}\n\n/** Credentials and headers resolved privately for one request, never advertised as model metadata. */\nexport interface PiAiRequestAuth {\n /** Request API key; omission leaves authentication to provider auth or the supplied headers. */\n apiKey?: string\n /** Authentication headers overriding profile headers; host attribution remains reserved. */\n headers?: Record<string, string>\n}\n\n/** Constructor options for {@link PiAiAdapter}: the resolution hooks the plugin owns. */\nexport interface PiAiAdapterOptions {\n /** Current validated profiles by provider route; called once per operation. */\n profiles: () => ReadonlyMap<string, ResolvedPiAiProviderProfile>\n /**\n * Resolve credentials for one already-resolved profile; called once per\n * stream call and frozen for that call. An empty result defers to the route's own\n * pi-ai auth, which for an installed catalog route is its provider-native\n * ambient discovery; the plugin allows that only for a profile naming no\n * credential at all, because a named reference that misses throws `LlmError`\n * `MISSING_CREDENTIAL` rather than falling back.\n */\n resolveAuth: (provider: string, profile: ResolvedPiAiProviderProfile) => Promise<PiAiRequestAuth>\n /**\n * How every collection this adapter builds resolves auth the request-level\n * `apiKey` override does not cover. Required rather than optional: a\n * collection built without them gets pi-ai's in-memory default store, which\n * is empty at every boot and discarded on every configuration change, so a\n * route whose only method is a login would report itself unconfigured on\n * every request no matter how often the human signed in.\n */\n auth: PiAiAuthInjection\n /** Resolve the optional durable attachment service at request time. */\n resolveAttachments?: () => AttachmentStore | undefined\n /** Bridge one attachment reference into the current model-tool execution world. */\n resolveImageAccess?: (attachments: AttachmentStore, ref: ImageAttachmentRef) => ImageAttachmentAccess | undefined\n /**\n * Observe one assistant history message degrading to provider-neutral\n * conversion because its stored replay state is unusable by this build.\n */\n onReplayDegrade?: (detail: { provider: string; model: string; reason: string }) => void\n}\n\n/** The two auth injectables a pi-ai collection is built with. */\nexport interface PiAiAuthInjection {\n /** Durable storage for credentials pi-ai itself writes: logins, and the refreshes it runs under its own lock. */\n credentials: CredentialStore\n /** Ambient lookups a provider performs while resolving its own auth. */\n authContext: AuthContext\n}\n\n/** Copy profile stream knobs into pi-ai's common option vocabulary. */\nfunction profileOptions(\n profile: ResolvedPiAiProviderProfile,\n reasoning: ModelThinkingLevel | undefined,\n apiKey: string | undefined,\n): SimpleStreamOptions {\n const enabledReasoning: ThinkingLevel | undefined = reasoning === 'off' ? undefined : reasoning\n return {\n ...apiKey === undefined ? {} : { apiKey },\n ...enabledReasoning === undefined ? {} : { reasoning: enabledReasoning },\n ...profile.reasoningSplit === undefined ? {} : { samplingParams: { reasoning_split: profile.reasoningSplit } },\n ...profile.thinkingBudgets === undefined ? {} : { thinkingBudgets: profile.thinkingBudgets },\n ...profile.cacheRetention === undefined ? {} : { cacheRetention: profile.cacheRetention },\n ...profile.transport === undefined ? {} : { transport: profile.transport },\n ...profile.timeoutMs === undefined ? {} : { timeoutMs: profile.timeoutMs },\n ...profile.websocketConnectTimeoutMs === undefined ? {} : { websocketConnectTimeoutMs: profile.websocketConnectTimeoutMs },\n // The agent recovery layer owns visible attempts; one adapter call is one SDK attempt.\n maxRetries: 0,\n }\n}\n\n/**\n * The profile default this exact model can actually take, for DESCRIBING it.\n * A configured level the model does not support yields none rather than\n * throwing: `resolveModel` builds the model catalog, and a catalog that fails\n * takes its whole provider out of every picker — so one mis-set profile field\n * would hide every model on the route, including the ones that support the\n * level. The request path still refuses, which is where a bad configuration\n * belongs: describing what a model can do must not fail because a deployment\n * asked it for something it cannot.\n * @param model - the resolved model descriptor.\n * @param effort - the profile's configured level, if any.\n * @returns the level when this model supports it, otherwise undefined.\n */\nfunction describableReasoningLevel(\n model: Model<Api>,\n effort: ReasoningEffortIdType | ModelThinkingLevel | undefined,\n): ModelThinkingLevel | undefined {\n if (effort === undefined) return undefined\n return getSupportedThinkingLevels(model).some(level => level === effort)\n ? effort as ModelThinkingLevel\n : undefined\n}\n\n/** Validate an explicit ChatCode CLI profile effort without invoking pi-ai's clamp. */\nfunction resolveReasoningLevel(\n model: Model<Api>,\n effort: ReasoningEffortIdType | ModelThinkingLevel | undefined,\n): ModelThinkingLevel | undefined {\n if (effort === undefined) return undefined\n const supported = getSupportedThinkingLevels(model)\n if (supported.some(level => level === effort)) return effort as ModelThinkingLevel\n throw new LlmError(\n `pi-ai provider \"${model.provider}\" model \"${model.id}\" does not support reasoning effort \"${effort}\"`,\n 'UNSUPPORTED_REASONING_EFFORT',\n )\n}\n\n/**\n * Selectable reasoning efforts for one model, or nothing at all.\n *\n * A model that carries no reasoning metadata — every hand-declared one, and\n * every catalog model pi-ai marks as non-reasoning — is reported by pi-ai as\n * supporting the single level `off`. Passing that through would offer a control\n * that cannot do what it says: `off` is translated to *omitting* the reasoning\n * option, which for such a model is byte-for-byte the same request as naming no\n * effort — so a provider whose own default is to think would keep thinking with\n * `off` selected. Omitting `reasoning` entirely is the seam's way of saying the\n * capability is unavailable, which leaves the surface offering only the\n * provider's default.\n * @param model - the resolved model descriptor.\n * @param defaultLevel - the profile's configured effort, already validated.\n * @returns the `reasoning` field, or an empty object when none can be offered.\n */\nfunction reasoningInfo(\n model: Model<Api>,\n defaultLevel: ModelThinkingLevel | undefined,\n): Pick<LlmResolvedModelInfo, 'reasoning'> | Record<string, never> {\n if (!model.reasoning) return {}\n const levels = getSupportedThinkingLevels(model)\n return {\n reasoning: {\n efforts: levels.map(level => ({\n id: ReasoningEffortId(level),\n name: `${level.charAt(0).toUpperCase()}${level.slice(1)}`,\n })),\n ...defaultLevel === undefined ? {} : { defaultEffort: ReasoningEffortId(defaultLevel) },\n },\n }\n}\n\n/** Merge deployment headers while removing case-insensitive attribution collisions. */\nfunction requestHeaders(\n headers: Readonly<Record<string, string>> | undefined,\n auth: Readonly<Record<string, string>> | undefined,\n): Record<string, string> {\n const attribution = attributionHeaders()\n const reserved = new Set([...Object.keys(attribution), ...Object.keys(auth ?? {})].map(name => name.toLowerCase()))\n return {\n ...Object.fromEntries(Object.entries(headers ?? {}).filter(([name]) => !reserved.has(name.toLowerCase()))),\n ...Object.fromEntries(Object.entries(auth ?? {}).filter(([name]) =>\n !Object.keys(attribution).some(reservedName => reservedName.toLowerCase() === name.toLowerCase()))),\n ...attribution,\n }\n}\n\n/**\n * pi-ai-backed multi-provider adapter. Each operation reads the current\n * profiles, so a configuration change reaches the next request without a\n * restart; model descriptors come from the collection those profiles built.\n */\nexport class PiAiAdapter extends LlmAdapter {\n private snapshot: PiAiSnapshot | undefined\n\n constructor(private readonly config: PiAiAdapterOptions) {\n super()\n }\n\n /**\n * The snapshot for the current profiles. Resolution memoizes its result, so\n * an unchanged configuration is recognized by identity; a changed one gets a\n * brand-new collection, leaving any snapshot an operation already captured\n * untouched for as long as that operation holds it.\n */\n private current(): PiAiSnapshot {\n const profiles = this.config.profiles()\n if (this.snapshot?.profiles === profiles) return this.snapshot\n const models: MutableModels = createModels(this.config.auth)\n for (const profile of profiles.values()) models.setProvider(profile.piProvider)\n this.snapshot = { profiles, models }\n return this.snapshot\n }\n\n /** The profile for one route within one snapshot, or the not-owned failure. */\n private profileOf(snapshot: PiAiSnapshot, provider: string): ResolvedPiAiProviderProfile {\n const profile = snapshot.profiles.get(provider)\n if (profile === undefined) {\n throw new LlmError(`pi-ai adapter does not own provider \"${provider}\"`, 'NO_ADAPTER')\n }\n return profile\n }\n\n /** The configured descriptor for one exact route/model pair within one snapshot. */\n private modelOf(snapshot: PiAiSnapshot, provider: string, model: string): Model<Api> {\n this.profileOf(snapshot, provider)\n const resolved = snapshot.models.getModel(provider, model)\n if (resolved === undefined) {\n throw new LlmError(`pi-ai provider \"${provider}\" has no configured model \"${model}\"`, 'UNKNOWN_MODEL')\n }\n return resolved\n }\n\n override providerInfo(provider: string): LlmProviderInfo {\n // The configured name, not the route key: `displayName` exists so a\n // deployment can label a route, and a label only the configuration surface\n // reads would leave every selector showing the raw key.\n return { id: provider, name: this.current().profiles.get(provider)?.displayName ?? provider }\n }\n\n override providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {\n return this.current().profiles.get(provider)?.retryPolicy\n }\n\n override listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n return Promise.resolve().then(() => {\n const snapshot = this.current()\n this.profileOf(snapshot, provider)\n return snapshot.models.getModels(provider).map(model => ({\n provider,\n id: model.id,\n name: model.name,\n inputModalities: [...model.input],\n }))\n })\n }\n\n override resolveModel(\n provider: string,\n model: string,\n _signal?: AbortSignal,\n ): Promise<LlmResolvedModelInfo> {\n return Promise.resolve().then(() => {\n const snapshot = this.current()\n return this.modelInfo(snapshot, provider, model)\n })\n }\n\n private modelInfo(snapshot: PiAiSnapshot, provider: string, model: string): LlmResolvedModelInfo {\n const profile = this.profileOf(snapshot, provider)\n const resolvedModel = this.modelOf(snapshot, provider, model)\n const defaultLevel = describableReasoningLevel(resolvedModel, profile.reasoning)\n // Only a cap the deployment configured is a request default; the\n // catalog's `maxTokens` sizes the model and stops there.\n const configuredMaxTokens = profile.configuredMaxTokens.get(model)\n return {\n provider,\n id: model,\n name: resolvedModel.name,\n inputModalities: [...resolvedModel.input],\n context: { contextWindow: resolvedModel.contextWindow },\n ...configuredMaxTokens === undefined ? {} : { defaultMaxTokens: configuredMaxTokens },\n ...reasoningInfo(resolvedModel, defaultLevel),\n }\n }\n\n override prepareCall(provider: string, model: string, _signal?: AbortSignal): Promise<PreparedAdapterCall> {\n const snapshot = this.current()\n return Promise.resolve({\n model: this.modelInfo(snapshot, provider, model),\n stream: options => this.streamWithSnapshot(options, snapshot),\n })\n }\n\n stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n return this.streamWithSnapshot(options, this.current())\n }\n\n private async * streamWithSnapshot(\n options: GenerateOptions,\n snapshot: PiAiSnapshot,\n ): AsyncIterable<StreamChunk> {\n if (options.stop !== undefined) {\n throw new LlmError('llm-pi-ai does not support GenerateOptions.stop', 'UNSUPPORTED_OPTION')\n }\n // One capture per stream call, taken before any await: the profile, the\n // model descriptor, and the collection all come from the same immutable\n // snapshot, and the credential freezes with them. A configuration change\n // mid-request builds a separate snapshot, so this request finishes under\n // the one it started with and the next call picks up the new one.\n const profile = this.profileOf(snapshot, options.provider)\n const model = this.modelOf(snapshot, options.provider, options.model)\n const reasoning = resolveReasoningLevel(\n model,\n options.reasoningEffort ?? profile.reasoning,\n )\n const auth = await this.config.resolveAuth(options.provider, profile)\n\n const consumer = new AbortController()\n const upstream = options.signal === undefined\n ? consumer.signal\n : AbortSignal.any([options.signal, consumer.signal])\n const streamIdleTimeoutMs = profile.streamIdleTimeoutMs\n using watchdog = idleWatchdog(upstream, streamIdleTimeoutMs, 'LLM_STREAM_IDLE_TIMEOUT')\n\n try {\n const containsImage = options.messages.some(message => contentHasImage(message.content))\n if (containsImage && !model.input.includes('image')) {\n throw new LlmError(`pi-ai model \"${model.id}\" does not support image input`, 'UNSUPPORTED_CONTENT')\n }\n const attachments = containsImage ? this.config.resolveAttachments?.() : undefined\n if (containsImage && attachments === undefined) {\n throw new LlmError('pi-ai image input requires the durable attachment service', 'UNSUPPORTED_CONTENT')\n }\n const onReplayDegrade = (reason: string): void => {\n this.config.onReplayDegrade?.({ provider: options.provider, model: options.model, reason })\n }\n const context = attachments === undefined\n ? toPiContext(options, undefined, onReplayDegrade)\n : await toPiContext({ ...options, signal: watchdog.signal }, {\n attachments,\n resolveImageAccess: ref => this.config.resolveImageAccess?.(attachments, ref),\n maxRequestImageBytes: profile.maxRequestImageBytes,\n requestImagePolicy: {\n maxPixels: profile.requestImagePixelBudget,\n maxBytes: profile.requestImageMaxBytes,\n },\n }, onReplayDegrade)\n const events = snapshot.models.streamSimple(model, context, {\n ...profileOptions(profile, reasoning, auth.apiKey),\n ...options.temperature === undefined ? {} : { temperature: options.temperature },\n ...options.maxTokens === undefined ? {} : { maxTokens: options.maxTokens },\n ...options.sessionId === undefined ? {} : { sessionId: String(options.sessionId) },\n signal: watchdog.signal,\n // Profile headers are deployment-owned; attribution names are\n // Host-owned and therefore win collisions.\n headers: requestHeaders(profile.headers, auth.headers),\n })\n const iterator = toStreamChunks(events, model.contextWindow, options.signal)[Symbol.asyncIterator]()\n let exhausted = false\n try {\n while (true) {\n const result = await watchdog.next(iterator)\n const timeout = timeoutOf(watchdog.signal, 'LLM_STREAM_IDLE_TIMEOUT')\n if (timeout !== undefined) throw timeout\n if (result.done) {\n exhausted = true\n return\n }\n yield result.value\n }\n } finally {\n if (!exhausted) {\n consumer.abort('pi-ai stream consumer stopped')\n try {\n await iterator.return(undefined)\n } catch (_abortedSdkTeardown) {\n // The stable signal already owns SDK termination; return-time abort cannot add an outcome.\n }\n }\n }\n } catch (error: unknown) {\n if (timeoutOf(watchdog.signal, 'LLM_STREAM_IDLE_TIMEOUT') !== undefined) {\n throw new LlmError(`pi-ai stream idle timeout after ${streamIdleTimeoutMs}ms`, 'TIMEOUT', { cause: error })\n }\n if (options.signal?.aborted) {\n throw new LlmError('pi-ai request aborted by caller', 'ABORTED', { cause: error })\n }\n throw error\n } finally {\n consumer.abort('pi-ai stream consumer stopped')\n }\n }\n}\n","/** Aggregate imported models while dispatching each private route through its selected adapter. @module dsh-llm-chatcode-config/adapter */\n\nimport { LlmAdapter, LlmError } from '@deepseek-ai/dsh-llm'\nimport { getOrCreateAnonymousUserId } from '@deepseek-ai/dsh-anonymous-user-id'\nimport { DeepSeekAdapter, resolveAdapterOptions } from '@deepseek-ai/dsh-llm-deepseek'\nimport type {\n GenerateOptions,\n LlmModelInfo,\n LlmProviderInfo,\n LlmResolvedModelInfo,\n PreparedAdapterCall,\n ResolvedRetryPolicy,\n StreamChunk,\n} from '@deepseek-ai/dsh-llm'\nimport { PiAiAdapter } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport type { PiAiAdapterOptions } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport { isolatedPiAiAuth } from '../vendor/dsh-llm-pi-ai/src/auth.ts'\nimport type { ResolvedPiAiProviderProfile } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { ChatCodeModelSelection, ChatCodeSource } from './source.ts'\n\n/** One public provider route containing every imported ChatCode custom model. */\nexport const CHATCODE_PROVIDER = 'chatcode-custom'\n/** Display name for the unified imported-model group. */\nexport const CHATCODE_PROVIDER_NAME = '自定义模型'\n/** Provider route and selector group for centrally managed Coding Plan models. */\nexport const CODING_PLAN_PROVIDER = 'chatcode-codingplan'\nexport const CODING_PLAN_PROVIDER_NAME = '内置模型'\n/** Provider route and selector group for opt-in MAAS models. */\nexport const MAAS_PROVIDER = 'chatcode-maas'\nexport const MAAS_PROVIDER_NAME = '元景'\n\ninterface PrivateSelection extends ChatCodeModelSelection {\n selection: string\n}\n\nconst DEEPSEEK_MODEL = /deepseek/i\n\nfunction privateModelKey(route: string, model: string): string {\n return `${route}\\u0000${model}`\n}\n\nfunction createDeepSeekAdapter(\n route: string,\n profile: ResolvedPiAiProviderProfile,\n model: ReturnType<ResolvedPiAiProviderProfile['piProvider']['getModels']>[number],\n apiKey: string | undefined,\n): DeepSeekAdapter {\n const protocol = profile.api === 'anthropic-messages'\n ? 'messages'\n : profile.api === 'openai-completions'\n ? 'chat-completions'\n : undefined\n if (protocol === undefined || profile.baseURL === undefined) {\n throw new LlmError(`chatcode-config: DeepSeek model route \"${route}\" has no supported protocol or base URL`, 'INVALID_CHATCODE_CONFIG')\n }\n const connection = {\n ...resolveAdapterOptions({\n protocol,\n baseURL: profile.baseURL,\n defaultContextWindow: model.contextWindow,\n maxTokens: model.maxTokens,\n models: [{\n id: model.id,\n name: model.name,\n contextWindow: model.contextWindow,\n maxTokens: model.maxTokens,\n inputModalities: [...model.input],\n }],\n streamIdleTimeoutMs: profile.streamIdleTimeoutMs,\n }),\n retryPolicy: profile.retryPolicy,\n }\n return new DeepSeekAdapter({\n options: () => connection,\n resolveApiKey: () => {\n if (apiKey === undefined) {\n throw new LlmError(`chatcode-config: no API key for DeepSeek model \"${model.id}\"`, 'MISSING_CREDENTIAL')\n }\n return Promise.resolve(apiKey)\n },\n resolveUserId: () => getOrCreateAnonymousUserId(),\n prepareExtensions: () => Promise.resolve({ fields: {}, accept: () => Promise.resolve() }),\n })\n}\n\n/** A static unified ChatCode catalog with request adapters selected from actual model ids. */\nexport class ChatCodeAdapter extends LlmAdapter {\n private readonly piAdapter: PiAiAdapter\n private readonly deepSeekAdapters = new Map<string, LlmAdapter>()\n private readonly routes = new Map<string, PrivateSelection>()\n private readonly publicModels = new Map<string, string>()\n\n constructor(\n options: PiAiAdapterOptions,\n private readonly profiles: ReadonlyMap<string, ResolvedPiAiProviderProfile>,\n private readonly provider = CHATCODE_PROVIDER,\n private readonly providerName = CHATCODE_PROVIDER_NAME,\n selections?: ReadonlyMap<string, ChatCodeModelSelection>,\n apiKeys: ReadonlyMap<string, string> = new Map(),\n ) {\n super()\n this.piAdapter = new PiAiAdapter(options)\n for (const [route, profile] of profiles) for (const model of profile.piProvider.getModels()) {\n const selection = [...(selections ?? new Map<string, ChatCodeModelSelection>())]\n .find(([, target]) => target.route === route && target.model === model.id)?.[0] ?? model.id\n if (this.routes.has(selection)) {\n throw new LlmError(`chatcode-config provider has duplicate public model \"${selection}\"`, 'INVALID_CHATCODE_CONFIG')\n }\n this.routes.set(selection, { selection, route, model: model.id })\n this.publicModels.set(privateModelKey(route, model.id), selection)\n if (DEEPSEEK_MODEL.test(model.id)) {\n this.deepSeekAdapters.set(privateModelKey(route, model.id), createDeepSeekAdapter(route, profile, model, apiKeys.get(route)))\n }\n }\n }\n\n private requestAdapter(target: ChatCodeModelSelection): LlmAdapter {\n return this.deepSeekAdapters.get(privateModelKey(target.route, target.model)) ?? this.piAdapter\n }\n\n /** Reject routes outside the one public provider registered by this adapter. */\n private assertProvider(provider: string): void {\n if (provider !== this.provider) {\n throw new LlmError(`chatcode-config adapter does not own provider \"${provider}\"`, 'NO_ADAPTER')\n }\n }\n\n /** Resolve the private route for one publicly selected model. */\n private routeOf(provider: string, model: string): PrivateSelection {\n this.assertProvider(provider)\n const target = this.routes.get(model)\n if (target === undefined) {\n throw new LlmError(`chatcode-config provider has no configured model \"${model}\"`, 'UNKNOWN_MODEL')\n }\n return target\n }\n\n private validateOutput(options: GenerateOptions, target: PrivateSelection): void {\n const ceiling = this.profiles.get(target.route)?.configuredMaxTokens.get(target.model)\n if (ceiling !== undefined && options.maxTokens !== undefined && options.maxTokens > ceiling) {\n throw new LlmError('chatcode-config: maxTokens exceeds the configured model output limit', 'UNSUPPORTED_OPTION')\n }\n }\n\n override providerInfo(provider: string): LlmProviderInfo {\n this.assertProvider(provider)\n return { id: provider, name: this.providerName }\n }\n\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined {\n return this.profiles.values().next().value?.retryPolicy\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n this.assertProvider(provider)\n const catalogs = await Promise.all([...this.profiles.keys()].map(async route => ({\n route,\n models: await this.piAdapter.listModels(route),\n })))\n return catalogs.flatMap(({ route, models }) => models.map(model => ({\n ...model,\n id: this.publicModels.get(privateModelKey(route, model.id)) ?? model.id,\n provider: this.provider,\n })))\n }\n\n override async resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo> {\n const target = this.routeOf(provider, model)\n const resolved = await this.requestAdapter(target).resolveModel(target.route, target.model, signal)\n return { ...resolved, id: target.selection, provider: this.provider }\n }\n\n override async prepareCall(provider: string, model: string, signal?: AbortSignal): Promise<PreparedAdapterCall> {\n const target = this.routeOf(provider, model)\n const prepared = await this.requestAdapter(target).prepareCall(target.route, target.model, signal)\n return {\n model: { ...prepared.model, id: target.selection, provider: this.provider },\n stream: (options) => {\n const preparedTarget = this.routeOf(options.provider, options.model)\n this.validateOutput(options, preparedTarget)\n return prepared.stream({ ...options, provider: preparedTarget.route, model: preparedTarget.model })\n },\n }\n }\n\n override stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n const target = this.routeOf(options.provider, options.model)\n this.validateOutput(options, target)\n return this.requestAdapter(target).stream({ ...options, provider: target.route, model: target.model })\n }\n}\n\n/** Live custom-model adapter whose prepared calls retain their starting settings snapshot. */\nexport class LiveChatCodeAdapter extends LlmAdapter {\n private snapshot?: { source: ChatCodeSource; adapter: ChatCodeAdapter }\n\n constructor(\n private readonly source: () => ChatCodeSource,\n private readonly provider = CHATCODE_PROVIDER,\n private readonly providerName = CHATCODE_PROVIDER_NAME,\n ) { super() }\n\n private current(): ChatCodeAdapter {\n const source = this.source()\n if (this.snapshot?.source === source) return this.snapshot.adapter\n const adapter = new ChatCodeAdapter({\n profiles: () => source.profiles,\n resolveAuth: (route) => {\n const auth = source.auth.get(route)\n if (auth === undefined) {\n throw new LlmError('chatcode-config: missing auth for resolved profile', 'INVARIANT')\n }\n return Promise.resolve(auth)\n },\n auth: isolatedPiAiAuth(),\n }, source.profiles, this.provider, this.providerName, source.selections, source.apiKeys)\n this.snapshot = { source, adapter }\n return adapter\n }\n\n override providerInfo(provider: string): LlmProviderInfo {\n return this.current().providerInfo(provider)\n }\n\n override providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {\n return this.current().providerRetryPolicy(provider)\n }\n\n override listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n return this.current().listModels(provider)\n }\n\n override resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo> {\n return this.current().resolveModel(provider, model, signal)\n }\n\n override prepareCall(provider: string, model: string, signal?: AbortSignal): Promise<PreparedAdapterCall> {\n return this.current().prepareCall(provider, model, signal)\n }\n\n override stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n return this.current().stream(options)\n }\n}\n","/** ChatCode session login and its shared, host-only credential record. */\nimport { randomUUID } from 'node:crypto'\nimport { setTimeout as wait } from 'node:timers/promises'\nimport { Service } from '@deepseek-ai/cordis'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { credentialKey } from '@deepseek-ai/dsh-credentials'\nimport type { CredentialProvider, CredentialRecord } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\n\n/** Keep the address stable for grants written by the initial implementation. */\nexport const CHATCODE_CREDENTIAL_KEY = credentialKey('chatcode-auth', 'default')\n/** Process-scoped credential accepted from immutable desktop/terminal launchers. */\nexport const CHATCODE_CLI_OAUTH_TOKEN = 'CHATCODE_CLI_OAUTH_TOKEN'\nexport interface ChatCodeGrant {\n version: 1\n accessToken: string\n refreshToken?: string\n longToken?: string\n expiresAtMs?: number\n userName?: string\n emailAddress?: string\n}\nexport interface ChatCodeLoginState {\n sessionId: string\n state: 'pending' | 'succeeded' | 'failed' | 'timed-out' | 'cancelled'\n expiresAtMs: number\n}\n/** Safe UI projection: never add a token or raw upstream response here. */\nexport interface ChatCodeAuthStatus {\n required: boolean\n configured: boolean\n expired: boolean\n validation: 'valid' | 'invalid' | 'unavailable' | 'none'\n expiresAtMs?: number\n userName?: string\n emailAddress?: string\n login?: ChatCodeLoginState\n}\nexport interface ChatCodeLoginStart { sessionId: string; url: string }\nexport interface ChatCodeStatusOptions {\n /** Bypass the short validation cache and contact the account service again. */\n force?: boolean\n}\nexport interface ChatCodeAuthOptions {\n requireLogin?: boolean\n loginUrl: string\n apiBaseUrl: string\n pollIntervalMs: number\n pollTimeoutMs: number\n requestTimeoutMs: number\n}\nexport interface ChatCodeAuthApi {\n status(options?: ChatCodeStatusOptions): Promise<ChatCodeAuthStatus>\n startLogin(): Promise<ChatCodeLoginStart>\n cancelLogin(sessionId: string): Promise<void>\n waitForLogin(sessionId: string, signal?: AbortSignal): Promise<ChatCodeLoginState['state']>\n logout(): Promise<void>\n /** Host-only accessor; presentation adapters must use status(). */\n accessToken(signal?: AbortSignal): Promise<string | undefined>\n /** Host-only launch fact; reveals presence, never the credential value. */\n environmentTokenActive(): boolean\n}\ninterface AccountState {\n version: 2\n grant?: ChatCodeGrant\n login?: ChatCodeLoginState\n validation?: 'valid' | 'invalid' | 'unavailable'\n checkedAtMs?: number\n}\ndeclare module '@deepseek-ai/cordis' {\n interface Context { chatcodeAuth: ChatCodeAuthService }\n}\nconst objectOf = (value: unknown): Record<string, unknown> => value !== null && typeof value === 'object' ? value as Record<string, unknown> : {}\nconst stringOf = (value: unknown): string | undefined => typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined\nconst finiteTime = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value) && value > 0 && value <= 8.64e15\n\nfunction endpoint(value: string): URL {\n const url = new URL(value)\n if (url.username || url.password || (url.protocol !== 'https:' && !(url.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname)))) {\n throw new Error('ChatCode endpoints require HTTPS (HTTP is allowed only on loopback).')\n }\n return url\n}\n/** Preserve the configured hash-router query while adding this attempt's UUID. */\nexport function loginUrlOf(loginUrl: string, sessionId: string): string {\n const url = endpoint(loginUrl)\n if (!url.hash) url.searchParams.set('sessionId', sessionId)\n else {\n const hash = url.hash.slice(1)\n const split = hash.indexOf('?')\n const route = split < 0 ? hash : hash.slice(0, split)\n const params = new URLSearchParams(split < 0 ? '' : hash.slice(split + 1))\n params.set('sessionId', sessionId)\n url.hash = `${route}?${params.toString()}`\n }\n return url.href\n}\n/** Decode both the original payload and the concurrency-safe envelope. */\nexport function grantOf(value: unknown): ChatCodeGrant | undefined {\n const envelope = objectOf(value)\n const candidate = envelope.version === 2 ? objectOf(envelope.grant) : envelope\n if (candidate.version !== 1 || !stringOf(candidate.accessToken)) return undefined\n for (const field of ['refreshToken', 'longToken', 'userName', 'emailAddress']) {\n if (candidate[field] !== undefined && typeof candidate[field] !== 'string') return undefined\n }\n if (candidate.expiresAtMs !== undefined && !finiteTime(candidate.expiresAtMs)) return undefined\n return {\n version: 1, accessToken: stringOf(candidate.accessToken)!,\n ...(candidate.refreshToken === undefined ? {} : { refreshToken: candidate.refreshToken as string }),\n ...(candidate.longToken === undefined ? {} : { longToken: candidate.longToken as string }),\n ...(candidate.userName === undefined ? {} : { userName: candidate.userName as string }),\n ...(candidate.emailAddress === undefined ? {} : { emailAddress: candidate.emailAddress as string }),\n ...(candidate.expiresAtMs === undefined ? {} : { expiresAtMs: candidate.expiresAtMs as number }),\n }\n}\nfunction stateOf(record: CredentialRecord | undefined): AccountState {\n const payload = objectOf(record?.kind === 'grant' ? record.payload : undefined)\n const grant = grantOf(payload)\n const state: AccountState = { version: 2, ...(grant ? { grant } : {}) }\n if (payload.version !== 2) return state\n const login = objectOf(payload.login)\n if (typeof login.sessionId === 'string' && finiteTime(login.expiresAtMs) && ['pending', 'succeeded', 'failed', 'timed-out', 'cancelled'].includes(String(login.state))) {\n state.login = { sessionId: login.sessionId, state: login.state as ChatCodeLoginState['state'], expiresAtMs: login.expiresAtMs }\n }\n if (['valid', 'invalid', 'unavailable'].includes(String(payload.validation)) && finiteTime(payload.checkedAtMs)) {\n state.validation = payload.validation as AccountState['validation'] & string\n state.checkedAtMs = payload.checkedAtMs\n }\n return state\n}\nfunction recordOf(state: AccountState): CredentialRecord {\n // The credentials seam accepts a JSON object; no undefined properties are emitted.\n return { kind: 'grant', payload: { ...state } }\n}\nfunction emailOf(value: unknown): string | undefined {\n const root = objectOf(value)\n const data = objectOf(root.data)\n for (const source of [data, objectOf(data.account), root]) {\n for (const key of ['email', 'emailAddress', 'userEmail', 'mail']) {\n const email = stringOf(source[key])\n if (email && email.length <= 320 && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email\n }\n }\n return undefined\n}\nfunction responseGrant(body: unknown, previous?: ChatCodeGrant): ChatCodeGrant | undefined {\n const data = objectOf(objectOf(body).data)\n const accessToken = stringOf(data.access_token)\n if (!accessToken) return undefined\n const expiresAtMs = typeof data.expires_in === 'number' && data.expires_in > 0 ? Date.now() + data.expires_in * 1000 : undefined\n const grant: ChatCodeGrant = { version: 1, accessToken }\n for (const [target, source] of [['refreshToken', 'refresh_token'], ['longToken', 'longToken'], ['userName', 'userName']] as const) {\n const value = stringOf(data[source]) ?? previous?.[target]\n if (value) grant[target] = value\n }\n if (finiteTime(expiresAtMs)) grant.expiresAtMs = expiresAtMs\n if (previous?.emailAddress) grant.emailAddress = previous.emailAddress\n // No new expiry means unknown; reusing an expired timestamp causes endless refreshes.\n return grant\n}\nfunction stale(grant: ChatCodeGrant): boolean {\n return grant.expiresAtMs !== undefined && grant.expiresAtMs <= Date.now() + 30_000\n}\n\n/**\n * Snapshot the desktop grant only from the inherited process environment.\n * Project/user .env files are deliberately excluded: this credential is an\n * explicit property of one host launch, not durable ChatCode CLI configuration.\n */\nexport function chatCodeEnvironmentToken(ctx: Context): string | undefined {\n return stringOf(launchEnvironmentOf(ctx).getFrom(CHATCODE_CLI_OAUTH_TOKEN, ['process'])?.value)\n}\n\n/** One protocol owner, shared across Web and TUI through credentials-local's file lock. */\nexport class ChatCodeAuthService extends Service implements ChatCodeAuthApi {\n private readonly lifetime = new AbortController()\n private readonly active = new Map<string, AbortController>()\n private readonly failures = new Map<string, ChatCodeLoginState>()\n private readonly tasks = new Set<Promise<void>>()\n /** A new host process must contact ChatCode once before trusting persisted validation metadata. */\n private startupValidationPending = true\n\n private readonly environmentAccessToken: string | undefined\n\n constructor(\n ctx: Context,\n private readonly credentials: CredentialProvider,\n private readonly options: ChatCodeAuthOptions,\n environmentAccessToken?: string,\n ) {\n super(ctx, 'chatcodeAuth')\n this.environmentAccessToken = stringOf(environmentAccessToken)\n endpoint(options.loginUrl)\n endpoint(options.apiBaseUrl)\n ctx.effect(() => async () => {\n this.lifetime.abort()\n await Promise.allSettled(this.tasks)\n }, 'chatcode-auth: stop pending requests')\n }\n\n private async mutate(fn: (state: AccountState) => Promise<AccountState | undefined>): Promise<AccountState> {\n try {\n const result = await this.credentials.modifyRecord(CHATCODE_CREDENTIAL_KEY, async record => {\n const next = await fn(stateOf(record))\n return next === undefined ? undefined : recordOf(next)\n })\n return stateOf(result)\n } catch {\n // Provider errors can include the credential document; never send them to UIs/logs.\n throw new Error('ChatCode credential operation failed; check the ChatCode CLI credential store permissions and availability.')\n }\n }\n\n private async ensure(signal?: AbortSignal, force = false): Promise<AccountState> {\n const combined = AbortSignal.any([this.lifetime.signal, ...(signal ? [signal] : []), AbortSignal.timeout(Math.min(20_000, this.options.requestTimeoutMs * 3))])\n combined.throwIfAborted()\n const state = await this.mutate(async current => {\n combined.throwIfAborted()\n const grant = current.grant\n if (!grant) {\n this.startupValidationPending = false\n return undefined\n }\n // The caller may poll status for presentation, but only the first read\n // in this host process contacts the company network automatically.\n // An explicit retry bypasses this guard after a transient outage.\n if (!force && !this.startupValidationPending) return undefined\n let next = grant\n let result: { validation: 'valid' | 'invalid' | 'unavailable'; emailAddress?: string }\n try {\n if (stale(grant)) {\n const refreshed = await this.refresh(grant, combined)\n if (refreshed.grant) next = refreshed.grant\n result = refreshed.grant ? await this.account(next, combined) : { validation: refreshed.validation }\n } else {\n result = await this.account(grant, combined)\n if (result.validation === 'invalid') {\n const refreshed = await this.refresh(grant, combined)\n if (refreshed.grant) {\n next = refreshed.grant\n result = await this.account(next, combined)\n } else result = { validation: refreshed.validation }\n }\n }\n } finally {\n this.startupValidationPending = false\n }\n // Persist rotated long tokens even if subsequent account validation is temporarily unavailable.\n if (result.emailAddress) next = { ...next, emailAddress: result.emailAddress }\n signal?.throwIfAborted()\n this.lifetime.signal.throwIfAborted()\n return { ...current, grant: next, validation: result.validation, checkedAtMs: Date.now() }\n })\n return state\n }\n\n async status(options: ChatCodeStatusOptions = {}): Promise<ChatCodeAuthStatus> {\n // An inference-scoped desktop token may not be authorized for the account\n // profile endpoint. Its validity is established by managed-catalog I/O;\n // do not read or mutate the durable credential record on this path.\n if (this.environmentAccessToken !== undefined) {\n return {\n required: this.options.requireLogin !== false,\n configured: true,\n expired: false,\n validation: 'valid',\n }\n }\n const state = await this.ensure(undefined, options.force === true)\n const grant = state.grant\n const login = state.login?.state === 'pending' ? this.failures.get(state.login.sessionId) ?? state.login : state.login\n return {\n required: this.options.requireLogin !== false,\n configured: grant !== undefined,\n expired: grant?.expiresAtMs !== undefined && grant.expiresAtMs <= Date.now(),\n validation: grant ? state.validation ?? 'unavailable' : 'none',\n ...(grant?.expiresAtMs === undefined ? {} : { expiresAtMs: grant.expiresAtMs }),\n ...(grant?.userName ? { userName: grant.userName } : {}),\n ...(grant?.emailAddress ? { emailAddress: grant.emailAddress } : {}),\n ...(login ? { login: login.state === 'pending' && login.expiresAtMs <= Date.now() ? { ...login, state: 'timed-out' as const } : login } : {}),\n }\n }\n\n async accessToken(signal?: AbortSignal): Promise<string | undefined> {\n signal?.throwIfAborted()\n if (this.environmentAccessToken !== undefined) return this.environmentAccessToken\n const state = await this.ensure(signal)\n signal?.throwIfAborted()\n return state.validation === 'valid' && state.grant && (state.grant.expiresAtMs === undefined || state.grant.expiresAtMs > Date.now()) ? state.grant.accessToken : undefined\n }\n\n environmentTokenActive(): boolean {\n return this.environmentAccessToken !== undefined\n }\n\n async startLogin(): Promise<ChatCodeLoginStart> {\n if (this.environmentAccessToken !== undefined) {\n throw new Error('ChatCode authentication is provided by the launch environment.')\n }\n this.lifetime.signal.throwIfAborted()\n const sessionId = randomUUID()\n const url = loginUrlOf(this.options.loginUrl, sessionId)\n const login: ChatCodeLoginState = { sessionId, state: 'pending', expiresAtMs: Date.now() + this.options.pollTimeoutMs }\n // Publish the attempt before returning its URL. A newer process's attempt wins.\n await this.mutate(async current => {\n this.lifetime.signal.throwIfAborted()\n for (const controller of this.active.values()) controller.abort()\n return { ...current, login }\n })\n this.failures.clear()\n const controller = new AbortController()\n this.active.set(sessionId, controller)\n const signal = AbortSignal.any([controller.signal, this.lifetime.signal, AbortSignal.timeout(this.options.pollTimeoutMs)])\n const task = this.pollAndCommit(login, signal).catch(async () => {\n const state = Date.now() >= login.expiresAtMs ? 'timed-out' : signal.aborted ? 'cancelled' : 'failed'\n const failed: ChatCodeLoginState = { ...login, state }\n try { await this.finish(failed) } catch { this.failures.set(sessionId, failed) }\n }).finally(() => { this.active.delete(sessionId); this.tasks.delete(task) })\n this.tasks.add(task)\n return { sessionId, url }\n }\n\n async logout(): Promise<void> {\n // The environment source has strict lifetime precedence. Logging out must\n // neither persist it nor destroy an unrelated stored identity underneath.\n if (this.environmentAccessToken !== undefined) return\n for (const controller of this.active.values()) controller.abort()\n await this.mutate(async current => ({ version: 2, ...(current.login ? { login: { ...current.login, state: 'cancelled' } } : {}) }))\n this.failures.clear()\n // Keep the token-free tombstone: other processes must not resurrect an old attempt.\n }\n\n async cancelLogin(sessionId: string): Promise<void> {\n this.active.get(sessionId)?.abort()\n await this.mutate(async current => current.login?.sessionId === sessionId && current.login.state === 'pending'\n ? { ...current, login: { ...current.login, state: 'cancelled' } } : undefined)\n }\n\n async waitForLogin(sessionId: string, signal?: AbortSignal): Promise<ChatCodeLoginState['state']> {\n const combined = AbortSignal.any([this.lifetime.signal, ...(signal ? [signal] : [])])\n while (true) {\n combined.throwIfAborted()\n const status = await this.status()\n if (status.login?.sessionId !== sessionId) return 'cancelled'\n if (status.login.state !== 'pending') return status.login.state\n await wait(this.options.pollIntervalMs, undefined, { signal: combined })\n }\n }\n\n private async finish(login: ChatCodeLoginState): Promise<void> {\n await this.mutate(async current => current.login?.sessionId === login.sessionId && current.login.state === 'pending' ? { ...current, login } : undefined)\n }\n\n private async pollAndCommit(login: ChatCodeLoginState, signal: AbortSignal): Promise<void> {\n let grant: ChatCodeGrant | undefined\n while (Date.now() < login.expiresAtMs) {\n signal.throwIfAborted()\n const current = await this.mutate(async () => undefined)\n if (current.login?.sessionId !== login.sessionId || current.login.state !== 'pending') return\n if (!grant) {\n const response = await this.request(`/caassist-api-lt/caassist/api/account/session/login?${new URLSearchParams({ sessionId: login.sessionId })}`, { method: 'GET', signal })\n if (response?.ok) grant = responseGrant(response.body)\n }\n if (grant) {\n const account = await this.account(grant, signal)\n if (account.validation === 'invalid') throw new Error('ChatCode rejected the login grant.')\n if (account.validation === 'valid') {\n const validated = { ...grant, ...(account.emailAddress ? { emailAddress: account.emailAddress } : {}) }\n await this.mutate(async latest => {\n // Check AFTER acquiring the file lock: logout may have won while this callback queued.\n signal.throwIfAborted()\n if (latest.login?.sessionId !== login.sessionId || latest.login.state !== 'pending') return undefined\n return { version: 2, grant: validated, validation: 'valid', checkedAtMs: Date.now(), login: { ...login, state: 'succeeded' } }\n })\n return\n }\n }\n await wait(Math.min(this.options.pollIntervalMs, Math.max(1, login.expiresAtMs - Date.now())), undefined, { signal })\n }\n await this.finish({ ...login, state: 'timed-out' })\n }\n\n private async account(grant: ChatCodeGrant, signal: AbortSignal): Promise<{ validation: 'valid' | 'invalid' | 'unavailable'; emailAddress?: string }> {\n const response = await this.request('/caassist-api-lt/caassist/api/account/info', {\n method: 'POST', headers: { authorization: `Bearer ${grant.accessToken}`, 'content-type': 'application/json' }, body: '{}', signal,\n })\n const body = objectOf(response?.body)\n if (response?.status === 401 || response?.status === 403 || body.code === '76021501') return { validation: 'invalid' }\n if (!response?.ok || !(body.success === true || body.code === '00000000')) return { validation: 'unavailable' }\n const emailAddress = emailOf(body)\n return { validation: 'valid', ...(emailAddress ? { emailAddress } : {}) }\n }\n\n private async refresh(current: ChatCodeGrant, signal: AbortSignal): Promise<{ grant?: ChatCodeGrant; validation: 'invalid' | 'unavailable' }> {\n const username = current.userName || current.emailAddress\n if (!username || !current.longToken) return { validation: 'invalid' }\n const response = await this.request('/caassist-api-lt/caassist/api/account/long/login', {\n method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ username, longToken: current.longToken }), signal,\n })\n const body = objectOf(response?.body)\n const grant = response?.ok ? responseGrant(body, current) : undefined\n if (grant) return { grant, validation: 'unavailable' }\n return { validation: response?.status === 401 || response?.status === 403 || body.code === '76021501' || body.success === false ? 'invalid' : 'unavailable' }\n }\n\n private async request(path: string, init: RequestInit): Promise<{ ok: boolean; status: number; body: unknown } | undefined> {\n const signal = AbortSignal.any([this.lifetime.signal, ...(init.signal ? [init.signal] : []), AbortSignal.timeout(this.options.requestTimeoutMs)])\n try {\n const response = await fetch(new URL(path, this.options.apiBaseUrl), { ...init, signal, redirect: 'error' })\n return { ok: response.ok, status: response.status, body: await response.json().catch(() => undefined) }\n } catch { return undefined }\n }\n}\n","/** Mount and settings configuration for ChatCode model sources. @module dsh-llm-chatcode-config/config */\n\nimport z from '@deepseek-ai/schemastery'\nimport { RetryPolicySchema } from '@deepseek-ai/dsh-llm'\nimport type { RetryPolicyConfig } from '@deepseek-ai/dsh-llm'\n\n/** One user-defined model stored in the plugin-owned settings namespace. */\nexport interface CustomModel {\n /** Exact model ID sent to the configured gateway. */\n model: string\n /** Plaintext gateway credential stored in settings.yaml. */\n apiKey: string\n /** Gateway base URL, including any path prefix. */\n baseUrl: string\n /** Optional selector label; the model ID is used when omitted. */\n description?: string\n /** Legacy protocol hint used when protocol is omitted. */\n provider?: string | null\n /** Compatible wire protocol: OpenAI or Anthropic. */\n protocol?: string\n /** Context capacity advertised to ChatCode CLI. */\n contextWindow?: number\n /** Default and maximum output token count. */\n maxTokens?: number\n /** Legacy context-capacity fallback. */\n maxInputTokens?: number\n}\n\n/** One provider/model rule used to classify ChatCode model statistics. */\nexport interface ModelKindRule {\n /** Exact ChatCode CLI provider route; omission matches every provider. */\n provider?: string\n /** Exact provider model id; omission matches every model. */\n model?: string\n /** ChatCode model category. */\n kind: number\n}\n\n/** Operational reporting controls for committed ChatCode CLI Session events. */\nexport interface ReportingConfig {\n /** Enable reporting when the Session service is available. */\n enabled: boolean\n /** Enable durable AI-generated-code reporting. */\n codeSave: boolean\n /** Enable conversation and message database synchronization. */\n conversationSync: boolean\n /** Enable the user-visible ChatCode message chain. */\n chatCodeSession: boolean\n /** Maximum code records in one save request. */\n codeBatchItems: number\n /** Maximum aggregate code characters in one save request. */\n codeBatchChars: number\n /** Delay before retrying the durable code outbox. */\n codeRetryDelayMs: number\n /** Absolute code outbox directory; an empty value uses the resolved ChatCode CLI Home. */\n codeOutboxDir: string\n /** Include subagent Sessions in conversation database synchronization. */\n includeSubagentConversationSync: boolean\n /** Ordered exact-match overrides applied before backend URL classification. */\n modelKindRules: ModelKindRule[]\n}\n\n/** Model sources, account access, and operations-reporting configuration. */\nexport interface Config {\n /** Legacy Host JSON file used only when the settings namespace is absent. */\n settingsPath?: string\n /** User-defined models served from the plugin-owned settings namespace. */\n customModels: CustomModel[]\n /** Context capacity when a managed entry omits its capacity. */\n defaultContextWindow: number\n /** Output default and ceiling when a managed entry omits maxTokens. */\n defaultMaxTokens: number\n /** Retry policy for every imported route; omission uses the LLM service default. */\n retryPolicy?: RetryPolicyConfig\n /** ChatCode account sign-in and refresh endpoint selection. */\n auth: {\n /** Retained for login UI compatibility; it never blocks model calls. */\n requireLogin: boolean\n loginUrl: string\n apiBaseUrl: string\n pollIntervalMs: number\n pollTimeoutMs: number\n requestTimeoutMs: number\n }\n /** CVP backend root for generated code, conversation synchronization, and ChatCode message records. */\n cvpChatCodeApiUrl: string\n /** Optional CVP credential override and timeout for launch admission. */\n startupGate: {\n token: string\n timeoutMs: number\n }\n /** ChatCode operations reporting derived from committed Session events. */\n reporting: ReportingConfig\n\n /** Runtime-config API queried once when the ChatCode CLI profile starts. */\n codingPlanEndpoint: string\n /** Include the separately configured MAAS catalog in the model selector. */\n enableMaas: boolean\n /** MAAS catalog API, queried only when {@link enableMaas} is true. */\n maasEndpoint: string\n /** Bound one catalog request so a failed control plane cannot block startup indefinitely. */\n catalogTimeoutMs: number\n}\n\n/** Mount input accepts independently partial account and reporting sections. */\nexport interface ConfigInput extends Omit<Partial<Config>, 'auth' | 'reporting' | 'startupGate'> {\n auth?: Partial<Config['auth']>\n reporting?: Partial<ReportingConfig>\n startupGate?: Partial<Config['startupGate']>\n}\n\n/** Validate mounting options without exposing control-plane credentials. */\nexport const Config: z<ConfigInput, Config> = z.object({\n settingsPath: z.string(),\n customModels: z.array(z.object({\n model: z.string().required(),\n apiKey: z.string().required().role('secret'),\n baseUrl: z.string().required(),\n description: z.string(),\n provider: z.union([z.string(), z.const(null)]),\n protocol: z.string(),\n contextWindow: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER),\n maxTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER),\n maxInputTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER),\n })).default([]),\n defaultContextWindow: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(262_144),\n defaultMaxTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(4096),\n retryPolicy: RetryPolicySchema,\n\n auth: z.object({\n requireLogin: z.boolean().default(true),\n loginUrl: z.string().default('https://chatcode.chinaunicom.cn/unicode/#/login'),\n apiBaseUrl: z.string().default('https://chatcode.chinaunicom.cn'),\n pollIntervalMs: z.number().step(1).min(250).max(60_000).default(1_000),\n pollTimeoutMs: z.number().step(1).min(1_000).max(7_200_000).default(3_600_000),\n requestTimeoutMs: z.number().step(1).min(1_000).max(60_000).default(5_000),\n }).default({\n requireLogin: true,\n loginUrl: 'https://chatcode.chinaunicom.cn/unicode/#/login',\n apiBaseUrl: 'https://chatcode.chinaunicom.cn',\n pollIntervalMs: 1_000,\n pollTimeoutMs: 3_600_000,\n requestTimeoutMs: 5_000,\n }),\n\n cvpChatCodeApiUrl: z.string().default('https://chatcode.chinaunicom.cn/cvp'),\n startupGate: z.object({\n token: z.string().role('secret').default(''),\n timeoutMs: z.number().step(1).min(1_000).max(60_000).default(5_000),\n }).default({ token: '', timeoutMs: 5_000 }),\n // cvpChatCodeApiUrl: z.string().default('http://127.0.0.1:8080'),\n\n reporting: z.object({\n enabled: z.boolean().default(true),\n codeSave: z.boolean().default(true),\n conversationSync: z.boolean().default(true),\n chatCodeSession: z.boolean().default(true),\n codeBatchItems: z.number().step(1).min(1).max(500).default(50),\n codeBatchChars: z.number().step(1).min(1_024).max(5 * 1024 * 1024).default(512 * 1024),\n codeRetryDelayMs: z.number().step(1).min(1_000).max(300_000).default(5_000),\n codeOutboxDir: z.string().default(''),\n includeSubagentConversationSync: z.boolean().default(false),\n modelKindRules: z.array(z.object({\n provider: z.string(),\n model: z.string(),\n kind: z.number().step(1).min(0).max(3).required(),\n })).default([]),\n }).default({\n enabled: true,\n codeSave: true,\n conversationSync: true,\n chatCodeSession: true,\n codeBatchItems: 50,\n codeBatchChars: 512 * 1024,\n codeRetryDelayMs: 5_000,\n codeOutboxDir: '',\n includeSubagentConversationSync: false,\n modelKindRules: [],\n }),\n\n codingPlanEndpoint: z.string().default('https://chatcode.chinaunicom.cn/cvp/api/cli/v1/model-runtime-configs'),\n enableMaas: z.boolean().default(false),\n maasEndpoint: z.string().default('https://chatcode.chinaunicom.cn/cvp/wanma/api/v1/cli/maas-models'),\n catalogTimeoutMs: z.number().step(1).min(1).max(60_000).default(10_000),\n\n})\n","/** Read centrally managed model catalogs without exposing their credentials. @module dsh-llm-chatcode-config/managed */\n\nimport { createHash } from 'node:crypto'\nimport { userInfo } from 'node:os'\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { PiAiRequestAuth } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport { resolveProfiles } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { PiAiProviderProfile, ResolvedPiAiProviderProfile } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { Config } from './config.ts'\nimport type { ChatCodeModelSelection, ChatCodeSource } from './source.ts'\n\n/** Resolve the OS account that launched the current DSH host. */\nexport function currentUserName(): string {\n const environmentName = process.env.USERNAME?.trim() || process.env.USER?.trim()\n if (environmentName !== undefined && environmentName !== '') return environmentName\n try {\n return userInfo().username.trim()\n } catch {\n return ''\n }\n}\n\n/** Query fields required by the CodingPlan runtime catalogue. */\nfunction runtimeQuery(userName = currentUserName()): Readonly<Record<string, string>> {\n return { userEmail: userName }\n}\n\n/** Host-only authorization for ChatCode control-plane requests. */\nexport interface ManagedCatalogAuthorization {\n accessToken: string\n}\n\n/** Optional host-side diagnostic sink; callers decide where messages are written. */\nexport type ManagedCatalogDiagnostic = (message: string) => void\n\ntype Protocol = 'openai-completions' | 'anthropic-messages'\n\ninterface RuntimeModel {\n logicalModelId: string\n displayName: string\n description?: string\n protocol?: string\n provider?: string\n baseUrl?: string\n providerModelId?: string\n apiKey?: string\n maxToken?: number\n contextWindow?: number\n}\n\ninterface MaasCatalogModel {\n id: number\n logicalModelId: string\n displayName: string\n description?: string\n protocol?: string\n model?: string\n maxTokens?: number\n contextWindow?: number\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : undefined\n}\n\nfunction string(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction positive(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isSafeInteger(value) && value > 0 ? value : undefined\n}\n\nconst DIAGNOSTIC_BODY_LIMIT = 16_000\nconst SENSITIVE_FIELD = /(?:api[-_]?key|access[-_]?token|refresh[-_]?token|long[-_]?token|authorization|password|secret)/i\n\n/** Render enough of a JSON response to diagnose its shape without logging credentials. */\nfunction diagnosticBody(value: unknown): string {\n try {\n const rendered = JSON.stringify(value, (key, item) => SENSITIVE_FIELD.test(key) ? '[REDACTED]' : item)\n if (rendered === undefined) return '<empty>'\n return rendered.length <= DIAGNOSTIC_BODY_LIMIT\n ? rendered\n : `${rendered.slice(0, DIAGNOSTIC_BODY_LIMIT)}...<truncated>`\n } catch {\n return '<unserializable JSON>'\n }\n}\n\nfunction catalogHeaders(\n authorization: ManagedCatalogAuthorization | undefined,\n noCache = false,\n): Record<string, string> {\n const accessToken = authorization?.accessToken.trim()\n if (accessToken !== undefined && accessToken !== '' && !/[\\r\\n]/.test(accessToken)) {\n return {\n Accept: 'application/json',\n ...(noCache ? { 'Cache-Control': 'no-cache' } : {}),\n Authorization: `Bearer ${accessToken}`,\n accessToken,\n }\n }\n return { Accept: 'application/json', ...(noCache ? { 'Cache-Control': 'no-cache' } : {}) }\n}\n\nfunction protocolOf(model: RuntimeModel): Protocol | undefined {\n switch (model.protocol?.trim().toLowerCase()) {\n case 'openai': return 'openai-completions'\n case 'anthropic': return 'anthropic-messages'\n default: return undefined\n }\n}\n\n/** Accept gateway roots and a complete OpenAI chat-completions URL from the control plane. */\nfunction endpointOf(value: string): string | undefined {\n let url: URL\n try { url = new URL(value) } catch { return undefined }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) return undefined\n url.pathname = url.pathname.replace(/\\/chat\\/completions\\/?$/i, '') || '/'\n return url.href.replace(/\\/+$/, '')\n}\n\nfunction requestApiKey(apiKey: string | undefined): string | undefined {\n // Control planes commonly redact a key as \"****\". It is not a credential and\n // must never be sent to a provider or reflected in a diagnostic.\n if (apiKey === undefined || apiKey.trim() === '' || /^\\*+$/.test(apiKey.trim()) || /[\\r\\n]/.test(apiKey)) return undefined\n return apiKey\n}\n\nfunction requestAuth(protocol: Protocol, apiKey: string | undefined): PiAiRequestAuth {\n if (apiKey === undefined) return {}\n return protocol === 'anthropic-messages'\n ? { headers: { Authorization: `Bearer ${apiKey}` } }\n : { apiKey }\n}\n\n/** Fetch the supported control-plane response shape and report only generic, non-secret errors. */\nexport async function fetchRuntimeModels(\n endpoint: string,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n diagnostic?: ManagedCatalogDiagnostic,\n): Promise<readonly RuntimeModel[]> {\n let url: URL\n try { url = new URL(endpoint) } catch {\n throw new LlmError('chatcode-config: managed model endpoint is invalid', 'INVALID_CHATCODE_CONFIG')\n }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) {\n throw new LlmError('chatcode-config: managed model endpoint must be HTTP(S) without credentials', 'INVALID_CHATCODE_CONFIG')\n }\n for (const [key, value] of Object.entries(runtimeQuery())) url.searchParams.set(key, value)\n diagnostic?.(`chatcode-config: CodingPlan request GET ${url.href}`)\n let response: Response\n try {\n response = await fetch(url, { headers: catalogHeaders(authorization), signal: AbortSignal.timeout(timeoutMs) })\n } catch (error) {\n diagnostic?.(`chatcode-config: CodingPlan request failed before a response (${error instanceof Error ? error.message : String(error)})`)\n throw new LlmError('chatcode-config: managed model catalog is unavailable', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n }\n let body: unknown\n try {\n body = await response.json()\n diagnostic?.(`chatcode-config: CodingPlan response status=${response.status} body=${diagnosticBody(body)}`)\n } catch {\n diagnostic?.(`chatcode-config: CodingPlan response status=${response.status} body=<invalid JSON>`)\n throw new LlmError('chatcode-config: managed model catalog returned invalid JSON', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n if (!response.ok) throw new LlmError('chatcode-config: managed model catalog request failed', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n const top = record(body)\n const data = top === undefined ? undefined : record(top.data)\n const rows = data === undefined ? undefined : data.models\n if (top?.code !== '00000000' || !Array.isArray(rows)) {\n throw new LlmError('chatcode-config: managed model catalog returned an invalid response', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const models = rows.flatMap(row => {\n const item = record(row)\n if (item === undefined) return []\n const logicalModelId = string(item.logicalModelId)\n if (logicalModelId === undefined || logicalModelId.trim() === '') return []\n const parsed: RuntimeModel = {\n logicalModelId,\n displayName: string(item.displayName) ?? logicalModelId,\n }\n const description = string(item.description)\n const protocol = string(item.protocol)\n const provider = string(item.provider)\n const baseUrl = string(item.baseUrl)\n const providerModelId = string(item.providerModelId)\n const apiKey = string(item.apiKey)\n const maxToken = positive(item.maxToken)\n const contextWindow = positive(item.contextWindow)\n if (description !== undefined) parsed.description = description\n if (protocol !== undefined) parsed.protocol = protocol\n if (provider !== undefined) parsed.provider = provider\n if (baseUrl !== undefined) parsed.baseUrl = baseUrl\n if (providerModelId !== undefined) parsed.providerModelId = providerModelId\n if (apiKey !== undefined) parsed.apiKey = apiKey\n if (maxToken !== undefined) parsed.maxToken = maxToken\n if (contextWindow !== undefined) parsed.contextWindow = contextWindow\n return [parsed]\n })\n diagnostic?.(`chatcode-config: CodingPlan parsed ${String(rows.length)} response rows into ${String(models.length)} model records`)\n return models\n}\n\n/** Fetch the public MAAS catalog. It intentionally contains no endpoint or credential fields. */\nasync function fetchMaasCatalog(\n endpoint: string,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n): Promise<readonly MaasCatalogModel[]> {\n let url: URL\n try { url = new URL(endpoint) } catch {\n throw new LlmError('chatcode-config: MAAS model endpoint is invalid', 'INVALID_CHATCODE_CONFIG')\n }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) {\n throw new LlmError('chatcode-config: MAAS model endpoint must be HTTP(S) without credentials', 'INVALID_CHATCODE_CONFIG')\n }\n let response: Response\n try {\n response = await fetch(url, { headers: catalogHeaders(authorization, true), signal: AbortSignal.timeout(timeoutMs) })\n } catch {\n throw new LlmError('chatcode-config: MAAS model catalog is unavailable', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n }\n if (!response.ok) throw new LlmError('chatcode-config: MAAS model catalog request failed', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n let body: unknown\n try { body = await response.json() } catch {\n throw new LlmError('chatcode-config: MAAS model catalog returned invalid JSON', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const top = record(body)\n if (top?.code !== 200 || !Array.isArray(top.data)) {\n throw new LlmError('chatcode-config: MAAS model catalog returned an invalid response', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n return top.data.flatMap(row => {\n const item = record(row)\n const id = positive(item?.id)\n const logicalModelId = string(item?.logicalModelId)?.trim()\n if (id === undefined || logicalModelId === undefined || logicalModelId === '') return []\n const parsed: MaasCatalogModel = {\n id,\n logicalModelId,\n displayName: string(item?.displayName)?.trim() || logicalModelId,\n }\n const description = string(item?.description)\n const protocol = string(item?.protocol)\n const model = string(item?.model)\n const maxTokens = positive(item?.maxTokens)\n const contextWindow = positive(item?.contextWindow)\n if (description !== undefined) parsed.description = description\n if (protocol !== undefined) parsed.protocol = protocol\n if (model !== undefined) parsed.model = model\n if (maxTokens !== undefined) parsed.maxTokens = maxTokens\n if (contextWindow !== undefined) parsed.contextWindow = contextWindow\n return [parsed]\n })\n}\n\nfunction maasRuntimeUrl(catalogEndpoint: string, id: number): URL {\n let url: URL\n try { url = new URL(catalogEndpoint) } catch {\n throw new LlmError('chatcode-config: MAAS model endpoint is invalid', 'INVALID_CHATCODE_CONFIG')\n }\n const path = url.pathname.replace(/\\/+$/, '')\n if (!path.endsWith('/maas-models')) {\n throw new LlmError('chatcode-config: MAAS endpoint must end with /maas-models', 'INVALID_CHATCODE_CONFIG')\n }\n url.pathname = `${path}/${String(id)}/runtime-config`\n url.search = ''\n return url\n}\n\n/** Fetch one selected MAAS model's private runtime configuration. */\nasync function fetchMaasRuntime(\n endpoint: string,\n catalog: MaasCatalogModel,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n): Promise<RuntimeModel | undefined> {\n const url = maasRuntimeUrl(endpoint, catalog.id)\n let response: Response\n try {\n response = await fetch(url, { headers: catalogHeaders(authorization, true), signal: AbortSignal.timeout(timeoutMs) })\n } catch {\n throw new LlmError('chatcode-config: MAAS runtime configuration is unavailable', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n }\n if (!response.ok) throw new LlmError('chatcode-config: MAAS runtime configuration request failed', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n let body: unknown\n try { body = await response.json() } catch {\n throw new LlmError('chatcode-config: MAAS runtime configuration returned invalid JSON', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const top = record(body)\n const data = top === undefined ? undefined : record(top.data)\n // The runtime resource is addressed by the catalog ID. Some gateways return\n // only private connection fields here, so an omitted `id` is valid; if an ID\n // is supplied it must still agree with the requested catalog row.\n const runtimeId = positive(data?.id)\n if (top?.code !== 200 || data === undefined || (runtimeId !== undefined && runtimeId !== catalog.id)) {\n throw new LlmError('chatcode-config: MAAS runtime configuration returned an invalid response', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const logicalModelId = string(data.logicalModelId)?.trim() || catalog.logicalModelId\n const providerModelId = string(data.model)?.trim() || catalog.model?.trim()\n const baseUrl = string(data.baseUrl)\n if (logicalModelId === undefined || logicalModelId === '' || providerModelId === undefined || providerModelId === '' || baseUrl === undefined) return undefined\n const parsed: RuntimeModel = {\n logicalModelId,\n displayName: string(data.displayName)?.trim() || catalog.displayName,\n baseUrl,\n providerModelId,\n }\n const description = string(data.description) ?? catalog.description\n const protocol = string(data.protocol) ?? catalog.protocol\n const apiKey = string(data.apiKey)\n const maxToken = positive(data.maxTokens) ?? catalog.maxTokens\n const contextWindow = positive(data.contextWindow) ?? catalog.contextWindow\n if (description !== undefined) parsed.description = description\n if (protocol !== undefined) parsed.protocol = protocol\n if (apiKey !== undefined) parsed.apiKey = apiKey\n if (maxToken !== undefined) parsed.maxToken = maxToken\n if (contextWindow !== undefined) parsed.contextWindow = contextWindow\n return parsed\n}\n\n/** Resolve every public MAAS entry through its private runtime endpoint before publishing it as selectable. */\nexport async function fetchMaasRuntimeModels(\n endpoint: string,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n): Promise<readonly RuntimeModel[]> {\n const catalog = await fetchMaasCatalog(endpoint, timeoutMs, authorization)\n const loaded = await Promise.all(catalog.map(async item => {\n try { return await fetchMaasRuntime(endpoint, item, timeoutMs, authorization) } catch (error) {\n if (error instanceof LlmError) return undefined\n throw error\n }\n }))\n return loaded.flatMap(model => model === undefined ? [] : [model])\n}\n\n/** Translate runnable managed entries into detached pi-ai routes. Incomplete public metadata is deliberately not selectable. */\nexport function resolveManagedSource(models: readonly RuntimeModel[], group: string, config: Config): ChatCodeSource {\n const profiles: Record<string, PiAiProviderProfile> = {}\n const auth = new Map<string, PiAiRequestAuth>()\n const apiKeys = new Map<string, string>()\n const selections = new Map<string, ChatCodeModelSelection>()\n for (const entry of models) {\n const protocol = protocolOf(entry)\n const baseURL = entry.baseUrl === undefined ? undefined : endpointOf(entry.baseUrl)\n const providerModelId = entry.providerModelId?.trim()\n // A row such as the documented DeepSeek-V3 public descriptor is display\n // metadata only: without protocol, endpoint and provider model id it cannot\n // make a safe provider request, so it never becomes a broken selector item.\n if (protocol === undefined || baseURL === undefined || providerModelId === undefined || providerModelId === '') continue\n const selection = entry.logicalModelId.trim()\n if (selection === '' || selections.has(selection)) continue\n const route = `managed-${group}-${createHash('sha256').update(JSON.stringify([protocol, baseURL, providerModelId, selection])).digest('hex').slice(0, 20)}`\n profiles[route] = {\n displayName: entry.displayName.trim() || selection,\n api: protocol,\n baseURL,\n models: [{\n id: providerModelId,\n name: entry.displayName.trim() || selection,\n contextWindow: entry.contextWindow ?? entry.maxToken ?? config.defaultContextWindow,\n maxTokens: entry.maxToken ?? config.defaultMaxTokens,\n }],\n ...protocol === 'openai-completions' ? {\n compat: { maxTokensField: 'max_tokens', supportsDeveloperRole: false },\n // The OpenAI SDK defaults Accept to application/json even for streaming\n // calls. ChatCode's forwarding gateway enforces content negotiation and\n // otherwise returns a JSON business error with HTTP 200, which the SSE\n // parser can only report later as a missing finish_reason.\n headers: { Accept: 'text/event-stream' },\n } : {},\n ...config.retryPolicy === undefined ? {} : { retryPolicy: config.retryPolicy },\n }\n const apiKey = requestApiKey(entry.apiKey)\n auth.set(route, requestAuth(protocol, apiKey))\n if (apiKey !== undefined) apiKeys.set(route, apiKey)\n selections.set(selection, { route, model: providerModelId })\n }\n return { profiles: resolveProfiles(profiles), auth, apiKeys, selections }\n}\n","/** Durable file-per-record outbox for generated-code statistics. */\nimport { randomUUID } from 'node:crypto'\nimport { mkdir, open, readdir, readFile, rename, unlink } from 'node:fs/promises'\nimport { basename, join } from 'node:path'\n\ninterface OutboxRecord {\n version: 1\n id: string\n createdAt: number\n codes: string[]\n}\n\n/** One ordered code batch and the files acknowledged with it. */\nexport interface CodeOutboxBatch {\n files: string[]\n codes: string[]\n}\n\n/** Persist generated code until a backend acknowledgement permits deletion. */\nexport class CodeOutbox {\n constructor(private readonly directory: string) {}\n\n /** Atomically append non-empty code strings to the outbox. */\n async enqueue(codes: readonly string[]): Promise<void> {\n const kept = codes.map(code => code.trim()).filter(Boolean)\n if (kept.length === 0) return\n await mkdir(this.directory, { recursive: true, mode: 0o700 })\n for (const code of kept) await this.writeRecord(code)\n }\n\n private async writeRecord(code: string): Promise<void> {\n const id = randomUUID()\n const record: OutboxRecord = { version: 1, id, createdAt: Date.now(), codes: [code] }\n const target = join(this.directory, `${String(record.createdAt).padStart(13, '0')}-${id}.json`)\n const temporary = `${target}.${randomUUID()}.tmp`\n const handle = await open(temporary, 'wx', 0o600)\n try {\n await handle.writeFile(`${JSON.stringify(record)}\\n`, 'utf8')\n await handle.sync()\n } finally {\n await handle.close()\n }\n await rename(temporary, target)\n }\n\n /** Read the oldest complete records within both configured batch limits. */\n async readBatch(maxItems: number, maxChars: number): Promise<CodeOutboxBatch> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 })\n const entries = (await readdir(this.directory, { withFileTypes: true }))\n .filter(entry => entry.isFile() && entry.name.endsWith('.json'))\n .map(entry => entry.name)\n .sort()\n const batch: CodeOutboxBatch = { files: [], codes: [] }\n let chars = 0\n for (const name of entries) {\n const path = join(this.directory, name)\n const record = await this.readRecord(path)\n if (!record) continue\n const nextChars = record.codes.reduce((sum, code) => sum + code.length, 0)\n if (batch.codes.length > 0 && (batch.codes.length + record.codes.length > maxItems || chars + nextChars > maxChars)) break\n batch.files.push(path)\n batch.codes.push(...record.codes)\n chars += nextChars\n if (batch.codes.length >= maxItems || chars >= maxChars) break\n }\n return batch\n }\n\n /** Delete only records included in a backend-acknowledged batch. */\n async acknowledge(files: readonly string[]): Promise<void> {\n for (const file of files) {\n try {\n await unlink(file)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n }\n }\n\n private async readRecord(path: string): Promise<OutboxRecord | undefined> {\n try {\n const value = JSON.parse(await readFile(path, 'utf8')) as unknown\n if (isRecord(value)\n && value.version === 1\n && typeof value.id === 'string'\n && Number.isSafeInteger(value.createdAt)\n && Array.isArray(value.codes)\n && value.codes.length > 0\n && value.codes.every(code => typeof code === 'string' && code.trim().length > 0)) {\n return value as unknown as OutboxRecord\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined\n }\n const invalidDirectory = join(this.directory, 'invalid')\n await mkdir(invalidDirectory, { recursive: true, mode: 0o700 })\n await rename(path, join(invalidDirectory, `${basename(path)}.${randomUUID()}.invalid`))\n return undefined\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/** Pure extraction of code that is safe to count as AI-generated output. */\nimport { extname } from 'node:path'\n\n/** Code attributed to one successful model response or mutating tool call. */\nexport interface ExtractedCode {\n /** Code text without surrounding Markdown fences. */\n code: string\n /** Optional Markdown language identifier. */\n language?: string\n /** Optional path supplied to a first-party file mutation tool. */\n filePath?: string\n}\n\nconst EXCLUDED_FENCE_LABELS = new Set([\n 'text', 'plaintext', 'plain', 'output', 'result', 'log', 'example', 'sample',\n 'demo', 'note', 'notice', 'warning', 'error', 'exception', 'stacktrace', 'trace',\n])\n\n/** Extract reportable fenced code blocks from assistant-visible Markdown. */\nexport function extractMarkdownCode(markdown: string): ExtractedCode[] {\n const result: ExtractedCode[] = []\n const pattern = /(?:^|\\n)(`{3,}|~{3,})[ \\t]*([^\\r\\n]*)\\r?\\n([\\s\\S]*?)\\r?\\n?\\1(?=\\r?\\n|$)/g\n for (const match of markdown.matchAll(pattern)) {\n const label = match[2]?.trim().split(/[ \\t]/, 1)[0]?.toLowerCase() ?? ''\n const code = match[3]?.trim()\n if (!code || EXCLUDED_FENCE_LABELS.has(label) || (!label && looksLikeConsoleResult(code))) continue\n result.push({ code, ...(label ? { language: label } : {}) })\n }\n return result\n}\n\n/** Extract code from one successful first-party mutation request. */\nexport function extractMutationCode(name: string, args: unknown): ExtractedCode | undefined {\n if (!isRecord(args)) return undefined\n if (name === 'write') {\n return codeAt(args, 'file_path', 'content')\n }\n if (name === 'edit') {\n if (typeof args.old_string !== 'string' || args.old_string.length === 0) return undefined\n return codeAt(args, 'file_path', 'new_string')\n }\n if (name !== 'str_replace_editor') return undefined\n if (args.command === 'create') return codeAt(args, 'path', 'file_text')\n if (args.command === 'str_replace') {\n if (typeof args.old_str !== 'string' || args.old_str.length === 0) return undefined\n return codeAt(args, 'path', 'new_str')\n }\n if (args.command === 'insert' && Number.isInteger(args.insert_line)) {\n return codeAt(args, 'path', 'new_str')\n }\n return undefined\n}\n\n/** Parse model-produced JSON arguments before mutation extraction. */\nexport function extractMutationCodeFromJson(name: string, raw: string): ExtractedCode | undefined {\n try {\n return extractMutationCode(name, JSON.parse(raw) as unknown)\n } catch {\n return undefined\n }\n}\n\n/** Infer a stable Markdown language name from a file path. */\nexport function inferLanguage(filePath: string): string | undefined {\n const extension = extname(filePath).slice(1).toLowerCase()\n if (!extension) return undefined\n const aliases: Readonly<Record<string, string>> = {\n cjs: 'javascript', htm: 'html', js: 'javascript', mjs: 'javascript',\n py: 'python', ps1: 'powershell', sh: 'bash', ts: 'typescript', yml: 'yaml',\n }\n return aliases[extension] ?? extension\n}\n\nfunction codeAt(args: Readonly<Record<string, unknown>>, pathKey: string, codeKey: string): ExtractedCode | undefined {\n const code = args[codeKey]\n if (typeof code !== 'string' || code.trim().length === 0) return undefined\n const filePath = args[pathKey]\n if (typeof filePath !== 'string' || filePath.trim().length === 0) return { code: code.trim() }\n const language = inferLanguage(filePath)\n return { code: code.trim(), filePath, ...(language ? { language } : {}) }\n}\n\nfunction looksLikeConsoleResult(code: string): boolean {\n const lines = code.split('\\n')\n if (lines.length <= 3) return false\n const resultLines = lines.filter(line => /^[A-Za-z_]\\w*\\(\\d+\\)\\s*=/.test(line.trim()))\n return resultLines.length > lines.length * 0.5\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/** Backend payloads and pure Session-message projections. */\nimport type { ContentBlock, Message, TokenUsage } from '@deepseek-ai/dsh-llm/types'\nimport type { Session } from '@deepseek-ai/dsh-session'\nimport type { ModelKindRule } from '../config.ts'\n\n/** Conversation metadata accepted by the Wanma synchronization endpoint. */\nexport interface ConversationMeta {\n sessionId: string\n userEmail: string\n projectPath: string\n title?: string\n modelName: string\n startTime: string\n}\n\n/** One synchronized conversation message. */\nexport interface ConversationMessagePayload {\n uuid: string\n parentUuid?: string\n sessionId: string\n role: 'user' | 'assistant' | 'system' | 'tool'\n contentType: 'text' | 'think' | 'tool_use' | 'tool_result' | 'image'\n content: string\n toolName?: string\n toolInput?: string\n userEmail?: string\n modelName?: string\n modelKind?: number\n tokenUsage?: {\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheCreationTokens: number\n }\n usageTime?: string\n timestamp: string\n turnIndex: number\n}\n\n/** Request body for conversation synchronization. */\nexport interface ConversationSyncPayload {\n conversation: ConversationMeta\n messages: ConversationMessagePayload[]\n isComplete: boolean\n}\n\n/** Request body for one ChatCode message record. */\nexport interface ChatMessagePayload {\n chatId: string\n questionText: string\n answerText: string\n pluginVersion: string\n tokensIn: number\n tokensOut: number\n modelKind: number\n modelName: string\n baseUrl: string\n}\n\n/** Actual model identity and service address used for operations reporting. */\nexport interface ModelReport {\n modelName: string\n baseUrl: string\n}\n\n/** Resolve one public ChatCode CLI model selection to its private runtime identity. */\nexport type ModelReportResolver = (provider: string, model: string) => ModelReport\n\n/** Return the first explicit model-kind override, if one matches. */\nexport function matchModelKindRule(provider: string, model: string, rules: readonly ModelKindRule[]): number | undefined {\n return rules.find(rule => (rule.provider === undefined || rule.provider === provider)\n && (rule.model === undefined || rule.model === model))?.kind\n}\n\n/** Resolve the first exact model-kind rule, with category 2 as the fallback. */\nexport function resolveModelKind(provider: string, model: string, rules: readonly ModelKindRule[]): number {\n return matchModelKindRule(provider, model, rules) ?? 2\n}\n\n/** Build the immutable conversation fields for one Session. */\nexport function conversationMeta(\n session: Session,\n userEmail: string,\n title: string | undefined,\n modelName: string,\n): ConversationMeta {\n return {\n sessionId: String(session.id),\n userEmail,\n projectPath: session.header.cwd ?? '',\n ...(title ? { title } : {}),\n modelName,\n startTime: new Date(session.header.createdAt).toISOString(),\n }\n}\n\n/** Project one human or assistant message into a single backend row. */\nexport function conversationMessage(\n sessionId: string,\n message: Message,\n timestamp: number,\n turn: number,\n usage?: TokenUsage,\n): ConversationMessagePayload | undefined {\n const projected = projectBlocks(message.content)\n if (!projected) return undefined\n const model = message.source.kind === 'model' ? message.source.model : undefined\n return {\n uuid: String(message.id),\n sessionId,\n role: message.role === 'assistant' ? 'assistant' : message.role === 'system' ? 'system' : 'user',\n contentType: projected.contentType,\n content: projected.content,\n ...(model ? { modelName: model } : {}),\n ...(usage ? { tokenUsage: {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cacheReadTokens: usage.cacheReadTokens ?? 0,\n cacheCreationTokens: usage.cacheWriteTokens ?? 0,\n } } : {}),\n usageTime: new Date(timestamp).toISOString(),\n timestamp: new Date(timestamp).toISOString(),\n turnIndex: turn,\n }\n}\n\n/** Project one durable tool call into a stable conversation row. */\nexport function toolCallMessage(\n sessionId: string,\n callId: string,\n name: string,\n args: string,\n timestamp: number,\n turn: number,\n): ConversationMessagePayload {\n return {\n uuid: callId,\n sessionId,\n role: 'assistant',\n contentType: 'tool_use',\n content: name,\n toolName: name,\n toolInput: args,\n usageTime: new Date(timestamp).toISOString(),\n timestamp: new Date(timestamp).toISOString(),\n turnIndex: turn,\n }\n}\n\n/** Project one durable tool result into a stable conversation row. */\nexport function toolResultMessage(\n sessionId: string,\n message: Message,\n name: string,\n timestamp: number,\n turn: number,\n): ConversationMessagePayload {\n return {\n uuid: String(message.id),\n sessionId,\n role: 'tool',\n contentType: 'tool_result',\n content: textOfBlocks(message.content),\n toolName: name,\n usageTime: new Date(timestamp).toISOString(),\n timestamp: new Date(timestamp).toISOString(),\n turnIndex: turn,\n }\n}\n\n/** Return assistant-visible text without reasoning or tool-call arguments. */\nexport function visibleText(message: Message): string {\n return message.content.filter(block => block.type === 'text').map(block => block.text).join('\\n').trim()\n}\n\n/** Return direct-user text suitable for a title or question. */\nexport function userText(message: Message): string {\n return message.content.map(block => {\n if (block.type === 'text') return block.text\n if (block.type === 'image') return '[image]'\n if (block.type === 'file') return `[file: ${block.attachment.name}]`\n return ''\n }).filter(Boolean).join('\\n').trim()\n}\n\n/** Return a bounded, one-line tool result summary. */\nexport function toolSummary(message: Message, maxChars = 300): string {\n const text = textOfBlocks(message.content).replace(/[\\r\\n]+/g, ' ').trim()\n return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text\n}\n\nfunction projectBlocks(blocks: readonly ContentBlock[]): { contentType: ConversationMessagePayload['contentType']; content: string } | undefined {\n const kept = blocks.filter(block => block.type !== 'tool-call')\n if (kept.length === 0) return undefined\n if (kept.length === 1) {\n const block = kept[0]!\n if (block.type === 'text') return { contentType: 'text', content: block.text }\n if (block.type === 'reasoning') return { contentType: 'think', content: block.text }\n if (block.type === 'image') return { contentType: 'image', content: '[image]' }\n }\n return { contentType: 'text', content: JSON.stringify(kept.map(serializableBlock)) }\n}\n\nfunction serializableBlock(block: ContentBlock): unknown {\n if (block.type === 'image') return { type: 'image', name: block.attachment.name }\n if (block.type === 'file') return { type: 'file', name: block.attachment.name }\n if (block.type === 'tool-result') return { type: 'tool-result', toolCallId: block.toolCallId, content: block.content.map(serializableBlock), isError: block.isError === true }\n return block\n}\n\nfunction textOfBlocks(blocks: readonly ContentBlock[]): string {\n return blocks.map(block => {\n if (block.type === 'text' || block.type === 'reasoning') return block.text\n if (block.type === 'tool-result') return textOfBlocks(block.content)\n if (block.type === 'image') return '[image]'\n if (block.type === 'file') return `[file: ${block.attachment.name}]`\n return `[tool: ${block.name}]`\n }).join('\\n').trim()\n}\n","/** Session-scoped event projection into the three ChatCode reporting sinks. */\nimport type { ContentBlock } from '@deepseek-ai/dsh-llm/types'\nimport type { Session } from '@deepseek-ai/dsh-session'\nimport type { SessionEvent } from '@deepseek-ai/dsh-session/types'\nimport type {} from '@deepseek-ai/dsh-tools/types'\nimport { extractMarkdownCode, extractMutationCode, extractMutationCodeFromJson, type ExtractedCode } from './code.ts'\nimport type { ReportingConfig } from '../config.ts'\nimport { CodeOutbox } from './outbox.ts'\nimport {\n conversationMessage,\n conversationMeta,\n matchModelKindRule,\n toolCallMessage,\n toolResultMessage,\n toolSummary,\n userText,\n visibleText,\n type ChatMessagePayload,\n type ConversationMessagePayload,\n type ConversationSyncPayload,\n type ModelReport,\n type ModelReportResolver,\n} from './payloads.ts'\nimport type { ReportingTransport } from './transport.ts'\n\nconst PLUGIN_VERSION = '0.1.0'\n\ninterface Logger {\n warn(message: string): void\n}\n\ninterface ToolCallState {\n name: string\n code: ExtractedCode | undefined\n}\n\ninterface TurnState {\n turn: number\n pendingQuestion: string | undefined\n}\n\ninterface PendingModelResponse {\n responseId: string\n turn: number\n provider: string\n model: string\n questionText: string\n answerText: string\n tokensIn: number\n tokensOut: number\n report: ModelReport\n pendingToolIds: Set<string>\n codeRecords: { name: string; summary: string; code: ExtractedCode }[]\n}\n\ninterface ReporterSessionState {\n tail: Promise<void>\n topLevel: boolean\n title: string | undefined\n provider: string\n model: string\n chatId: string | undefined\n currentTurn: TurnState | undefined\n toolCalls: Map<string, ToolCallState>\n pendingResponses: Map<string, PendingModelResponse>\n responseByTool: Map<string, string>\n reportedResponses: Set<string>\n warned: Set<string>\n}\n\n/** Web-owned durable selection event consumed without requiring the Web package at runtime. */\ninterface ModelSelectionEvent {\n type: 'model/selection'\n seq: SessionEvent['seq']\n time: number\n data: {\n provider: string\n model: string\n }\n}\n\ntype ReportingSessionEvent = SessionEvent | ModelSelectionEvent\n\n/** Coordinates the durable code outbox without blocking Session event callbacks. */\nexport class CodeOutboxWorker {\n private running: Promise<void> | undefined\n private timer: ReturnType<typeof setTimeout> | undefined\n private stopped = false\n\n constructor(\n private readonly outbox: CodeOutbox,\n private readonly transport: ReportingTransport,\n private readonly maxItems: number,\n private readonly maxChars: number,\n private readonly retryDelayMs: number,\n private readonly logger: Logger,\n ) {}\n\n /** Persist code and trigger asynchronous delivery. */\n async enqueue(codes: readonly string[]): Promise<void> {\n await this.outbox.enqueue(codes)\n this.kick()\n }\n\n /** Resume files left by an earlier process. */\n start(): void {\n this.kick()\n }\n\n /** Wait for the active attempt and trigger one immediate attempt if idle. */\n async flushNow(): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = undefined\n }\n this.kick()\n await this.running\n }\n\n /** Stop retry scheduling after one bounded final attempt. */\n async stop(): Promise<void> {\n if (this.timer) clearTimeout(this.timer)\n this.timer = undefined\n await this.flushNow()\n if (this.timer) clearTimeout(this.timer)\n this.timer = undefined\n this.stopped = true\n }\n\n private kick(): void {\n if (this.stopped || this.running) return\n this.running = this.flushLoop().finally(() => { this.running = undefined })\n }\n\n private async flushLoop(): Promise<void> {\n try {\n while (true) {\n const batch = await this.outbox.readBatch(this.maxItems, this.maxChars)\n if (batch.files.length === 0) return\n await this.transport.saveCodes(batch.codes)\n await this.outbox.acknowledge(batch.files)\n }\n } catch (error) {\n this.logger.warn(`chatcode-reporting: code outbox retained after delivery failure: ${errorMessage(error)}`)\n if (!this.stopped && !this.timer) {\n this.timer = setTimeout(() => {\n this.timer = undefined\n this.kick()\n }, this.retryDelayMs)\n this.timer.unref?.()\n }\n }\n }\n}\n\n/** Project committed Session events while isolating state and ordering by Session. */\nexport class ChatCodeReporter {\n private readonly sessions = new WeakMap<Session, ReporterSessionState>()\n private readonly active = new Set<ReporterSessionState>()\n\n constructor(\n private readonly config: ReportingConfig,\n private readonly transport: ReportingTransport,\n private readonly codeWorker: CodeOutboxWorker,\n private readonly logger: Logger,\n private readonly resolveModelReport: ModelReportResolver = (_provider, model) => ({ modelName: model, baseUrl: '' }),\n ) {}\n\n /** Register Session-local state without starting network work. */\n created(session: Session): void {\n this.state(session)\n }\n\n /**\n * Seed a new Session with the Agent's selected route before its first messages.\n * @param session - Session owned by the newly published Agent.\n * @param provider - selected provider route, when configured.\n * @param model - selected provider-owned model, when configured.\n */\n seedModelRoute(session: Session, provider: string | undefined, model: string | undefined): void {\n if (provider === undefined || model === undefined) return\n const state = this.state(session)\n if (state.provider !== '' || state.model !== '') return\n state.provider = provider\n state.model = model\n }\n\n /** Enqueue one committed event and return immediately. */\n observe(session: Session, event: ReportingSessionEvent): void {\n const state = this.state(session)\n state.tail = state.tail.then(\n () => this.handle(session, state, event),\n () => this.handle(session, state, event),\n ).catch(error => this.warnOnce(state, 'event', error))\n }\n\n /** Wait until all work already queued for one Session has settled. */\n async flush(session: Session): Promise<void> {\n const state = this.sessions.get(session)\n if (state) await state.tail\n if (this.config.codeSave) await this.codeWorker.flushNow()\n }\n\n /** Drain and forget one disposed Session. */\n async disposed(session: Session): Promise<void> {\n const state = this.sessions.get(session)\n if (!state) return\n await state.tail\n await this.finalizePendingResponses(state)\n if (this.config.codeSave) await this.codeWorker.flushNow()\n this.sessions.delete(session)\n this.active.delete(state)\n }\n\n /** Drain every active Session and stop code retry scheduling. */\n async shutdown(): Promise<void> {\n await Promise.allSettled([...this.active].map(state => state.tail))\n await Promise.allSettled([...this.active].map(state => this.finalizePendingResponses(state)))\n if (this.config.codeSave) await this.codeWorker.stop()\n }\n\n private state(session: Session): ReporterSessionState {\n const current = this.sessions.get(session)\n if (current) return current\n const header = session.requestHeader()\n const created: ReporterSessionState = {\n tail: Promise.resolve(),\n topLevel: session.header.origin !== 'subagent',\n title: undefined,\n provider: header?.config.provider ?? '',\n model: header?.config.model ?? '',\n chatId: undefined,\n currentTurn: undefined,\n toolCalls: new Map(),\n pendingResponses: new Map(),\n responseByTool: new Map(),\n reportedResponses: new Set(),\n warned: new Set(),\n }\n this.sessions.set(session, created)\n this.active.add(created)\n return created\n }\n\n private async handle(session: Session, state: ReporterSessionState, event: ReportingSessionEvent): Promise<void> {\n if (event.type === 'turn/start') {\n state.currentTurn = { turn: event.data.turn, pendingQuestion: undefined }\n return\n }\n switch (event.type) {\n case 'model/selection':\n state.provider = event.data.provider\n state.model = event.data.model\n return\n case 'request/header':\n state.provider = event.data.header.config.provider\n state.model = event.data.header.config.model\n return\n case 'user/message':\n if (event.data.source.kind !== 'user') return\n await this.onUser(session, state, event)\n return\n case 'system/message':\n await this.onSystem(session, state, event)\n return\n case 'assistant/message':\n await this.onAssistant(session, state, event)\n return\n case 'tool/call':\n await this.onToolCall(session, state, event)\n return\n case 'tool/result':\n await this.onToolResult(session, state, event)\n return\n case 'tool/ptc-dispatch-start':\n await this.onNestedToolCall(session, state, event)\n return\n case 'tool/ptc-dispatch':\n await this.onNestedToolResult(session, state, event)\n return\n case 'turn/end':\n await this.onTurnEnd(session, state, event)\n return\n default:\n return\n }\n }\n\n private async onUser(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'user/message' }>): Promise<void> {\n const text = userText(event.data)\n if (!text) return\n state.title ??= text.slice(0, 200)\n const turn = state.currentTurn\n if (turn) turn.pendingQuestion = text\n if (this.shouldSync(state)) {\n const message = conversationMessage(String(session.id), event.data, event.time, state.currentTurn?.turn ?? 0)\n if (message) await this.sync(session, state, [message], false)\n }\n }\n\n private async onAssistant(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'assistant/message' }>): Promise<void> {\n state.provider = event.data.message.source.provider\n state.model = event.data.message.source.model\n const text = visibleText(event.data.message)\n if (this.config.codeSave && text) {\n const codes = extractMarkdownCode(text).map(item => item.code)\n if (codes.length > 0) await this.codeWorker.enqueue(codes)\n }\n if (this.shouldSync(state)) {\n const message = conversationMessage(String(session.id), event.data.message, event.time, event.data.turn, event.data.usage)\n if (message) await this.sync(session, state, [message], false)\n }\n if (!state.topLevel || !this.config.chatCodeSession || event.data.usage === undefined) return\n const { inputTokens, outputTokens } = event.data.usage\n if (inputTokens <= 0 && outputTokens <= 0) return\n const responseId = String(event.data.message.id)\n if (state.reportedResponses.has(responseId) || state.pendingResponses.has(responseId)) return\n const pendingToolIds = new Set(event.data.message.content.flatMap(block => block.type === 'tool-call' ? [String(block.id)] : []))\n const report = this.resolveModelReport(state.provider, state.model)\n const pending: PendingModelResponse = {\n responseId,\n turn: event.data.turn,\n provider: state.provider,\n model: state.model,\n questionText: state.currentTurn?.pendingQuestion ?? '',\n answerText: text,\n tokensIn: inputTokens,\n tokensOut: outputTokens,\n report,\n pendingToolIds,\n codeRecords: [],\n }\n if (state.currentTurn?.pendingQuestion !== undefined) state.currentTurn.pendingQuestion = undefined\n state.pendingResponses.set(responseId, pending)\n for (const callId of pendingToolIds) state.responseByTool.set(callId, responseId)\n await this.finishResponseIfReady(state, pending)\n }\n\n private async onSystem(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'system/message' }>): Promise<void> {\n if (!this.shouldSync(state)) return\n const message = conversationMessage(String(session.id), event.data.message, event.time, event.data.turn)\n if (message) await this.sync(session, state, [message], false)\n }\n\n private async onToolCall(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/call' }>): Promise<void> {\n const callId = String(event.data.callId)\n state.toolCalls.set(callId, {\n name: event.data.name,\n code: extractMutationCodeFromJson(event.data.name, event.data.arguments),\n })\n if (this.shouldSync(state)) {\n await this.sync(session, state, [toolCallMessage(String(session.id), callId, event.data.name, event.data.arguments, event.time, event.data.turn)], false)\n }\n }\n\n private async onToolResult(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/result' }>): Promise<void> {\n const callId = String(event.data.message.source.callId)\n const call = state.toolCalls.get(callId)\n const failed = event.data.error !== undefined || event.data.message.content.some(\n block => block.type === 'tool-result' && block.isError === true,\n )\n if (!failed && call?.code && this.config.codeSave) await this.codeWorker.enqueue([call.code.code])\n if (this.shouldSync(state)) {\n await this.sync(session, state, [toolResultMessage(String(session.id), event.data.message, call?.name ?? 'unknown', event.time, event.data.turn)], false)\n }\n await this.completeTool(state, callId, call?.name ?? 'unknown', failed, toolSummary(event.data.message), call?.code)\n }\n\n private async onNestedToolCall(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/ptc-dispatch-start' }>): Promise<void> {\n const callId = String(event.data.subCallId)\n state.toolCalls.set(callId, {\n name: event.data.name,\n code: extractMutationCode(event.data.name, event.data.arguments),\n })\n if (this.shouldSync(state)) {\n const raw = JSON.stringify(event.data.arguments)\n await this.sync(session, state, [toolCallMessage(String(session.id), callId, event.data.name, raw, event.time, state.currentTurn?.turn ?? 0)], false)\n }\n }\n\n private async onNestedToolResult(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/ptc-dispatch' }>): Promise<void> {\n const callId = String(event.data.subCallId)\n const call = state.toolCalls.get(callId)\n if (!event.data.isError && call?.code && this.config.codeSave) await this.codeWorker.enqueue([call.code.code])\n const summary = summaryOfBlocks(event.data.content)\n if (this.shouldSync(state)) {\n const timestamp = new Date(event.time).toISOString()\n const message: ConversationMessagePayload = {\n uuid: `${callId}:result`, sessionId: String(session.id), role: 'tool', contentType: 'tool_result',\n content: summary, toolName: event.data.name, usageTime: timestamp, timestamp,\n turnIndex: state.currentTurn?.turn ?? 0,\n }\n await this.sync(session, state, [message], false)\n }\n if (!event.data.isError && call?.code) {\n const rootResponseId = state.responseByTool.get(String(event.data.rootCallId))\n const pending = rootResponseId === undefined ? undefined : state.pendingResponses.get(rootResponseId)\n if (pending !== undefined) pending.codeRecords.push({ name: event.data.name, summary, code: call.code })\n }\n }\n\n private async onTurnEnd(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'turn/end' }>): Promise<void> {\n if (this.shouldSync(state)) await this.sync(session, state, [], true)\n await this.finalizePendingResponses(state, event.data.turn)\n state.toolCalls.clear()\n state.currentTurn = undefined\n }\n\n private shouldSync(state: ReporterSessionState): boolean {\n return this.config.conversationSync && (state.topLevel || this.config.includeSubagentConversationSync)\n }\n\n private async sync(session: Session, state: ReporterSessionState, messages: ConversationMessagePayload[], isComplete: boolean): Promise<void> {\n await this.attempt(state, 'conversation-sync', async () => {\n const userEmail = await this.transport.identity()\n const conversationReport = this.resolveModelReport(state.provider, state.model)\n const decorated = await Promise.all(messages.map(async message => {\n const selectedModel = message.modelName ?? state.model\n const report = this.resolveModelReport(state.provider, selectedModel)\n return {\n ...message,\n userEmail,\n modelName: report.modelName,\n modelKind: await this.modelKind(state.provider, selectedModel, report.baseUrl),\n }\n }))\n const payload: ConversationSyncPayload = {\n conversation: conversationMeta(session, userEmail, state.title, conversationReport.modelName),\n messages: decorated,\n isComplete,\n }\n await this.transport.syncConversation(payload)\n })\n }\n\n private async completeTool(\n state: ReporterSessionState,\n callId: string,\n name: string,\n failed: boolean,\n summary: string,\n code?: ExtractedCode,\n ): Promise<void> {\n const responseId = state.responseByTool.get(callId)\n const pending = responseId === undefined ? undefined : state.pendingResponses.get(responseId)\n if (pending === undefined || !pending.pendingToolIds.delete(callId)) return\n state.responseByTool.delete(callId)\n if (!failed && code !== undefined) pending.codeRecords.push({ name, summary, code })\n await this.finishResponseIfReady(state, pending)\n }\n\n private async finishResponseIfReady(state: ReporterSessionState, pending: PendingModelResponse): Promise<void> {\n if (pending.pendingToolIds.size > 0) return\n const answerParts = pending.answerText.trim() ? [pending.answerText.trim()] : []\n for (const record of pending.codeRecords) answerParts.push(formatToolRecord(record.name, 'success', record.summary, record.code))\n if (answerParts.length === 0) answerParts.push('ChatCode CLI 模型响应(工具调用)')\n state.pendingResponses.delete(pending.responseId)\n state.reportedResponses.add(pending.responseId)\n for (const [callId, responseId] of state.responseByTool) {\n if (responseId === pending.responseId) state.responseByTool.delete(callId)\n }\n await this.addChat(state, {\n questionText: pending.questionText,\n answerText: answerParts.join('\\n\\n'),\n tokensIn: pending.tokensIn,\n tokensOut: pending.tokensOut,\n }, pending.provider, pending.model, pending.report, 'chat-message')\n }\n\n private async finalizePendingResponses(state: ReporterSessionState, turn?: number): Promise<void> {\n for (const pending of state.pendingResponses.values()) {\n if (turn !== undefined && pending.turn !== turn) continue\n pending.pendingToolIds.clear()\n await this.finishResponseIfReady(state, pending)\n }\n }\n\n private async addChat(\n state: ReporterSessionState,\n content: Pick<ChatMessagePayload, 'questionText' | 'answerText' | 'tokensIn' | 'tokensOut'>,\n provider: string,\n model: string,\n report: ModelReport,\n warningKey: string,\n ): Promise<void> {\n await this.attempt(state, warningKey, async () => {\n const modelKind = await this.modelKind(provider, model, report.baseUrl)\n state.chatId ??= await this.transport.createChat()\n await this.transport.addChatMessage({\n chatId: state.chatId,\n ...content,\n pluginVersion: PLUGIN_VERSION,\n modelKind,\n modelName: report.modelName,\n baseUrl: report.baseUrl,\n })\n })\n }\n\n private async modelKind(provider: string, model: string, baseUrl: string): Promise<number> {\n return matchModelKindRule(provider, model, this.config.modelKindRules) ?? this.transport.modelKind(baseUrl)\n }\n\n private async attempt(state: ReporterSessionState, key: string, action: () => Promise<void>): Promise<void> {\n try {\n await action()\n } catch (error) {\n this.warnOnce(state, key, error)\n }\n }\n\n private warnOnce(state: ReporterSessionState, key: string, error: unknown): void {\n if (state.warned.has(key)) return\n state.warned.add(key)\n this.logger.warn(`chatcode-reporting: ${key} failed: ${errorMessage(error)}`)\n }\n}\n\nfunction summaryOfBlocks(blocks: readonly ContentBlock[]): string {\n const text = blocks.map(block => {\n if (block.type === 'text' || block.type === 'reasoning') return block.text\n if (block.type === 'tool-result') return summaryOfBlocks(block.content)\n if (block.type === 'image') return '[image]'\n if (block.type === 'file') return `[file: ${block.attachment.name}]`\n return `[tool: ${block.name}]`\n }).join(' ').replace(/\\s+/g, ' ').trim()\n return text.length > 300 ? `${text.slice(0, 300)}…` : text\n}\n\nfunction formatToolRecord(name: string, status: 'success' | 'error', summary: string, code?: ExtractedCode): string {\n const lines = ['ChatCode CLI 工具执行记录', '', `- 工具:${oneLine(name)}`, `- 状态:${status}`]\n if (code?.filePath) lines.push(`- 文件:${oneLine(code.filePath)}`)\n if (summary) lines.push(`- 摘要:${oneLine(summary)}`)\n if (!code?.code) return lines.join('\\n')\n const fence = '`'.repeat(Math.max(3, longestBacktickRun(code.code) + 1))\n return `${lines.join('\\n')}\\n\\n${fence}${code.language ?? ''}\\n${code.code}\\n${fence}`\n}\n\nfunction oneLine(value: string): string {\n return value.replace(/[\\r\\n]+/g, ' ').trim()\n}\n\nfunction longestBacktickRun(value: string): number {\n let longest = 0\n for (const match of value.matchAll(/`+/g)) longest = Math.max(longest, match[0].length)\n return longest\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","/** ChatCode model-source classification by normalized runtime base URL. */\n\n/** Model categories accepted by ChatCode operations reporting. */\nexport type ChatCodeModelKind = 0 | 1 | 2 | 3\n\n/** URL sets loaded from ChatCode system configuration. */\nexport type ModelKindUrls = Readonly<Record<0 | 1 | 3, ReadonlySet<string>>>\n\n/** Create an empty model-source configuration whose fallback category is `2`. */\nexport function emptyModelKindUrls(): ModelKindUrls {\n return { 0: new Set(), 1: new Set(), 3: new Set() }\n}\n\n/**\n * Normalize configured and runtime model URLs for exact source classification.\n * @param value - A configured gateway root or complete model request URL.\n * @returns A credential-free, query-free URL without a known request suffix.\n */\nexport function normalizeModelBaseUrl(value: string): string {\n const trimmed = value.trim()\n if (!trimmed) return ''\n try {\n const url = new URL(trimmed)\n url.username = ''\n url.password = ''\n url.search = ''\n url.hash = ''\n url.protocol = url.protocol.toLowerCase()\n url.hostname = url.hostname.toLowerCase()\n let pathname = url.pathname.replace(/\\/+$/u, '')\n for (const suffix of ['/chat/completions', '/chat/completion', '/v1/messages']) {\n if (!pathname.toLowerCase().endsWith(suffix)) continue\n pathname = pathname.slice(0, -suffix.length).replace(/\\/+$/u, '')\n break\n }\n url.pathname = pathname || '/'\n return url.toString().replace(/\\/$/u, '')\n } catch {\n return trimmed.toLowerCase().replace(/\\/+$/u, '')\n }\n}\n\n/**\n * Parse the semicolon-separated value returned by one ChatCode system setting.\n * @param value - Raw system setting value.\n * @returns Exact normalized URL members.\n */\nexport function parseModelBaseUrls(value: string): ReadonlySet<string> {\n return new Set(value.split(';').map(normalizeModelBaseUrl).filter(Boolean))\n}\n\n/**\n * Classify a runtime model URL; conflicting or absent matches use category `2`.\n * @param baseUrl - Actual model service address.\n * @param configured - URL sets for categories 0, 1, and 3.\n * @returns The unique matching category, or `2`.\n */\nexport function classifyModelBaseUrl(baseUrl: string, configured: ModelKindUrls): ChatCodeModelKind {\n const normalized = normalizeModelBaseUrl(baseUrl)\n if (!normalized) return 2\n const matches = ([0, 1, 3] as const).filter(kind =>\n [...configured[kind]].some(value => normalizeModelBaseUrl(value) === normalized))\n return matches.length === 1 ? matches[0] ?? 2 : 2\n}\n","/** Authenticated ChatCode HTTP protocol client. */\nimport { randomUUID } from 'node:crypto'\nimport type { ChatCodeAuthApi } from '../chatcode-auth.ts'\nimport { classifyModelBaseUrl, emptyModelKindUrls, parseModelBaseUrls, type ChatCodeModelKind, type ModelKindUrls } from './model-kind.ts'\nimport type { ChatMessagePayload, ConversationSyncPayload } from './payloads.ts'\n\nconst MODEL_KIND_CONFIG_KEYS = {\n 0: 'chatcode.cli.model.kind.0.baseurls',\n 1: 'chatcode.cli.model.kind.1.baseurls',\n 3: 'chatcode.cli.model.kind.3.baseurls',\n} as const\n\ninterface Logger {\n warn(message: string): void\n}\n\n/** Narrow transport operations consumed by the event projector. */\nexport interface ReportingTransport {\n /** Return the safe account label associated with the current grant. */\n identity(): Promise<string>\n /** Save generated code; success means the durable outbox may acknowledge it. */\n saveCodes(codes: readonly string[]): Promise<void>\n /** Synchronize conversation metadata and zero or more messages. */\n syncConversation(payload: ConversationSyncPayload): Promise<void>\n /** Create one ChatCode conversation and return its opaque id. */\n createChat(): Promise<string>\n /** Append one token-bearing model response to a ChatCode conversation. */\n addChatMessage(payload: ChatMessagePayload): Promise<void>\n /** Classify an actual model service URL through the cached ChatCode system configuration. */\n modelKind(baseUrl: string): Promise<ChatCodeModelKind>\n}\n\n/** Expected reporting failure without response-body or credential disclosure. */\nexport class ReportingRequestError extends Error {\n constructor(message: string, readonly kind: 'auth' | 'request' | 'response') {\n super(message)\n this.name = 'ReportingRequestError'\n }\n}\n\n/** Fetch-based implementation of the ChatCode reporting endpoints. */\nexport class ChatCodeTransport implements ReportingTransport {\n private readonly baseUrl: URL\n private modelKindUrls: ModelKindUrls = emptyModelKindUrls()\n private modelKindLoaded = false\n private modelKindLoad: Promise<void> | undefined\n\n constructor(\n private readonly auth: ChatCodeAuthApi,\n cvpChatCodeApiUrl: string,\n private readonly requestTimeoutMs: number,\n private readonly lifetime: AbortSignal,\n private readonly fetcher: typeof fetch = fetch,\n private readonly logger: Logger = { warn: () => undefined },\n ) {\n this.baseUrl = validatedBaseUrl(cvpChatCodeApiUrl)\n }\n\n async identity(): Promise<string> {\n const status = await this.auth.status()\n return status.emailAddress ?? status.userName ?? ''\n }\n\n async saveCodes(codes: readonly string[]): Promise<void> {\n const token = await this.token()\n const response = await this.request('wanma/to/openai/v2/save-code', {\n Authorization: token,\n }, { codes })\n if (!response.ok) throw this.httpError('save-code', response.status)\n await response.body?.cancel()\n }\n\n async syncConversation(payload: ConversationSyncPayload): Promise<void> {\n const token = await this.token()\n const response = await this.request('wanma/api/v1/conversations/sync', {\n Authorization: `Bearer ${token}`,\n }, payload)\n const text = await response.text()\n if (!response.ok) throw this.httpError('conversation sync', response.status)\n if (!text) return\n let body: unknown\n try {\n body = JSON.parse(text) as unknown\n } catch {\n return\n }\n if (isRecord(body) && body.code !== undefined && Number(body.code) !== 200) {\n throw new ReportingRequestError('conversation sync returned a non-success business code', businessKind(body.code))\n }\n }\n\n async createChat(): Promise<string> {\n const token = await this.token()\n const response = await this.request('chatcode/session/create', {\n Authorization: `Bearer ${token}`,\n }, { chatType: 1, sourceType: 5 })\n const body = await jsonBody(response, 'create ChatCode session')\n if (!response.ok) throw this.httpError('create ChatCode session', response.status)\n if (Number(body.code) !== 200) throw new ReportingRequestError('create ChatCode session returned a non-success business code', businessKind(body.code))\n const id = responseId(body)\n if (!id) throw new ReportingRequestError('create ChatCode session succeeded without a chat id', 'response')\n return id\n }\n\n async addChatMessage(payload: ChatMessagePayload): Promise<void> {\n const token = await this.token()\n const response = await this.request('chatcode/session/addMsgRecord', {\n Authorization: `Bearer ${token}`,\n }, payload)\n const body = await jsonBody(response, 'append ChatCode message')\n if (!response.ok) throw this.httpError('append ChatCode message', response.status)\n if (Number(body.code) !== 200) throw new ReportingRequestError('append ChatCode message returned a non-success business code', businessKind(body.code))\n if (!responseId(body)) throw new ReportingRequestError('append ChatCode message succeeded without a message id', 'response')\n }\n\n async modelKind(baseUrl: string): Promise<ChatCodeModelKind> {\n await this.loadModelKinds()\n return classifyModelBaseUrl(baseUrl, this.modelKindUrls)\n }\n\n private async loadModelKinds(): Promise<void> {\n if (this.modelKindLoaded) return\n if (this.modelKindLoad !== undefined) return this.modelKindLoad\n const pending = (async () => {\n try {\n const token = await this.token()\n const values = await Promise.all(([0, 1, 3] as const).map(async kind => {\n const key = MODEL_KIND_CONFIG_KEYS[kind]\n const response = await this.request(`system/config/configKey/${encodeURIComponent(key)}`, {\n Authorization: token,\n }, undefined, 'GET')\n if (!response.ok) throw this.httpError('load model-kind configuration', response.status)\n const body = await jsonBody(response, 'load model-kind configuration')\n return [kind, typeof body.msg === 'string' ? body.msg : ''] as const\n }))\n this.modelKindUrls = {\n 0: parseModelBaseUrls(values.find(([kind]) => kind === 0)?.[1] ?? ''),\n 1: parseModelBaseUrls(values.find(([kind]) => kind === 1)?.[1] ?? ''),\n 3: parseModelBaseUrls(values.find(([kind]) => kind === 3)?.[1] ?? ''),\n }\n } catch (error) {\n this.logger.warn(`chatcode-reporting: model-kind configuration is unavailable; using category 2: ${errorMessage(error)}`)\n } finally {\n this.modelKindLoaded = true\n }\n })()\n this.modelKindLoad = pending\n try {\n await pending\n } finally {\n if (this.modelKindLoad === pending) this.modelKindLoad = undefined\n }\n }\n\n private async token(): Promise<string> {\n const token = await this.auth.accessToken(this.lifetime)\n if (!token) throw new ReportingRequestError('ChatCode login is unavailable for reporting', 'auth')\n return token\n }\n\n private async request(\n path: string,\n extraHeaders: Record<string, string>,\n body: unknown,\n method: 'GET' | 'POST' = 'POST',\n ): Promise<Response> {\n const requestId = randomUUID()\n const signal = AbortSignal.any([this.lifetime, AbortSignal.timeout(this.requestTimeoutMs)])\n try {\n return await this.fetcher(new URL(path, this.baseUrl), {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': requestId,\n ...extraHeaders,\n },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n signal,\n redirect: 'error',\n })\n } catch (error) {\n if (signal.aborted) throw new ReportingRequestError(`ChatCode request was aborted (${requestId})`, 'request')\n throw new ReportingRequestError(`ChatCode request failed (${requestId}): ${error instanceof Error ? error.message : String(error)}`, 'request')\n }\n }\n\n private httpError(operation: string, status: number): ReportingRequestError {\n return new ReportingRequestError(`${operation} returned HTTP ${status}`, status === 401 || status === 403 ? 'auth' : 'request')\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction validatedBaseUrl(value: string): URL {\n const url = new URL(value)\n const loopback = ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname)\n if (url.username || url.password || (url.protocol !== 'https:' && !(url.protocol === 'http:' && loopback))) {\n throw new Error('ChatCode reporting requires HTTPS; HTTP is allowed only on loopback.')\n }\n url.pathname = `${url.pathname.replace(/\\/+$/u, '')}/`\n return url\n}\n\nasync function jsonBody(response: Response, operation: string): Promise<Record<string, unknown>> {\n try {\n const body = await response.json() as unknown\n if (isRecord(body)) return body\n } catch {\n // The protocol failure below owns the public diagnostic.\n }\n throw new ReportingRequestError(`${operation} returned invalid JSON`, 'response')\n}\n\nfunction responseId(body: Record<string, unknown>): string {\n const data = typeof body.data === 'string' ? body.data.trim() : ''\n if (data) return data\n const message = typeof body.msg === 'string' ? body.msg.trim() : ''\n return message && message !== '操作成功' && message.toLowerCase() !== 'success' ? message : ''\n}\n\nfunction businessKind(code: unknown): 'auth' | 'request' {\n const numeric = Number(code)\n return numeric === 401 || numeric === 403 ? 'auth' : 'request'\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/** Install ChatCode operations reporting over committed ChatCode CLI Session events. */\nimport type {} from '@deepseek-ai/dsh-agent'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { dshHomePath } from '@deepseek-ai/dsh-home-paths'\nimport { isAbsolute } from 'node:path'\nimport type { ChatCodeAuthApi } from '../chatcode-auth.ts'\nimport type { ReportingConfig } from '../config.ts'\nimport { CodeOutbox } from './outbox.ts'\nimport type { ModelReportResolver } from './payloads.ts'\nimport { ChatCodeReporter, CodeOutboxWorker } from './reporter.ts'\nimport { ChatCodeTransport } from './transport.ts'\n\n/** Resolved backend and reporting settings for one reporter instance. */\nexport interface ChatCodeReportingConfig extends ReportingConfig {\n /** CVP backend root for all reporting requests. */\n cvpChatCodeApiUrl: string\n /** Maximum duration of one backend request. */\n requestTimeoutMs: number\n}\n\n/** Register the reporter for all Sessions visible to this Cordis scope. */\nexport function installChatCodeReporting(\n ctx: Context,\n auth: ChatCodeAuthApi,\n config: ChatCodeReportingConfig,\n resolveModelReport: ModelReportResolver,\n): void {\n const lifetime = new AbortController()\n const transport = new ChatCodeTransport(auth, config.cvpChatCodeApiUrl, config.requestTimeoutMs, lifetime.signal, fetch, ctx.logger)\n if (config.codeOutboxDir !== '' && !isAbsolute(config.codeOutboxDir)) {\n throw new Error('ChatCode reporting codeOutboxDir must be an absolute path.')\n }\n const outbox = new CodeOutbox(config.codeOutboxDir || dshHomePath('chatcode-reporting', 'code-save-outbox'))\n const codeWorker = new CodeOutboxWorker(\n outbox,\n transport,\n config.codeBatchItems,\n config.codeBatchChars,\n config.codeRetryDelayMs,\n ctx.logger,\n )\n const reporter = new ChatCodeReporter(config, transport, codeWorker, ctx.logger, resolveModelReport)\n if (config.codeSave) codeWorker.start()\n ctx.on('session/created', session => { reporter.created(session) })\n ctx.on('agent/created', ({ agent }) => {\n reporter.seedModelRoute(agent.session, agent.options.provider, agent.options.model)\n return undefined\n })\n ctx.on('session/event', (session, event) => { reporter.observe(session, event) })\n ctx.on('session/disposed', session => reporter.disposed(session))\n ctx.effect(() => async () => {\n try {\n await reporter.shutdown()\n } finally {\n lifetime.abort()\n }\n }, 'chatcode-reporting: drain queued reports')\n}\n","/** Resolve custom-model settings and parse the legacy ChatCode JSON file. @module dsh-llm-chatcode-config/source */\n\nimport { createHash } from 'node:crypto'\nimport { readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport z from '@deepseek-ai/schemastery'\nimport { assertUsableApiKey, LlmError } from '@deepseek-ai/dsh-llm'\nimport type { PiAiRequestAuth } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport { resolveProfiles } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { PiAiProviderProfile, ResolvedPiAiProviderProfile } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { Config, CustomModel } from './config.ts'\n\nconst positiveInteger = z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER)\nconst documentSchema = z.object({\n customModels: z.array(z.object({\n model: z.string().required(),\n apiKey: z.string().required(),\n baseUrl: z.string().required(),\n description: z.string(),\n provider: z.union([z.string(), z.const(null)]),\n protocol: z.string(),\n contextWindow: positiveInteger,\n maxTokens: positiveInteger,\n maxInputTokens: positiveInteger,\n })).required(),\n})\n\n/** One activation's model profiles and private request credentials. */\nexport interface ChatCodeSource {\n /** Non-secret route and model metadata; immutable for the plugin's lifetime. */\n profiles: ReadonlyMap<string, ResolvedPiAiProviderProfile>\n /** Credentials are kept outside profile configuration and catalog responses. */\n auth: ReadonlyMap<string, PiAiRequestAuth>\n /** Validated literal keys retained for DeepSeek-native request dispatch. */\n apiKeys: ReadonlyMap<string, string>\n /** Public model identity to private provider/model routing. Never contains credentials. */\n selections: ReadonlyMap<string, ChatCodeModelSelection>\n /** Private source entries retained only by the Host so settings-managed models can merge with file imports. */\n entries?: readonly CustomModel[]\n}\n\n/** One public model selection's private request destination. */\nexport interface ChatCodeModelSelection {\n route: string\n model: string\n}\n\n/** Public reporting identity derived from one private model route. */\nexport interface ChatCodeModelReport {\n modelName: string\n baseUrl: string\n}\n\n/**\n * Resolve the actual provider model and service URL behind a public selection.\n * @param source - Current custom or managed model snapshot.\n * @param selection - Public model id selected through the aggregate provider.\n * @returns Reporting fields, or `undefined` when the selection is absent.\n */\nexport function reportModelFromSource(source: ChatCodeSource, selection: string): ChatCodeModelReport | undefined {\n const target = source.selections.get(selection)\n if (target === undefined) return undefined\n return {\n modelName: target.model,\n baseUrl: source.profiles.get(target.route)?.baseURL ?? '',\n }\n}\n\n/** Report only a field location: JSON/schema diagnostics may quote a credential. */\nfunction invalid(location: string): never {\n throw new LlmError(`chatcode-config: invalid ${location}`, 'INVALID_CHATCODE_CONFIG')\n}\n\n/** Normalize the two legacy wire dialects, retaining the provider=anthropic fallback. */\nfunction protocolOf(entry: CustomModel, location: string): 'openai-completions' | 'anthropic-messages' {\n switch (entry.protocol?.trim().toLowerCase()) {\n case undefined:\n case '':\n return entry.provider?.trim().toLowerCase() === 'anthropic' ? 'anthropic-messages' : 'openai-completions'\n case 'openai': return 'openai-completions'\n case 'anthropic': return 'anthropic-messages'\n default: return invalid(`${location}.protocol (expected OpenAI or Anthropic)`)\n }\n}\n\n/** Validate a complete base URL without discarding the gateway's path prefix. */\nfunction endpointOf(raw: string, location: string): string {\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n // URL parser messages include their input, which may contain credentials.\n return invalid(`${location}.baseUrl`)\n }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) {\n return invalid(`${location}.baseUrl (expected HTTP(S) without credentials, query, or fragment)`)\n }\n return url.href.replace(/\\/+$/, '')\n}\n\n/**\n * Validate customModels and resolve one detached activation snapshot.\n * @param data - parsed JSON from the external file, never a typed plugin configuration.\n * @param config - validated mount defaults.\n * @returns profiles and private credentials for exactly the declared model entries.\n */\nexport function resolveSource(data: unknown, config: Config): ChatCodeSource {\n let entries: CustomModel[]\n try {\n entries = documentSchema(data as Parameters<typeof documentSchema>[0]).customModels\n } catch {\n // Schema errors can quote source values; only the owning JSON field is public.\n return invalid('customModels (expected an array of models with model, baseUrl, and apiKey)')\n }\n const profiles: Record<string, PiAiProviderProfile> = {}\n const auth = new Map<string, PiAiRequestAuth>()\n const apiKeys = new Map<string, string>()\n const selections = new Map<string, ChatCodeModelSelection>()\n const modelIds = new Set<string>()\n for (const [index, entry] of entries.entries()) {\n const location = `customModels[${index}]`\n if (entry.model.trim() === '') invalid(`${location}.model`)\n if (modelIds.has(entry.model)) invalid(`${location}.model (duplicate model id in unified catalog)`)\n modelIds.add(entry.model)\n const api = protocolOf(entry, location)\n const baseURL = endpointOf(entry.baseUrl, location)\n const provider = `chatcode-${createHash('sha256').update(JSON.stringify([api, baseURL, entry.model])).digest('hex').slice(0, 20)}`\n const apiKey = assertUsableApiKey(entry.apiKey, 'chatcode-config', `${location}.apiKey`)\n profiles[provider] = {\n displayName: entry.description?.trim() || entry.model,\n api,\n baseURL,\n models: [{\n id: entry.model,\n name: entry.description?.trim() || entry.model,\n contextWindow: entry.contextWindow ?? entry.maxTokens ?? entry.maxInputTokens ?? config.defaultContextWindow,\n maxTokens: entry.maxTokens ?? config.defaultMaxTokens,\n }],\n ...api === 'openai-completions' ? { compat: { maxTokensField: 'max_tokens', supportsDeveloperRole: false } } : {},\n ...api === 'openai-completions' && /^minimax-m2(?:[.-]|$)/i.test(entry.model) ? { reasoningSplit: true } : {},\n ...config.retryPolicy === undefined ? {} : { retryPolicy: config.retryPolicy },\n }\n auth.set(provider, api === 'anthropic-messages'\n ? { headers: { Authorization: `Bearer ${apiKey}` } }\n : { apiKey })\n apiKeys.set(provider, apiKey)\n selections.set(entry.model, { route: provider, model: entry.model })\n }\n return { profiles: resolveProfiles(profiles), auth, apiKeys, selections, entries: entries.map(entry => ({ ...entry })) }\n}\n\n/**\n * Resolve the user-defined models in one validated settings snapshot.\n * @param config - Current resolved plugin settings.\n * @returns One immutable model and authentication snapshot.\n */\nexport function resolveConfiguredSource(config: Config): ChatCodeSource {\n return resolveSource({ customModels: config.customModels }, config)\n}\n\n/**\n * Read the configured Host file once; never use the agent's execution filesystem.\n * @param config - validated mount defaults and optional Host path.\n * @returns the complete validated snapshot; malformed JSON never appears in diagnostics.\n */\nexport async function readSource(config: Config): Promise<ChatCodeSource> {\n const filename = resolve(config.settingsPath ?? join(homedir(), '.chatcode-cli', 'settings.json'))\n let text: string\n try {\n text = await readFile(filename, 'utf8')\n } catch {\n // Host filesystem errors may quote sensitive paths; the mount owns the filename.\n throw new LlmError('chatcode-config: cannot read settingsPath', 'CHATCODE_CONFIG_READ_FAILED')\n }\n let data: unknown\n try {\n data = JSON.parse(text)\n } catch {\n // JSON syntax errors may include the source line containing an API key.\n throw new LlmError('chatcode-config: settingsPath is not valid JSON', 'INVALID_CHATCODE_CONFIG')\n }\n return resolveSource(data, config)\n}\n","/** Publish ChatCode-authenticated CodingPlan and MAAS catalogs into the LLM registry. @module dsh-llm-chatcode-config */\n\nimport { Service, type Context } from '@deepseek-ai/cordis'\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { AdapterRegistrationHandle } from '@deepseek-ai/dsh-llm'\nimport type { CredentialProvider } from '@deepseek-ai/dsh-credentials'\nimport type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands'\nimport type {} from '@deepseek-ai/dsh-cmdline'\nimport type {} from '@deepseek-ai/dsh-settings'\nimport { runUpdate, runUpdateSync } from './update.ts'\nimport { checkVersions, decisionPrompt, promptVersionAction, runDecisionInstall } from './version-check.ts'\nimport { isolatedPiAiAuth } from '../vendor/dsh-llm-pi-ai/src/auth.ts'\nimport {\n CHATCODE_PROVIDER,\n CODING_PLAN_PROVIDER,\n CODING_PLAN_PROVIDER_NAME,\n MAAS_PROVIDER,\n MAAS_PROVIDER_NAME,\n ChatCodeAdapter,\n LiveChatCodeAdapter,\n} from './adapter.ts'\nimport { chatCodeEnvironmentToken, ChatCodeAuthService } from './chatcode-auth.ts'\nimport { ChatCodeStartupGateService } from './startup-gate.ts'\nimport { Config } from './config.ts'\nimport { fetchMaasRuntimeModels, fetchRuntimeModels, resolveManagedSource } from './managed.ts'\nimport { installChatCodeReporting } from './reporting/index.ts'\nimport { readSource, reportModelFromSource, resolveConfiguredSource } from './source.ts'\nimport type { ChatCodeSource } from './source.ts'\n\nexport { Config } from './config.ts'\nexport type { CustomModel, ModelKindRule, ReportingConfig } from './config.ts'\nexport { ChatCodeAuthService } from './chatcode-auth.ts'\nexport { ChatCodeStartupGateService, checkChatCodeStartupGate, startupGateFailureMessage } from './startup-gate.ts'\nexport type { StartupGateResult, StartupGateFailure } from './startup-gate.ts'\n\nexport const name = 'llm-chatcode-config'\nexport const inject = ['llm']\nexport const SETTINGS_NAMESPACE = 'llm-chatcode-config'\n\n/** Optional, host-only refresh seam for terminal and browser clients. */\nexport interface ChatCodeModelCatalogApi {\n /** Reload CodingPlan and, when enabled, MAAS routes into the LLM registry. */\n refresh(): Promise<void>\n /** Current effective MAAS switch value. */\n maasEnabled(): boolean\n /** Persist the MAAS switch and wait for the matching catalog refresh. */\n setMaasEnabled(enabled: boolean): Promise<void>\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { chatcodeModelCatalog: ChatCodeModelCatalogService }\n}\n\n/**\n * Keeps catalog I/O in the host bundle: clients ask for a registry refresh but\n * never receive endpoint or credential-bearing runtime configuration.\n */\nexport class ChatCodeModelCatalogService extends Service implements ChatCodeModelCatalogApi {\n private writeMaas: ((enabled: boolean) => Promise<void>) | undefined\n\n constructor(\n ctx: Context,\n private readonly reload: () => Promise<void>,\n private readonly readMaas: () => boolean,\n ) {\n super(ctx, 'chatcodeModelCatalog')\n }\n\n refresh(): Promise<void> {\n return this.reload()\n }\n\n maasEnabled(): boolean {\n return this.readMaas()\n }\n\n async setMaasEnabled(enabled: boolean): Promise<void> {\n if (this.writeMaas === undefined) {\n throw new Error('ChatCode MAAS settings are not ready; retry after the Host finishes starting.')\n }\n await this.writeMaas(enabled)\n await this.reload()\n }\n\n /** Bind the durable settings writer once the optional settings service mounts. */\n bindMaasSettings(write: (enabled: boolean) => Promise<void>): void {\n this.writeMaas = write\n }\n}\n\n/** Register ChatCode model sources, account access, and operations reporting. */\nexport async function apply(ctx: Context, config: Config): Promise<void> {\n const environmentAccessToken = chatCodeEnvironmentToken(ctx)\n const catalogAuthorization = environmentAccessToken === undefined\n ? undefined\n : { accessToken: environmentAccessToken }\n // `chatcode-cli --update` reaches the tree as an inner argument; refresh the global\n // install and exit before any catalog boot work or interactive surface mounts.\n // First statement on purpose: a self-update must win over every later failure.\n // It is synchronous on purpose too: the profile's other plugins boot\n // concurrently, and `chatcode-cli --update` must finish — and exit — before any of\n // them can print. The final line is written (the console write is issued\n // immediately), then the process dies instead of returning into the boot.\n if ((ctx.get('cmdlineArgs')?.get() ?? []).includes('--update')) {\n const result = runUpdateSync()\n process.stdout.write(`${result.message}\\n`)\n process.exit(result.status === 'error' ? 1 : 0)\n }\n\n new ChatCodeStartupGateService(ctx, config)\n\n // Startup version admission: only a launcher-provided command line reaches\n // this path. Validate the ChatCode CLI package against CVP and, when the server\n // asks for an upgrade or a rollback, resolve the choice before the\n // interactive surface mounts. Network/probe failures leave startup open.\n if (ctx.get('cmdlineArgs') !== undefined) {\n const decision = await checkVersions(config)\n if (decision !== undefined) {\n const choice = await promptVersionAction(decisionPrompt(decision))\n if (choice !== 'perform') {\n ctx.get('appExit')?.(0)\n return\n }\n const verb = decision.action === 'upgrade' ? '升级' : '更换'\n process.stdout.write(`正在${verb}中...\\n`)\n const result = await runDecisionInstall(decision)\n process.stdout.write(`${result.message}\\n`)\n ctx.get('appExit')?.(result.ok ? 0 : 1)\n return\n }\n }\n\n // `/update` slash command, available from both the browser and terminal surfaces.\n ctx.inject(['commands'], commandsCtx => {\n commandsCtx.commands.register({\n name: 'update',\n description: '更新 ChatCode CLI 到最新版本',\n handler: async (invocation: CommandInvocation): Promise<CommandResult> => {\n // Progress lines are broadcast for the terminal surface, which renders\n // them live in an overlay panel; other surfaces (web) ignore the event\n // and just read the returned result text.\n const result = await runUpdate({\n signal: invocation.signal,\n onProgress: line => {\n (ctx.emit as (name: string, ...args: unknown[]) => void)('llm-chatcode-config/update-progress', line)\n },\n })\n return result.status === 'error'\n ? { kind: 'error', text: result.message }\n : { kind: 'success', text: result.message }\n },\n })\n })\n\n const register = (provider: string, providerName: string, source: ChatCodeSource): AdapterRegistrationHandle | undefined => {\n if (source.profiles.size === 0) return undefined\n const adapter = new ChatCodeAdapter({\n profiles: () => source.profiles,\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Profiles and auth share keys; route resolution precedes auth.\n resolveAuth: route => Promise.resolve(source.auth.get(route)!),\n auth: isolatedPiAiAuth(),\n }, source.profiles, provider, providerName, source.selections, source.apiKeys)\n return ctx.llm.registerAdapter([provider], adapter)\n }\n\n let current: () => Config = () => config\n let lastCustomConfig: Config | undefined\n let customSourceSnapshot: ChatCodeSource | undefined\n const customSource = (): ChatCodeSource => {\n const resolved = current()\n if (resolved === lastCustomConfig && customSourceSnapshot !== undefined) return customSourceSnapshot\n const source = resolveConfiguredSource(resolved)\n lastCustomConfig = resolved\n customSourceSnapshot = source\n return source\n }\n const customAdapter = new LiveChatCodeAdapter(customSource)\n let customRegistration: AdapterRegistrationHandle | undefined\n const refreshCustom = (): void => {\n const routes = customSource().profiles.size === 0 ? [] : [CHATCODE_PROVIDER]\n if (customRegistration === undefined) {\n if (routes.length === 0) return\n customRegistration = ctx.llm.registerAdapter(routes, customAdapter)\n return\n }\n customRegistration.replace(routes)\n }\n const managedRegistrations = new Map<string, AdapterRegistrationHandle>()\n const managedSources = new Map<string, ChatCodeSource>()\n const resolveReportingModel = (provider: string, model: string): { modelName: string; baseUrl: string } => {\n const source = provider === CHATCODE_PROVIDER ? customSource() : managedSources.get(provider)\n return source === undefined ? { modelName: model, baseUrl: '' }\n : reportModelFromSource(source, model) ?? { modelName: model, baseUrl: '' }\n }\n\n ctx.inject(['credentials'], authCtx => {\n const auth = new ChatCodeAuthService(\n authCtx,\n authCtx.get('credentials') as CredentialProvider,\n config.auth,\n environmentAccessToken,\n )\n if (config.reporting.enabled) {\n authCtx.inject(['sessions'], reportingCtx => {\n installChatCodeReporting(reportingCtx, auth, {\n ...config.reporting,\n cvpChatCodeApiUrl: config.cvpChatCodeApiUrl,\n requestTimeoutMs: config.auth.requestTimeoutMs,\n }, resolveReportingModel)\n })\n }\n })\n\n let refreshQueued = false\n let refreshInFlight: Promise<void> | undefined\n const clearManaged = (): void => {\n for (const registration of managedRegistrations.values()) registration()\n managedRegistrations.clear()\n managedSources.clear()\n }\n const refreshOnce = async (): Promise<void> => {\n clearManaged()\n const resolved = current()\n const catalogs: { provider: string; name: string; endpoint: string; group: 'codingplan' | 'maas' }[] = [{\n provider: CODING_PLAN_PROVIDER,\n name: CODING_PLAN_PROVIDER_NAME,\n endpoint: resolved.codingPlanEndpoint,\n group: 'codingplan',\n }]\n if (resolved.enableMaas) {\n if (resolved.maasEndpoint.trim() === '') {\n ctx.logger.warn('chatcode-config: MAAS is enabled but no MAAS catalog endpoint is configured')\n } else {\n catalogs.push({ provider: MAAS_PROVIDER, name: MAAS_PROVIDER_NAME, endpoint: resolved.maasEndpoint, group: 'maas' })\n }\n }\n const loaded = await Promise.all(catalogs.map(async catalog => {\n try {\n const models = catalog.group === 'maas'\n ? await fetchMaasRuntimeModels(catalog.endpoint, resolved.catalogTimeoutMs, catalogAuthorization)\n : await fetchRuntimeModels(\n catalog.endpoint,\n resolved.catalogTimeoutMs,\n catalogAuthorization,\n message => ctx.logger.info(message),\n )\n const source = resolveManagedSource(models, catalog.group, resolved)\n if (catalog.group === 'codingplan') {\n ctx.logger.info(`chatcode-config: CodingPlan registered ${String(source.selections.size)} runnable models from ${String(models.length)} parsed records`)\n }\n return { catalog, source }\n } catch (error) {\n if (error instanceof LlmError) {\n ctx.logger.warn(`chatcode-config: ${catalog.name} models were not registered (${error.code})`)\n return undefined\n }\n throw error\n }\n }))\n // Keep the custom adapter available while remote catalogs load, then\n // rebuild all three product-facing groups as one ordered registry block.\n // Web consumes `listProviders()` in registration order, so managed\n // catalogs register first and the user catalog last.\n if (customRegistration !== undefined) {\n customRegistration()\n customRegistration = undefined\n }\n for (const entry of loaded) {\n if (entry === undefined) continue\n const registration = register(entry.catalog.provider, entry.catalog.name, entry.source)\n if (registration !== undefined) {\n managedRegistrations.set(entry.catalog.provider, registration)\n managedSources.set(entry.catalog.provider, entry.source)\n }\n }\n refreshCustom()\n }\n // Settings can invoke `onChange()` during installation, while TUI can ask\n // for the same refresh as it boots. Ordinary callers share one request;\n // only an actual settings change queues a second pass.\n const refreshManaged = (): Promise<void> => {\n if (refreshInFlight !== undefined) return refreshInFlight\n const task = (async () => {\n do {\n refreshQueued = false\n await refreshOnce()\n } while (refreshQueued)\n })()\n const tracked = task.finally(() => {\n if (refreshInFlight === tracked) refreshInFlight = undefined\n })\n refreshInFlight = tracked\n return tracked\n }\n const refreshForSettingsChange = (): void => {\n // Settings edits affect custom calls immediately. The managed refresh\n // later re-registers this adapter at the end to restore display order.\n refreshCustom()\n if (refreshInFlight !== undefined) {\n refreshQueued = true\n return\n }\n void refreshManaged()\n }\n const modelCatalogService = new ChatCodeModelCatalogService(\n ctx,\n refreshManaged,\n () => current().enableMaas,\n )\n\n ctx.logger.info(`chatcode-config: waiting for settings service to register namespace \"${SETTINGS_NAMESPACE}\"`)\n ctx.inject(['settings'], async settingsCtx => {\n ctx.logger.info(`chatcode-config: settings service available; registering namespace \"${SETTINGS_NAMESPACE}\"`)\n try {\n settingsCtx.settings.installSection(ctx, SETTINGS_NAMESPACE, Config, config, {\n setSource: source => { current = source },\n onChange: refreshForSettingsChange,\n validate: value => { resolveConfiguredSource(value) },\n })\n } catch (error) {\n ctx.logger.warn(`chatcode-config: failed to register settings namespace \"${SETTINGS_NAMESPACE}\" (${error instanceof Error ? error.message : String(error)})`)\n throw error\n }\n modelCatalogService.bindMaasSettings(async enabled => {\n ctx.logger.info(`chatcode-config: persisting MAAS setting enableMaas=${String(enabled)}`)\n const ops = [{ op: 'set' as const, path: ['enableMaas'], value: enabled }]\n const revision = (): number | undefined =>\n settingsCtx.settings.describe().find(entry => entry.ns === SETTINGS_NAMESPACE)?.revision\n try {\n await settingsCtx.settings.mutate(SETTINGS_NAMESPACE, ops, revision())\n } catch (error) {\n if ((error as { code?: unknown })?.code !== 'SETTINGS_CONFLICT') throw error\n await settingsCtx.settings.mutate(SETTINGS_NAMESPACE, ops, revision())\n }\n ctx.logger.info(`chatcode-config: persisted MAAS setting enableMaas=${String(enabled)}`)\n })\n const descriptor = settingsCtx.settings.describe().find(entry => entry.ns === SETTINGS_NAMESPACE)\n ctx.logger.info(`chatcode-config: settings namespace \"${SETTINGS_NAMESPACE}\" registered=${String(descriptor !== undefined)} revision=${String(descriptor?.revision ?? 'missing')} enableMaas=${String(current().enableMaas)}`)\n if (descriptor?.user !== undefined) {\n ctx.logger.info(`chatcode-config: settings namespace \"${SETTINGS_NAMESPACE}\" loaded an existing user section`)\n return\n }\n try {\n const imported = await readSource(config)\n await settingsCtx.settings.replace(SETTINGS_NAMESPACE, { customModels: imported.entries ?? [] })\n ctx.logger.info(`chatcode-config: settings namespace \"${SETTINGS_NAMESPACE}\" initialized from the legacy source`)\n } catch (error) {\n if (!(error instanceof LlmError)) throw error\n ctx.logger.warn('chatcode-config: legacy settingsPath is unavailable or invalid; custom models were not imported and import will retry when the Host starts again')\n }\n })\n // Always populate the catalog during host startup. When settings is mounted,\n // its initial onChange may already have started this same single-flight load.\n await refreshManaged()\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["invalid","Config","wait","protocolOf","endpointOf","isRecord","isRecord","errorMessage"],"sources":["../src/update.ts","../src/version-check.ts","../vendor/dsh-llm-pi-ai/src/auth.ts","../vendor/dsh-llm-pi-ai/src/replay.ts","../vendor/dsh-llm-pi-ai/src/catalog.ts","../vendor/dsh-llm-pi-ai/src/provider.ts","../vendor/dsh-llm-pi-ai/src/config.ts","../vendor/dsh-llm-pi-ai/src/context.ts","../vendor/dsh-llm-pi-ai/src/stream.ts","../vendor/dsh-llm-pi-ai/src/adapter.ts","../src/adapter.ts","../src/chatcode-auth.ts","../src/config.ts","../src/managed.ts","../src/reporting/outbox.ts","../src/reporting/code.ts","../src/reporting/payloads.ts","../src/reporting/reporter.ts","../src/reporting/model-kind.ts","../src/reporting/transport.ts","../src/reporting/index.ts","../src/source.ts","../src/index.ts"],"sourcesContent":["/** Self-update for the global ChatCode CLI installation. @module dsh-llm-chatcode-config/update */\n\nimport { spawn, spawnSync, type ChildProcess, type StdioOptions } from 'node:child_process'\nimport { createRequire } from 'node:module'\n\n/**\n * The public ChatCode CLI package owns both browser and terminal surfaces.\n */\nexport const CHATCODE_CLI_PACKAGES = ['@chatcode/chatcode-cli'] as const\n\n/** Bound one npm call so a stalled registry cannot hang the command forever. */\nconst VIEW_TIMEOUT_MS = 20_000\nconst LIST_TIMEOUT_MS = 15_000\nconst INSTALL_TIMEOUT_MS = 120_000\n\n/** Outcome of one update run, shared by `chatcode-cli --update` and `/update`. */\nexport interface UpdateResult {\n status: 'up-to-date' | 'updated' | 'error' | 'aborted'\n /** Human-facing summary shown by both entry points. */\n message: string\n}\n\n/** Progress sink and cancellation for the interactive `/update` path. */\nexport interface UpdateOptions {\n /** Cancel the run: each awaited step checks it and npm children are killed. */\n signal?: AbortSignal\n /** Receive one progress line instead of writing it to stdout. */\n onProgress?: (line: string) => void\n}\n\n/** Print one progress line to the terminal while an update runs. */\nfunction log(message: string): void {\n process.stdout.write(`[update] ${message}\\n`)\n}\n\n/**\n * Run one npm invocation and capture its exit code and combined output.\n * Registry, auth, and proxy resolution are npm's own business: no registry is\n * forced, so a project's `.npmrc` (mirror, scoped registry, token) applies.\n * @param args - npm arguments after the `npm` command word.\n * @param timeoutMs - bound on the whole invocation.\n */\nfunction runNpm(args: readonly string[], timeoutMs: number, signal?: AbortSignal): Promise<{ code: number; output: string }> {\n return new Promise((resolve) => {\n // Windows resolves npm through its .cmd shim, which Node refuses to spawn\n // without a shell since the CVE-2024-27980 hardening. The shell receives a\n // single command string (never an argument array), which also avoids the\n // DEP0190 warning about unescaped shell arguments.\n const win = process.platform === 'win32'\n const stdio: StdioOptions = ['ignore', 'pipe', 'pipe']\n let child: ChildProcess\n if (win) {\n // A single command string, so no argument array is exposed to the shell.\n const spec = args.map(argument => /\\s/.test(argument) ? JSON.stringify(argument) : argument).join(' ')\n child = spawn(`npm ${spec}`, { shell: true, stdio })\n } else {\n child = spawn('npm', args, { stdio })\n }\n let output = ''\n let done = false\n const settle = (code: number): void => {\n if (done) return\n done = true\n clearTimeout(timer)\n if (signal !== undefined) signal.removeEventListener('abort', onAbort)\n resolve({ code, output })\n }\n const timer = setTimeout(() => { child.kill() }, timeoutMs)\n // An interactive cancellation kills the npm child so a stalled install\n // cannot keep running behind the closed panel.\n const onAbort = (): void => {\n clearTimeout(timer)\n child.kill()\n }\n if (signal !== undefined) {\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n const collect = (chunk: Buffer): void => { output += chunk.toString() }\n child.stdout?.on('data', collect)\n child.stderr?.on('data', collect)\n child.on('error', (error) => { output += String(error); settle(-1) })\n child.on('close', (code) => { settle(code ?? -1) })\n })\n}\n\n/** Strip npm's advisory `npm warn` lines from captured combined output. */\nfunction cleanNpmOutput(output: string): string {\n return output.split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(line => line !== '' && !/^npm warn\\b/i.test(line))\n .join('\\n')\n}\n\n/**\n * Turn npm's noisy combined output into one readable failure line. `--json`\n * errors print `{ \"error\": { \"code\", \"summary\", \"detail\" } }` on stderr,\n * possibly surrounded by `npm error` prose; lift the first brace block and read\n * the summary from it, else fall back to the cleaned raw text.\n */\nfunction describeNpmFailure(output: string, packageName: string): string {\n const start = output.indexOf('{')\n const end = output.lastIndexOf('}')\n if (start !== -1 && end > start) {\n try {\n const parsed = JSON.parse(output.slice(start, end + 1)) as { error?: { code?: unknown; summary?: unknown; detail?: unknown } }\n const code = typeof parsed.error?.code === 'string' ? parsed.error.code : undefined\n const summary = typeof parsed.error?.summary === 'string' ? parsed.error.summary : undefined\n if (code !== undefined || summary !== undefined) {\n return `${summary ?? code}(${packageName})`\n }\n } catch {\n // Not a parseable JSON block; fall through to the cleaned raw text.\n }\n }\n const cleaned = cleanNpmOutput(output)\n return `${cleaned || 'npm view 失败'}(${packageName})`\n}\n\n/**\n * Fetch the latest published version of one package through `npm view`, so the\n * same registry, scoped-registry override, and auth token the installer uses\n * also decide what \"latest\" means.\n */\nexport async function fetchLatestVersion(packageName: string, signal?: AbortSignal): Promise<string> {\n const result = await runNpm(['view', packageName, 'version', '--json'], VIEW_TIMEOUT_MS, signal)\n if (result.code !== 0 || result.output.trim() === '') {\n throw new Error(describeNpmFailure(result.output, packageName))\n }\n const stdout = cleanNpmOutput(result.output)\n try {\n const parsed = JSON.parse(stdout) as unknown\n if (typeof parsed === 'string' && parsed !== '') return parsed\n } catch {\n // npm prints a bare version string on some versions; fall through.\n }\n throw new Error(`无法从 registry 解析最新版本(${packageName})`)\n}\n\n/** Best-effort read of one installed package version from a co-located install. */\nfunction resolveCoLocatedVersion(packageName: string): string | undefined {\n try {\n const require = createRequire(import.meta.url)\n const manifest = require(`${packageName}/package.json`) as { version?: unknown }\n return typeof manifest.version === 'string' ? manifest.version : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Extract the `--json` result from npm's combined output. npm can prefix\n * advisory `npm warn` lines on stderr (e.g. from a pnpm-injected env config),\n * so lift the first brace block and parse just that, not the whole stream.\n */\nfunction parseNpmJson(output: string): unknown {\n const start = output.indexOf('{')\n const end = output.lastIndexOf('}')\n if (start === -1 || end <= start) return undefined\n try {\n return JSON.parse(output.slice(start, end + 1)) as unknown\n } catch {\n return undefined\n }\n}\n\n/** Resolve one installed global package version through npm's own store. */\nasync function resolveGlobalVersion(packageName: string, signal?: AbortSignal): Promise<string | undefined> {\n const result = await runNpm(['list', '-g', packageName, '--json', '--depth=0'], LIST_TIMEOUT_MS, signal)\n // npm ls can exit non-zero for unrelated problems in the global tree; only an\n // empty or unparseable payload counts as \"not found\".\n if (result.output.trim() === '') return undefined\n const parsed = parseNpmJson(result.output) as { dependencies?: Record<string, { version?: unknown }> } | undefined\n const version = parsed?.dependencies?.[packageName]?.version\n return typeof version === 'string' ? version : undefined\n}\n\n/**\n * Best-effort read of one installed package version; `undefined` when it cannot\n * be resolved. The co-located probe first targets a dev tree, then falls back\n * to npm's view of the global install.\n */\nexport async function resolveCurrentVersion(packageName: string, signal?: AbortSignal): Promise<string | undefined> {\n return resolveCoLocatedVersion(packageName) ?? await resolveGlobalVersion(packageName, signal)\n}\n\n/** Run `npm install -g <specs...>`, letting npm pick the registry it would install from. */\nexport function runNpmInstall(packageSpecs: readonly string[], signal?: AbortSignal): Promise<{ code: number; output: string }> {\n return runNpm(['install', '-g', ...packageSpecs], INSTALL_TIMEOUT_MS, signal)\n}\n\n/** One package's installed and published versions. */\ninterface PackageUpdate {\n name: string\n current: string | undefined\n latest: string\n}\n\n/**\n * Check the latest version and, when newer than the running one, install the\n * public ChatCode CLI package. Progress lines go to `options.onProgress` when given (the\n * interactive surface renders them in a panel), else to stdout — so the\n * `chatcode-cli --update` sync entry point keeps printing as before. Every awaited step\n * honors `options.signal`: an abort kills the in-flight npm child and settles\n * with the `aborted` status.\n */\nexport async function runUpdate(options: UpdateOptions = {}): Promise<UpdateResult> {\n const { signal, onProgress } = options\n const progress = (line: string): void => {\n if (onProgress !== undefined) onProgress(line)\n else log(line)\n }\n const aborted = (): UpdateResult | undefined =>\n signal?.aborted === true ? { status: 'aborted', message: '更新已中止' } : undefined\n\n progress(`开始检查更新:${CHATCODE_CLI_PACKAGES.join('、')}`)\n const updates: PackageUpdate[] = []\n for (const name of CHATCODE_CLI_PACKAGES) {\n if (aborted() !== undefined) return aborted()!\n const current = await resolveCurrentVersion(name, signal)\n if (aborted() !== undefined) return aborted()!\n progress(`当前版本 ${name}:${current ?? '(未安装或未解析)'}`)\n let latest: string\n try {\n latest = await fetchLatestVersion(name, signal)\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error)\n progress(`检查 ${name} 最新版本失败:${detail}`)\n return {\n status: 'error',\n message: `检查更新失败:${detail}`,\n }\n }\n if (aborted() !== undefined) return aborted()!\n progress(`最新版本 ${name}:${latest}`)\n updates.push({ name, current, latest })\n }\n\n const needsUpdate = updates.some(update => update.current !== update.latest)\n if (!needsUpdate) {\n const summary = updates.map(update => `${update.name} ${update.latest}`).join(',')\n progress('ChatCode CLI 已是最新版本,无需更新')\n return { status: 'up-to-date', message: `ChatCode CLI 已是最新版本(${summary})` }\n }\n\n const packageSpecs = updates.map(update => `${update.name}@${update.latest}`)\n progress(`检测到新版本,开始安装:${packageSpecs.join(' ')}`)\n const result = await runNpmInstall(packageSpecs, signal)\n if (aborted() !== undefined) return aborted()!\n if (result.code !== 0) {\n const detail = cleanNpmOutput(result.output) || '未知错误'\n progress(`安装失败(exit ${result.code})`)\n return {\n status: 'error',\n message: `更新失败:${detail}\\n请手动执行:npm install -g ${packageSpecs.join(' ')}`,\n }\n }\n\n progress('安装完成')\n const summary = updates.map(update => `${update.name} ${update.current ?? '(未知)'} → ${update.latest}`).join(',')\n return { status: 'updated', message: `已更新:${summary},请重启 ChatCode CLI 以生效` }\n}\n\n/** Run one npm invocation synchronously and capture its exit code and output. */\nfunction syncRunNpm(args: readonly string[], timeoutMs: number): { code: number; output: string } {\n const win = process.platform === 'win32'\n const spec = args.map(argument => /\\s/.test(argument) ? JSON.stringify(argument) : argument).join(' ')\n const result = win\n ? spawnSync(`npm ${spec}`, { shell: true, encoding: 'utf8', timeout: timeoutMs, stdio: ['ignore', 'pipe', 'pipe'] })\n : spawnSync('npm', args, { encoding: 'utf8', timeout: timeoutMs, stdio: ['ignore', 'pipe', 'pipe'] })\n if (result.error !== undefined) return { code: -1, output: String(result.error) }\n return { code: result.status ?? -1, output: `${result.stdout ?? ''}${result.stderr ?? ''}` }\n}\n\n/**\n * Print one progress line without yielding the event loop. On a Windows\n * console `process.stdout.write` still issues the console write immediately\n * (libuv calls WriteConsoleW synchronously), so the bytes are on screen before\n * the caller's hard exit — and because we never yield, the concurrently booting\n * profile stays frozen and cannot print its own logs.\n */\nfunction syncLog(message: string): void {\n process.stdout.write(`[update] ${message}\\n`)\n}\n\n/** Resolve one installed global package version synchronously through npm's store. */\nfunction resolveGlobalVersionSync(packageName: string): string | undefined {\n const result = syncRunNpm(['list', '-g', packageName, '--json', '--depth=0'], LIST_TIMEOUT_MS)\n if (result.output.trim() === '') return undefined\n const parsed = parseNpmJson(result.output) as { dependencies?: Record<string, { version?: unknown }> } | undefined\n const version = parsed?.dependencies?.[packageName]?.version\n return typeof version === 'string' ? version : undefined\n}\n\n/**\n * Synchronous twin of {@link runUpdate} for `chatcode-cli --update`. Blocking the event\n * loop on purpose: the profile's other plugins boot concurrently with this one,\n * and `chatcode-cli --update` must finish — and exit — before any of them can print.\n * The final message is returned, not logged, so the caller writes it once and\n * picks the exit code.\n */\nexport function runUpdateSync(): UpdateResult {\n syncLog(`开始检查更新:${CHATCODE_CLI_PACKAGES.join('、')}`)\n const updates: PackageUpdate[] = []\n for (const name of CHATCODE_CLI_PACKAGES) {\n const current = resolveCoLocatedVersion(name) ?? resolveGlobalVersionSync(name)\n syncLog(`当前版本 ${name}:${current ?? '(未安装或未解析)'}`)\n const view = syncRunNpm(['view', name, 'version', '--json'], VIEW_TIMEOUT_MS)\n let latest: string\n if (view.code !== 0 || view.output.trim() === '') {\n const detail = describeNpmFailure(view.output, name)\n syncLog(`检查 ${name} 最新版本失败:${detail}`)\n return { status: 'error', message: `检查更新失败:${detail}` }\n }\n try {\n const parsed = JSON.parse(cleanNpmOutput(view.output)) as unknown\n if (typeof parsed !== 'string' || parsed === '') throw new Error('invalid version payload')\n latest = parsed\n } catch {\n const detail = `无法从 registry 解析最新版本(${name})`\n syncLog(`检查 ${name} 最新版本失败:${detail}`)\n return { status: 'error', message: `检查更新失败:${detail}` }\n }\n syncLog(`最新版本 ${name}:${latest}`)\n updates.push({ name, current, latest })\n }\n\n const needsUpdate = updates.some(update => update.current !== update.latest)\n if (!needsUpdate) {\n const summary = updates.map(update => `${update.name} ${update.latest}`).join(',')\n syncLog('ChatCode CLI 已是最新版本,无需更新')\n return { status: 'up-to-date', message: `ChatCode CLI 已是最新版本(${summary})` }\n }\n\n const packageSpecs = updates.map(update => `${update.name}@${update.latest}`)\n syncLog(`检测到新版本,开始安装:${packageSpecs.join(' ')}`)\n const install = syncRunNpm(['install', '-g', ...packageSpecs], INSTALL_TIMEOUT_MS)\n if (install.code !== 0) {\n const detail = cleanNpmOutput(install.output) || '未知错误'\n syncLog(`安装失败(exit ${install.code})`)\n return { status: 'error', message: `更新失败:${detail}\\n请手动执行:npm install -g ${packageSpecs.join(' ')}` }\n }\n\n syncLog('安装完成')\n const summary = updates.map(update => `${update.name} ${update.current ?? '(未知)'} → ${update.latest}`).join(',')\n return { status: 'updated', message: `已更新:${summary},请重启 ChatCode CLI 以生效` }\n}\n","/**\n * Startup version admission against the CVP version-validate endpoint.\n *\n * Mirrors the `yuanjing-wanma-cli` startup flow: after launch, ask CVP whether\n * the installed ChatCode CLI package is still usable. When the server reports a newer\n * enabled version (status 1) or a disabled current version with a rollback\n * (status -1), present a keyboard dialog and either install the server-selected\n * version or leave the program before the interactive surface mounts.\n * @module dsh-llm-chatcode-config/version-check\n */\n\nimport { emitKeypressEvents, type Key } from 'node:readline'\nimport { stdin, stdout } from 'node:process'\nimport type { Config } from './config.ts'\nimport { CHATCODE_CLI_PACKAGES, resolveCurrentVersion, runNpmInstall } from './update.ts'\n\nexport type VersionCheckAction = 'upgrade' | 'rollback'\n\n/** One ChatCode CLI package the server asked us to move. */\nexport interface VersionCheckPackage {\n name: string\n /** Version currently installed on this machine. */\n currentVersion: string\n /** Version the server wants us to install. */\n targetVersion: string\n}\n\n/** A startup decision that requires user interaction. */\nexport interface VersionCheckDecision {\n action: VersionCheckAction\n packages: VersionCheckPackage[]\n}\n\nexport interface VersionCheckOptions {\n request?: typeof fetch\n resolveVersion?: (packageName: string) => Promise<string | undefined>\n timeoutMs?: number\n}\n\n/** Union of the endpoint's two status envelopes plus the 500 error fallback. */\ninterface ValidateBody {\n code?: unknown\n data?: unknown\n status?: unknown\n version?: unknown\n}\n\nconst ERROR_CODE = 500\n\nfunction validateUrl(cvpChatCodeApiUrl: string): URL {\n const base = cvpChatCodeApiUrl.replace(/\\/+$/u, '')\n return new URL(`${base}/chatcode/api/v1/cli/version/validate`)\n}\n\n/**\n * Interpret one 200 JSON body. Returns nothing when the server said \"valid\",\n * \"unknown package/version\", or errored — every such case leaves startup alone,\n * matching the reference's fail-open behavior.\n */\nfunction decide(body: ValidateBody): { action: VersionCheckAction; version: string } | undefined {\n if (body.code === ERROR_CODE) return undefined\n const data = body.data\n const payload = data !== null && typeof data === 'object' ? data as ValidateBody : body\n if (typeof payload.version === 'string' && payload.version !== '') {\n if (payload.status === 1) return { action: 'upgrade', version: payload.version }\n if (payload.status === -1) return { action: 'rollback', version: payload.version }\n }\n return undefined\n}\n\nasync function validatePackage(\n config: Config,\n packageName: string,\n options: VersionCheckOptions,\n): Promise<{ action: VersionCheckAction; currentVersion: string; version: string } | undefined> {\n const resolveVersion = options.resolveVersion ?? resolveCurrentVersion\n let versionNum: string | undefined\n try {\n versionNum = await resolveVersion(packageName)\n } catch {\n return undefined\n }\n if (versionNum === undefined || versionNum === '') return undefined\n\n const url = validateUrl(config.cvpChatCodeApiUrl)\n url.searchParams.set('packageName', packageName)\n url.searchParams.set('versionNum', versionNum)\n\n // console.log(`[version-check] 开始校验 ${packageName}@${versionNum}`)\n const request = options.request ?? fetch\n let response: Response\n try {\n response = await request(url, { signal: AbortSignal.timeout(options.timeoutMs ?? 10_000) })\n } catch (err) {\n console.log(`[version-check] 请求失败 (${packageName}): ${(err as Error)?.message ?? err}`)\n return undefined\n }\n if (!response.ok) return undefined\n const body = await response.json().catch(() => undefined) as ValidateBody | undefined\n if (body === null || typeof body !== 'object') return undefined\n const wrapped = decide(body)\n return wrapped === undefined ? undefined : { ...wrapped, currentVersion: versionNum }\n}\n\n/**\n * Validate the ChatCode CLI package and collapse results into one decision.\n * A disabled version wins over an available upgrade: an unusable install must\n * be replaced before any forward update matters.\n */\nexport async function checkVersions(config: Config, options: VersionCheckOptions = {}): Promise<VersionCheckDecision | undefined> {\n const outcomes = (await Promise.all(CHATCODE_CLI_PACKAGES.map(async (name): Promise<VersionCheckPackage & { action: VersionCheckAction } | undefined> => {\n const outcome = await validatePackage(config, name, options)\n return outcome === undefined ? undefined : { name, action: outcome.action, currentVersion: outcome.currentVersion, targetVersion: outcome.version }\n }))).filter((entry): entry is VersionCheckPackage & { action: VersionCheckAction } => entry !== undefined)\n\n const rollbacks = outcomes.filter(entry => entry.action === 'rollback')\n if (rollbacks.length > 0) return { action: 'rollback', packages: rollbacks.map(({ name, currentVersion, targetVersion }) => ({ name, currentVersion, targetVersion })) }\n const upgrades = outcomes.filter(entry => entry.action === 'upgrade')\n if (upgrades.length > 0) return { action: 'upgrade', packages: upgrades.map(({ name, currentVersion, targetVersion }) => ({ name, currentVersion, targetVersion })) }\n return undefined\n}\n\n/** Install the server-selected versions for one decision. */\nexport async function runDecisionInstall(decision: VersionCheckDecision): Promise<{ ok: boolean; message: string }> {\n const specs = decision.packages.map(pkg => `${pkg.name}@${pkg.targetVersion}`)\n const result = await runNpmInstall(specs)\n if (result.code !== 0) {\n const detail = result.output.trim() || '未知错误'\n return { ok: false, message: `安装失败:${detail}\\n请手动执行:npm install -g ${specs.join(' ')}` }\n }\n const summary = decision.packages.map(pkg => `${pkg.name} ${pkg.targetVersion}`).join('、')\n const verb = decision.action === 'upgrade' ? '升级' : '更换'\n return { ok: true, message: `已${verb}到 ${summary},请重启 ChatCode CLI 以生效` }\n}\n\nexport interface VersionPrompt {\n title: string\n message: string\n performLabel: string\n cancelLabel: string\n}\n\n/** Localize one decision into the terminal dialog copy. */\nexport function decisionPrompt(decision: VersionCheckDecision): VersionPrompt {\n const targets = decision.packages.map(pkg => `${pkg.name} ${pkg.targetVersion}`).join('、')\n if (decision.action === 'upgrade') {\n return {\n title: '版本升级提醒',\n message: `新版本已发布(${targets}),请升级后再使用。`,\n performLabel: '升级',\n cancelLabel: '不升级(退出程序)',\n }\n }\n const current = decision.packages.map(pkg => `${pkg.name} ${pkg.currentVersion}`).join('、')\n return {\n title: '版本禁用提醒',\n message: `当前版本已禁用(${current}),请更换到(${targets})后再使用。`,\n performLabel: '更换',\n cancelLabel: '不更换(退出程序)',\n }\n}\n\n/**\n * Show a two-option keyboard dialog: up/down arrows move the cursor, Enter\n * chooses. Selecting the first option returns `perform`; the second option or\n * Ctrl+C returns `exit`. Without a TTY there is no menu to read, so it fails\n * open to `exit` and the caller leaves startup untouched.\n */\nexport function promptVersionAction(prompt: VersionPrompt): Promise<'perform' | 'exit'> {\n if (stdin.isTTY !== true) return Promise.resolve('exit')\n\n const labels = [prompt.performLabel, prompt.cancelLabel]\n return new Promise(resolve => {\n let selected = 0\n let drawn = 0\n\n const computeDrawn = (lines: string[]): number => {\n const cols = stdout.columns || 80\n return lines.reduce((total, ln) => {\n if (ln === '') return total + 1\n const width = [...ln].reduce((sum, ch) => sum + (/^[\\u1100-\\u11ff\\u2e80-\\ua4cf\\uf900-\\ufaff\\uff00-\\uffef]/u.test(ch) ? 2 : 1), 0)\n return total + Math.max(1, Math.ceil(width / cols))\n }, 0)\n }\n\n const render = (): void => {\n const lines = [prompt.title, prompt.message, '', ...labels.map((label, index) => index === selected ? `> ${label}` : ` ${label}`)]\n if (drawn > 0) {\n // Move to the real first physical row of the previously drawn block and\n // wipe everything below. Line count must account for terminal wrapping\n // (long dialog text wraps into several physical rows); using the logical\n // line count leaves the top row uncleared, so every redraw stacks a new\n // copy of the title.\n stdout.write(`\\x1b[${drawn}A\\x1b[0J`)\n }\n stdout.write(`${lines.join('\\n')}\\n`)\n drawn = computeDrawn(lines)\n }\n\n const finish = (value: 'perform' | 'exit'): void => {\n if (stdin.isTTY === true) stdin.setRawMode(false)\n stdin.pause()\n stdin.off('keypress', onKeypress)\n stdout.write('\\n')\n resolve(value)\n }\n\n const onKeypress = (_chunk: string, key: Key): void => {\n if (key.ctrl && key.name === 'c') { finish('exit'); return }\n if (key.name === 'up') { selected = selected === 0 ? labels.length - 1 : selected - 1; render(); return }\n if (key.name === 'down') { selected = selected === labels.length - 1 ? 0 : selected + 1; render(); return }\n if (key.name === 'return') finish(selected === 0 ? 'perform' : 'exit')\n }\n\n emitKeypressEvents(stdin)\n stdin.setRawMode(true)\n stdin.resume()\n stdin.on('keypress', onKeypress)\n render()\n })\n}\n","/**\n * The three adapters between pi-ai's auth model and the harness credential\n * plane. Every pi-ai-specific concept stays on this side of them: the harness\n * seams they consume — `ctx.credentials` records and `ctx.authorization` flows —\n * name nothing from this library, so another adapter family can arrive with a\n * different auth model and share the same two seams.\n *\n * @module dsh-llm-pi-ai/auth\n */\n\nimport { homedir } from 'node:os'\nimport { access } from 'node:fs/promises'\nimport { resolve as resolvePath } from 'node:path'\nimport type { AuthContext, Credential, CredentialInfo, CredentialStore } from '@earendil-works/pi-ai'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { defaultProviderAuthContext, InMemoryCredentialStore } from '@earendil-works/pi-ai'\nimport type { PiAiAuthInjection } from './adapter.ts'\nimport {\n credentialKey, credentialKeyId, credentialKeyScope, credentialRef, isCredentialKeySegment, isCredentialRefName,\n} from '@deepseek-ai/dsh-credentials'\nimport type { CredentialKey, CredentialProvider, CredentialRecord } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\nimport { LlmError } from '@deepseek-ai/dsh-llm'\n\n/**\n * The record scope every credential this adapter family stores is written\n * under. It is the plugin's registered name, which is what tells a later\n * reader — a configuration UI, or a second adapter family serving the same\n * provider name — that this plugin owns the format inside the record.\n */\nexport const RECORD_SCOPE = 'llm-pi-ai'\n\n/**\n * The record address for one pi-ai provider id.\n * @param providerId - pi-ai's own provider id, which is also the harness route key.\n * @returns the scoped credential key this adapter family reads and writes.\n */\nexport function recordKeyFor(providerId: string): CredentialKey {\n return credentialKey(RECORD_SCOPE, providerId)\n}\n\n/**\n * The JSON image of one grant payload: plain objects lose their\n * explicitly-undefined members and array entries JSON cannot hold become\n * null, exactly as `JSON.stringify` would render them. pi-ai credentials\n * idiomatically carry optional members as explicit `undefined` (a github.com\n * Copilot grant holds `enterpriseUrl: undefined`), which the credential\n * store's strict validator refuses as unrepresentable. Everything else —\n * non-finite numbers and foreign prototypes included — passes through\n * untouched, so a genuinely unstorable value still fails loud at the store.\n * @param value - the value to render.\n * @returns the value's JSON image.\n */\nfunction jsonImage(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(entry => entry === undefined ? null : jsonImage(entry))\n if (typeof value === 'object' && value !== null && Object.getPrototypeOf(value) === Object.prototype) {\n const image: Record<string, unknown> = {}\n for (const [key, member] of Object.entries(value)) {\n if (member !== undefined) image[key] = jsonImage(member)\n }\n return image\n }\n return value\n}\n\n/**\n * Translate a stored record into the credential pi-ai expects.\n *\n * An `api-key` record is structural on both sides, so it is rebuilt field by\n * field. A `grant` payload is pi-ai's own OAuth credential, stored verbatim:\n * the seam treats it as opaque JSON precisely so a library that owns a token\n * format keeps owning it, refresh fields and all.\n * @param record - the stored record, or undefined when nothing is stored.\n * @returns the pi-ai credential, or undefined for an absent record.\n */\nfunction toPiCredential(record: CredentialRecord | undefined): Credential | undefined {\n if (record === undefined) return undefined\n if (record.kind === 'api-key') {\n return {\n type: 'api_key',\n ...record.key === undefined ? {} : { key: record.key },\n ...record.env === undefined ? {} : { env: { ...record.env } },\n }\n }\n return record.payload as Credential\n}\n\n/**\n * Translate a pi-ai credential into the record to store.\n * @param credential - what a login or refresh produced.\n * @returns the record to commit, in the union the credential seam stores.\n */\nfunction toRecord(credential: Credential): CredentialRecord {\n if (credential.type === 'api_key') {\n return {\n kind: 'api-key',\n ...credential.key === undefined ? {} : { key: credential.key },\n ...credential.env === undefined ? {} : { env: { ...credential.env } },\n }\n }\n return { kind: 'grant', payload: jsonImage(credential) }\n}\n\n/**\n * The credential service, or the failure that names what is missing. Reads\n * answer \"nothing stored\" without a service, because a composition with no\n * credential plane genuinely holds no credential; writes refuse, because a\n * login whose grant silently evaporated would report success and then fail\n * every request.\n * @param ctx - the plugin context.\n * @returns the live service.\n * @throws {LlmError} code `NO_CREDENTIAL_STORE` when none is mounted.\n */\nfunction writableStore(ctx: Context): CredentialProvider {\n const credentials = ctx.get('credentials')\n if (credentials === undefined) {\n throw new LlmError(\n 'llm-pi-ai: this composition mounts no credentials service, so there is nowhere to store the'\n + ' credential a sign-in produces; mount one (dsh-credentials-local) to sign in',\n 'NO_CREDENTIAL_STORE',\n )\n }\n return credentials\n}\n\n/**\n * A pi-ai `CredentialStore` over the harness credential records.\n *\n * pi-ai runs OAuth refresh *inside* `modify()`, so this store's exclusion has\n * to cover a network round trip rather than a file rename — which is why the\n * record write path takes a wait limit of its own rather than the short one a\n * local write would need.\n *\n * pi-ai asks this store about every provider in the collection, hand-declared\n * routes included, and a route key is an arbitrary settings dict key while a\n * record id is not. An id outside the record grammar can never have stored a\n * record, so reads answer \"nothing stored\" and a delete has nothing to remove;\n * only `modify` refuses it, because a write that cannot land must not report\n * that it did.\n * @param ctx - the plugin context carrying the optional `ctx.credentials`.\n * @returns the store to hand `createModels()`.\n */\nexport function credentialStoreFrom(ctx: Context): CredentialStore {\n return {\n async read(providerId) {\n const credentials = ctx.get('credentials')\n if (credentials === undefined) return undefined\n if (!isCredentialKeySegment(providerId)) return undefined\n return toPiCredential(await credentials.readRecord(recordKeyFor(providerId)))\n },\n async list(): Promise<readonly CredentialInfo[]> {\n const stored = await ctx.get('credentials')?.listRecords() ?? []\n const mine: CredentialInfo[] = []\n for (const entry of stored) {\n // Records another plugin owns are not this collection's to report:\n // their payloads are written in a format pi-ai never agreed to.\n if (credentialKeyScope(entry.key) !== RECORD_SCOPE) continue\n mine.push({\n providerId: credentialKeyId(entry.key),\n type: entry.kind === 'api-key' ? 'api_key' : 'oauth',\n })\n }\n return mine\n },\n async modify(providerId, mutate) {\n if (!isCredentialKeySegment(providerId)) {\n throw new LlmError(\n `llm-pi-ai: provider id \"${providerId}\" cannot address a stored credential record (a record id is a`\n + ' lowercase hyphenated identifier); authenticate this route through apiKeyEnv instead of a stored'\n + ' credential',\n 'UNSTORABLE_PROVIDER_ID',\n )\n }\n const stored = await writableStore(ctx).modifyRecord(recordKeyFor(providerId), async (current) => {\n const next = await mutate(toPiCredential(current))\n return next === undefined ? undefined : toRecord(next)\n })\n return toPiCredential(stored)\n },\n // `async` so a missing service reaches the caller as a rejection: pi-ai's\n // store contract is promise-returning, and a synchronous throw would\n // escape the `ModelsError` wrapper every other storage failure gets.\n async delete(providerId) {\n if (!isCredentialKeySegment(providerId)) return\n await writableStore(ctx).deleteRecord(recordKeyFor(providerId))\n },\n }\n}\n\n/**\n * A pi-ai `AuthContext` over the harness credential plane and the host\n * filesystem.\n *\n * `env()` answers from the credential seam first, so a value a deployment\n * stored through the harness is found by a provider's own ambient discovery —\n * without this, that discovery reads only the process environment and a stored\n * `AWS_ACCESS_KEY_ID` is invisible to it. `fileExists()` answers about the host\n * process's own filesystem rather than the workspace `ctx.fs` seam, because the\n * paths it is asked about (`~/.aws/credentials`, application-default\n * credentials) are facts about where this process runs, not about the project\n * under edit.\n * @param ctx - the plugin context carrying the optional `ctx.credentials`.\n * @returns the auth context to hand `createModels()`.\n */\nexport function authContextFrom(ctx: Context): AuthContext {\n return {\n async env(name) {\n // pi-ai asks about arbitrary provider-declared names; one that is not a\n // POSIX identifier can never have been stored as a reference, and asking\n // the seam would throw instead of answering \"not set\".\n if (isCredentialRefName(name)) {\n const credentials = ctx.get('credentials')\n const hit = await credentials?.resolve(credentialRef(name))\n if (hit !== undefined) return hit.value\n }\n return launchEnvironmentOf(ctx).get(name)?.value\n },\n async fileExists(path) {\n const expanded = path.startsWith('~/') || path === '~'\n ? resolvePath(homedir(), path.slice(1).replace(/^\\//, ''))\n : path\n try {\n await access(expanded)\n return true\n } catch {\n // Absent, unreadable, or a broken symlink — every one of which means\n // this ambient credential source cannot be used, which is the only\n // distinction the caller makes.\n return false\n }\n },\n }\n}\n\n/**\n * Create private auth storage for adapters whose explicit source owns every credential.\n * @returns an empty in-memory store and provider auth context, independent of ChatCode CLI login records.\n */\nexport function isolatedPiAiAuth(): PiAiAuthInjection {\n return { credentials: new InMemoryCredentialStore(), authContext: defaultProviderAuthContext() }\n}\n","/**\n * Durable pi-ai replay metadata and assistant-history reconstruction.\n *\n * ChatCode CLI content remains the durable source for text and tool calls. This\n * module stores only the provider-native metadata needed to reconstruct a\n * pi-ai assistant message on a later request.\n *\n * @module dsh-llm-pi-ai/replay\n */\n\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { Message, ModelMessageSource, ReplayEnvelope } from '@deepseek-ai/dsh-llm'\nimport type { Api, AssistantMessage, Usage as PiUsage } from '@earendil-works/pi-ai'\n\n/** Per-block half of the pi-ai replay envelope, one entry per content block. */\nexport type PiAiReplayBlock =\n | { type: 'text'; textSignature?: string }\n | { type: 'reasoning'; thinkingSignature?: string; redacted?: boolean }\n | { type: 'tool-call'; thoughtSignature?: string }\n\n/** Versioned response-level half of the pi-ai replay envelope. */\nexport interface PiAiReplayResponse {\n kind: 'pi-ai'\n version: 2\n api: Api\n provider: string\n model: string\n responseModel?: string\n responseId?: string\n stopReason: AssistantMessage['stopReason']\n}\n\n/** The validated halves of one pi-ai replay envelope. */\ninterface PiAiReplayState {\n response: PiAiReplayResponse\n blocks: PiAiReplayBlock[]\n}\n\n/** Parse tool-call argument JSON; tolerate model malformations with {}. */\nfunction parseArguments(raw: string): Record<string, unknown> {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n // fall through\n }\n return {}\n}\n\n/** Construct the zero usage value required by historical pi-ai messages. */\nfunction emptyPiUsage(): PiUsage {\n return {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n }\n}\n\n/**\n * Project a successful pi-ai response into the minimal durable replay state.\n * The per-block half is index-aligned with the streamed blocks (pi-ai content\n * order), so `BlockAssembler` prunes an entry with its block whenever assembly\n * removes one.\n * @param message - completed native pi-ai assistant response.\n * @returns the versioned lossless-JSON replay projection.\n */\nexport function toPiReplayState(message: AssistantMessage): ReplayEnvelope {\n const response: PiAiReplayResponse = {\n kind: 'pi-ai',\n version: 2,\n api: message.api,\n provider: message.provider,\n model: message.model,\n ...message.responseModel === undefined ? {} : { responseModel: message.responseModel },\n ...message.responseId === undefined ? {} : { responseId: message.responseId },\n stopReason: message.stopReason,\n }\n return {\n response,\n blocks: message.content.map((block): PiAiReplayBlock => {\n switch (block.type) {\n case 'text': return {\n type: 'text',\n ...block.textSignature === undefined ? {} : { textSignature: block.textSignature },\n }\n case 'thinking': return {\n type: 'reasoning',\n ...block.thinkingSignature === undefined ? {} : { thinkingSignature: block.thinkingSignature },\n ...block.redacted === undefined ? {} : { redacted: block.redacted },\n }\n case 'toolCall': return {\n type: 'tool-call',\n ...block.thoughtSignature === undefined ? {} : { thoughtSignature: block.thoughtSignature },\n }\n }\n }),\n }\n}\n\nfunction invalidReplay(message: string): never {\n throw new LlmError(`invalid pi-ai replay state: ${message}`, 'INVALID_REPLAY_STATE')\n}\n\n/** Validate the durable adapter-private envelope before it reaches pi-ai. */\nfunction readReplayState(value: unknown): PiAiReplayState {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return invalidReplay('expected a replay envelope')\n const envelope = value as Record<string, unknown>\n const rawResponse = envelope['response']\n if (typeof rawResponse !== 'object' || rawResponse === null || Array.isArray(rawResponse)) return invalidReplay('expected a response object')\n const response = rawResponse as Record<string, unknown>\n if (response['kind'] !== 'pi-ai') return invalidReplay('unknown state kind')\n if (response['version'] !== 2) return invalidReplay(`unsupported version ${String(response['version'])}`)\n for (const key of ['api', 'provider', 'model'] as const) {\n if (typeof response[key] !== 'string' || response[key].length === 0) return invalidReplay(`${key} must be a non-empty string`)\n }\n if (!['stop', 'length', 'toolUse', 'error', 'aborted'].includes(String(response['stopReason']))) {\n return invalidReplay('unknown stopReason')\n }\n if (response['responseModel'] !== undefined && typeof response['responseModel'] !== 'string') return invalidReplay('responseModel must be a string')\n if (response['responseId'] !== undefined && typeof response['responseId'] !== 'string') return invalidReplay('responseId must be a string')\n const blocks = envelope['blocks']\n if (!Array.isArray(blocks)) return invalidReplay('blocks must be an array')\n for (const [index, value] of blocks.entries()) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return invalidReplay(`block ${index} must be an object`)\n const block = value as Record<string, unknown>\n if (!['text', 'reasoning', 'tool-call'].includes(String(block['type']))) return invalidReplay(`block ${index} has an unknown type`)\n for (const signature of ['textSignature', 'thinkingSignature', 'thoughtSignature'] as const) {\n if (block[signature] !== undefined && typeof block[signature] !== 'string') return invalidReplay(`block ${index} ${signature} must be a string`)\n }\n if (block['redacted'] !== undefined && typeof block['redacted'] !== 'boolean') return invalidReplay(`block ${index} redacted must be boolean`)\n }\n return {\n response: response as unknown as PiAiReplayResponse,\n blocks: blocks as PiAiReplayBlock[],\n }\n}\n\n/** Convert provider-neutral blocks without trusting them as same-model replay. */\nfunction foreignAssistant(message: Message): AssistantMessage {\n const source = message.source.kind === 'model' ? message.source : undefined\n const content: AssistantMessage['content'] = []\n for (const block of message.content) {\n switch (block.type) {\n case 'text': content.push({ type: 'text', text: block.text }); break\n case 'reasoning': content.push({ type: 'thinking', thinking: block.text }); break\n case 'tool-call': content.push({\n type: 'toolCall',\n id: block.id,\n name: block.name,\n arguments: parseArguments(block.arguments),\n }); break\n case 'image':\n throw new LlmError('pi-ai chat history cannot represent structured assistant image output', 'UNSUPPORTED_CONTENT')\n default:\n // plugin-added block types are not representable in pi-ai.\n break\n }\n }\n return {\n role: 'assistant',\n content,\n // Deliberately never equals a catalog API: absent replay state is foreign\n // even if source names the same provider/model as this request.\n api: 'dsh-foreign',\n provider: source?.provider ?? 'dsh-foreign',\n model: source?.model ?? 'dsh-foreign',\n usage: emptyPiUsage(),\n stopReason: content.some(piece => piece.type === 'toolCall') ? 'toolUse' : 'stop',\n timestamp: 0,\n }\n}\n\n/** Recombine durable ChatCode CLI content with validated pi-ai replay metadata. */\nfunction replayedAssistant(message: Message, source: ModelMessageSource, rawState: unknown): AssistantMessage {\n const state = readReplayState(rawState)\n if (state.response.provider !== source.provider) return invalidReplay('provider does not match assistant source')\n if (state.response.model !== source.model) return invalidReplay('model does not match assistant source')\n if (state.blocks.length !== message.content.length) return invalidReplay('block count does not match assistant content')\n const content: AssistantMessage['content'] = message.content.map((block, index) => {\n const replay = state.blocks[index]\n if (replay === undefined || replay.type !== block.type) return invalidReplay(`block ${index} does not match assistant content`)\n switch (block.type) {\n case 'text': return {\n type: 'text',\n text: block.text,\n ...replay.type === 'text' && replay.textSignature !== undefined ? { textSignature: replay.textSignature } : {},\n }\n case 'reasoning': return {\n type: 'thinking',\n thinking: block.text,\n ...replay.type === 'reasoning' && replay.thinkingSignature !== undefined ? { thinkingSignature: replay.thinkingSignature } : {},\n ...replay.type === 'reasoning' && replay.redacted !== undefined ? { redacted: replay.redacted } : {},\n }\n case 'tool-call': return {\n type: 'toolCall',\n id: block.id,\n name: block.name,\n arguments: parseArguments(block.arguments),\n ...replay.type === 'tool-call' && replay.thoughtSignature !== undefined ? { thoughtSignature: replay.thoughtSignature } : {},\n }\n /* v8 ignore next -- readReplayState rejects unknown replay tags, so an equal plugin-added ChatCode CLI tag cannot reach this switch */\n default: return invalidReplay(`block ${index} has an unsupported ChatCode CLI type`)\n }\n })\n return {\n role: 'assistant',\n content,\n api: state.response.api,\n provider: state.response.provider,\n model: state.response.model,\n ...state.response.responseModel === undefined ? {} : { responseModel: state.response.responseModel },\n ...state.response.responseId === undefined ? {} : { responseId: state.response.responseId },\n usage: emptyPiUsage(),\n stopReason: state.response.stopReason,\n timestamp: 0,\n }\n}\n\n/**\n * Convert one durable ChatCode CLI assistant message into pi-ai history.\n *\n * Durable content is the authoritative record; replay metadata only restores\n * native fidelity (ids, signatures). A replay state this build cannot use —\n * another adapter's kind, another version, a malformed value, or metadata that\n * no longer matches the content — therefore degrades the one message to\n * provider-neutral history instead of failing the request.\n * @param message - assistant content with required source and optional adapter-owned replay metadata.\n * @param onDegrade - called with the diagnostic reason when an unusable replay\n * state falls back to provider-neutral conversion.\n * @returns a native pi-ai assistant message reconstructed from durable content.\n */\nexport function toPiAssistant(message: Message, onDegrade?: (reason: string) => void): AssistantMessage {\n const source = message.source\n if (source.kind !== 'model' || source.replayState === undefined) return foreignAssistant(message)\n try {\n return replayedAssistant(message, source, source.replayState)\n } catch (error: unknown) {\n /* v8 ignore next -- replayedAssistant throws only INVALID_REPLAY_STATE LlmErrors; the\n guard keeps a future non-replay failure loud instead of silently degrading it */\n if (!(error instanceof LlmError) || error.code !== 'INVALID_REPLAY_STATE') throw error\n onDegrade?.(error.message)\n return foreignAssistant(message)\n }\n}\n","/**\n * Materialization of one provider route's model catalog. The installed pi-ai\n * catalog supplies defaults keyed by model id, and a profile's own model\n * entries override them field by field, so a route naming a catalog provider\n * stays configuration-free while a route pi-ai has never heard of is fully\n * describable from `settings.yaml`.\n *\n * Every pi-ai `Model` field the harness cannot default is required here rather\n * than at request time: an unserviceable route fails while its configuration is\n * being resolved, which is the earliest point that can name the offending key.\n *\n * @module dsh-llm-pi-ai/catalog\n */\n\nimport { builtinProviders, getBuiltinModels, getBuiltinProviders } from '@earendil-works/pi-ai/providers/all'\nimport type { BuiltinProvider } from '@earendil-works/pi-ai/providers/all'\nimport type {\n AnthropicMessagesCompat,\n Api,\n BedrockCompat,\n ChatTemplateKwargValue,\n KnownApi,\n Model,\n ModelCost,\n ModelThinkingLevel,\n OpenAICompletionsCompat,\n OpenAIResponsesCompat,\n Provider,\n ThinkingLevelMap,\n} from '@earendil-works/pi-ai'\n\n/**\n * Pricing for a model the installed catalog does not describe. The harness\n * never reads pi-ai's cost metadata — `replay.ts` zeroes it and no consumer\n * reports spend — so this is the absence of a fact, not a configurable rate.\n */\nconst NO_COST: ModelCost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }\n\n/** One request modality a pi-ai model may accept. */\nexport type PiAiModality = Model<Api>['input'][number]\n\n/**\n * Every pi-ai request modality. The `Record` key type is a drift gate: a pi-ai\n * upgrade that adds or removes a modality fails compilation here naming the\n * drifted key, instead of silently narrowing what a profile may declare.\n */\nconst MODALITY_GATE: Record<PiAiModality, true> = {\n text: true,\n image: true,\n}\n\n/** Every request modality a profile may declare. */\nexport const MODALITIES = Object.keys(MODALITY_GATE) as readonly PiAiModality[]\n\n/**\n * One entry's modality list, or `undefined` when it states no answer. Absent\n * and empty mean the same thing — `[]` describes a model that accepts nothing\n * and could serve no request — which is what makes an entry naming a catalog\n * model without declaring modalities keep the catalog's, since the config\n * schema materializes `[]` for an absent array.\n * @param configured - the list a `models` or `modelOverrides` entry supplied.\n * @returns the declared modalities, or `undefined` to ask the next level.\n */\nfunction declaredInput(configured: readonly PiAiModality[] | undefined): Model<Api>['input'] | undefined {\n return configured === undefined || configured.length === 0 ? undefined : [...configured]\n}\n\n/**\n * Every pi-ai thinking level, in pi-ai's canonical escalation order. The\n * `Record` key type is a drift gate: a pi-ai upgrade that adds or removes a\n * level fails compilation here naming the drifted key, instead of silently\n * narrowing what a profile may declare.\n */\nconst THINKING_LEVEL_GATE: Record<ModelThinkingLevel, true> = {\n off: true,\n minimal: true,\n low: true,\n medium: true,\n high: true,\n xhigh: true,\n max: true,\n}\n\n/** Every pi-ai thinking level a profile may declare, in escalation order. */\nexport const THINKING_LEVELS = Object.keys(THINKING_LEVEL_GATE) as readonly ModelThinkingLevel[]\n\n/** One reasoning-dispatch wire format a profile may name. */\nexport type PiAiThinkingFormat = NonNullable<OpenAICompletionsCompat['thinkingFormat']>\n\n/**\n * The nameable reasoning-dispatch formats, most-reached first. The `Record`\n * key type is a drift gate: an upstream format addition fails compilation\n * here until it is named, so the offer never silently lags the upstream set.\n * The two `chat-template` variants are nameable because\n * {@link PiAiCompatProfile.chatTemplateKwargs} carries their kwargs;\n * `baseten` is nameable because {@link PiAiCompatProfile.chatTemplateArgs}\n * carries its arguments.\n */\nconst THINKING_FORMAT_GATE: Record<PiAiThinkingFormat, true> = {\n 'openai': true,\n 'deepseek': true,\n 'openrouter': true,\n 'together': true,\n 'baseten': true,\n 'zai': true,\n 'qwen': true,\n 'chat-template': true,\n 'qwen-chat-template': true,\n 'string-thinking': true,\n 'ant-ling': true,\n}\n\n/** Reasoning-dispatch wire formats a profile may name, most-reached first. */\nexport const SUPPORTED_THINKING_FORMATS = Object.keys(THINKING_FORMAT_GATE) as readonly PiAiThinkingFormat[]\n\n/** The output-cap field spellings pi-ai accepts. */\nexport type PiAiMaxTokensField = NonNullable<OpenAICompletionsCompat['maxTokensField']>\n\n/** Drift gate over {@link PiAiMaxTokensField}; an upstream spelling added here fails compilation until named. */\nconst MAX_TOKENS_FIELD_GATE: Record<PiAiMaxTokensField, true> = {\n max_completion_tokens: true,\n max_tokens: true,\n}\n\n/** The output-cap field spellings a profile may name. */\nexport const MAX_TOKENS_FIELDS = Object.keys(MAX_TOKENS_FIELD_GATE) as readonly PiAiMaxTokensField[]\n\n/** The prompt-cache marker conventions pi-ai accepts. */\nexport type PiAiCacheControlFormat = NonNullable<OpenAICompletionsCompat['cacheControlFormat']>\n\n/** Drift gate over {@link PiAiCacheControlFormat}; a new upstream convention fails compilation until named. */\nconst CACHE_CONTROL_FORMAT_GATE: Record<PiAiCacheControlFormat, true> = {\n anthropic: true,\n}\n\n/** The prompt-cache marker conventions a profile may name. */\nexport const CACHE_CONTROL_FORMATS = Object.keys(CACHE_CONTROL_FORMAT_GATE) as readonly PiAiCacheControlFormat[]\n\n/** The request-state placeholders a `chat_template_kwargs` value may name. */\nexport type PiAiChatTemplateVar = Extract<ChatTemplateKwargValue, { $var: string }>['$var']\n\n/** Drift gate over {@link PiAiChatTemplateVar}; a new upstream placeholder fails compilation until named. */\nconst CHAT_TEMPLATE_VAR_GATE: Record<PiAiChatTemplateVar, true> = {\n 'thinking.enabled': true,\n 'thinking.effort': true,\n}\n\n/** The request-state placeholders a profile may name. */\nexport const CHAT_TEMPLATE_VARS = Object.keys(CHAT_TEMPLATE_VAR_GATE) as readonly PiAiChatTemplateVar[]\n\nlet providerIndex: Map<string, Provider> | undefined\n\n/**\n * Installed catalog providers by id, constructed once. Each entry owns the API\n * implementations for its own models, which is why a catalog route reuses this\n * provider instead of being rebuilt from parts.\n * @returns the catalog provider index.\n */\nfunction catalogProviders(): Map<string, Provider> {\n providerIndex ??= new Map(builtinProviders().map(provider => [provider.id, provider]))\n return providerIndex\n}\n\n/**\n * The installed catalog provider for one route, when pi-ai ships one.\n * @param provider - provider route key.\n * @returns the catalog provider, or `undefined` for a route pi-ai does not ship.\n */\nexport function catalogProvider(provider: string): Provider | undefined {\n return catalogProviders().get(provider)\n}\n\n/**\n * Every provider route the installed pi-ai catalog ships.\n * @returns the catalog provider ids.\n */\nexport function catalogProviderIds(): readonly string[] {\n return getBuiltinProviders()\n}\n\n/**\n * The installed catalog models for one route, indexed by model id.\n * @param provider - provider route key.\n * @returns catalog models by id; empty for a route pi-ai does not ship.\n */\nexport function catalogModels(provider: string): Map<string, Model<Api>> {\n if (!catalogProviders().has(provider)) return new Map()\n const models = getBuiltinModels(provider as BuiltinProvider) as Model<Api>[]\n return new Map(models.map(model => [model.id, model]))\n}\n\n/**\n * Selectable reasoning efforts for one model: each key is a level the model\n * offers (and selectors show), and its value is the wire spelling dispatch\n * sends for it. `off` alone may leave its value empty — \"supported, send\n * nothing\" — because for most providers not thinking is the parameter's\n * absence; every other declared level must name a wire value. A level absent\n * from the dict is not offered.\n */\nexport type PiAiReasoningEfforts = Partial<Record<ModelThinkingLevel, string | null>>\n\n/**\n * Whether one pi-ai compat field is configurable on a profile.\n *\n * `withhold` is the disposition for a field pi-ai's installed catalog already\n * sets for a named vendor. Reaching for one of those on a hand-declared route\n * means configuring a provider that should have been named as a catalog route\n * instead, where the installed entry carries the right value already.\n */\ntype CompatDisposition = 'offer' | 'withhold'\n\n/**\n * Disposition of every `OpenAICompletionsCompat` field. The `Record` key type\n * is a drift gate: a pi-ai upgrade that adds a field fails compilation here\n * until it is classified, so the offer never silently lags the upstream set.\n */\nconst COMPLETIONS_COMPAT_GATE = {\n supportsStore: 'offer',\n supportsDeveloperRole: 'offer',\n supportsReasoningEffort: 'offer',\n supportsUsageInStreaming: 'offer',\n supportsFinishReason: 'offer',\n maxTokensField: 'offer',\n requiresToolResultName: 'offer',\n requiresAssistantAfterToolResult: 'offer',\n requiresThinkingAsText: 'offer',\n requiresReasoningContentOnAssistantMessages: 'offer',\n thinkingFormat: 'offer',\n chatTemplateKwargs: 'offer',\n chatTemplateArgs: 'offer',\n supportsThinkingTokenBudget: 'offer',\n supportsStrictMode: 'offer',\n cacheControlFormat: 'offer',\n supportsLongCacheRetention: 'offer',\n openRouterRouting: 'withhold',\n vercelGatewayRouting: 'withhold',\n zaiToolStream: 'withhold',\n supportsOpenAIGrammarTools: 'withhold',\n sendSessionAffinityHeaders: 'withhold',\n deferredToolsMode: 'withhold',\n sessionAffinityFormat: 'withhold',\n} as const satisfies Record<keyof OpenAICompletionsCompat, CompatDisposition>\n\n/** Disposition of every `OpenAIResponsesCompat` field; a drift gate like the one above. */\nconst RESPONSES_COMPAT_GATE = {\n supportsDeveloperRole: 'offer',\n supportsStrictMode: 'offer',\n supportsLongCacheRetention: 'offer',\n sessionAffinityFormat: 'withhold',\n supportsOpenAIGrammarTools: 'withhold',\n supportsAdditionalTools: 'withhold',\n supportsToolSearch: 'withhold',\n supportsExplicitPromptCacheMode: 'withhold',\n} as const satisfies Record<keyof OpenAIResponsesCompat, CompatDisposition>\n\n/** Disposition of every `AnthropicMessagesCompat` field; a drift gate like the one above. */\nconst ANTHROPIC_COMPAT_GATE = {\n supportsEagerToolInputStreaming: 'offer',\n supportsLongCacheRetention: 'offer',\n supportsCacheControlOnTools: 'offer',\n supportsTemperature: 'offer',\n forceAdaptiveThinking: 'offer',\n allowEmptySignature: 'offer',\n supportsStrictTools: 'offer',\n sendSessionAffinityHeaders: 'withhold',\n supportsToolReferences: 'withhold',\n} as const satisfies Record<keyof AnthropicMessagesCompat, CompatDisposition>\n\n/** Disposition of every `BedrockCompat` field; a drift gate like the one above. */\nconst BEDROCK_COMPAT_GATE = {\n supportsStrictMode: 'offer',\n} as const satisfies Record<keyof BedrockCompat, CompatDisposition>\n\n/**\n * Every wire protocol pi-ai gives a compat type. Derived from `Model.compat`'s\n * own conditional rather than listed by hand, so a pi-ai release that gives a\n * further protocol a compat type fails the {@link COMPAT_GATES} entry list\n * until someone classifies its fields. A protocol pi-ai gives no compat type\n * resolves away here and takes no configured compat at all.\n */\ntype ApiWithCompat = { [K in KnownApi]: NonNullable<Model<K>['compat']> extends never ? never : K }[KnownApi]\n\n/**\n * The compat gate of every wire protocol a profile may configure.\n *\n * Keyed by protocol, but grouped by pi-ai's compat *type*: the three Responses\n * protocols share `OpenAIResponsesCompat`, so a switch settable on one is\n * settable on all three. Keying by protocol alone would refuse\n * `azure-openai-responses` and `openai-codex-responses` the fields their own\n * models declare.\n */\nconst COMPAT_GATES: Readonly<Record<ApiWithCompat, Readonly<Record<string, CompatDisposition>>>> = {\n 'openai-completions': COMPLETIONS_COMPAT_GATE,\n 'openai-responses': RESPONSES_COMPAT_GATE,\n 'azure-openai-responses': RESPONSES_COMPAT_GATE,\n 'openai-codex-responses': RESPONSES_COMPAT_GATE,\n 'anthropic-messages': ANTHROPIC_COMPAT_GATE,\n 'bedrock-converse-stream': BEDROCK_COMPAT_GATE,\n}\n\n/**\n * The compat gate of one resolved protocol. A `string` lookup rather than a\n * keyed read: a route's `api` is configuration, so it may name a protocol\n * pi-ai gives no compat type — or none at all.\n * @param api - resolved wire protocol.\n * @returns that protocol's field gate, or `undefined` when it takes no compat.\n */\nfunction compatGate(api: string): Readonly<Record<string, CompatDisposition>> | undefined {\n return (COMPAT_GATES as Readonly<Record<string, Readonly<Record<string, CompatDisposition>>>>)[api]\n}\n\n/** The field names one gate offers. */\ntype OfferedIn<G> = { [K in keyof G]: G[K] extends 'offer' ? K : never }[keyof G]\n\n/** Every compat field name a profile may set, on whichever protocol takes it. */\ntype OfferedCompatField =\n | OfferedIn<typeof COMPLETIONS_COMPAT_GATE>\n | OfferedIn<typeof RESPONSES_COMPAT_GATE>\n | OfferedIn<typeof ANTHROPIC_COMPAT_GATE>\n | OfferedIn<typeof BEDROCK_COMPAT_GATE>\n\n/**\n * pi-ai wire-compatibility switches, set on the route (its models' default) or\n * per model (winning over the route, field by field).\n *\n * pi-ai decides each of these from the provider id and baseURL when no layer\n * sets it, and a private gateway's URL says nothing: for an endpoint it does\n * not recognize the detection answers as though it were OpenAI itself, which\n * is wrong for most OpenAI-compatible gateways. So every field here is one a\n * deployment must be able to state because nothing can infer it, while the\n * fields pi-ai's catalog sets for a named vendor stay withheld.\n *\n * A field belongs to the protocols whose upstream compat type declares it: a\n * model-level switch its protocol does not take fails resolution, and a\n * route-level one skips past models it cannot fit. \"The three Responses\n * protocols\" below means `openai-responses`, `azure-openai-responses`, and\n * `openai-codex-responses`, which pi-ai gives one shared compat type, so a\n * switch settable on one is settable on all three.\n */\nexport interface PiAiCompatProfile {\n /** Whether the endpoint accepts `store`; `openai-completions`. */\n supportsStore?: boolean\n /**\n * Whether the endpoint accepts the `developer` role for the system prompt,\n * which pi-ai sends only to a reasoning model; `false` keeps `system`.\n * `openai-completions` and the three Responses protocols.\n */\n supportsDeveloperRole?: boolean\n /** Whether the endpoint accepts `reasoning_effort`; `openai-completions`. */\n supportsReasoningEffort?: boolean\n /** Whether the endpoint accepts `stream_options: {include_usage: true}`; `openai-completions`. */\n supportsUsageInStreaming?: boolean\n /**\n * Whether streams include `finish_reason`; `false` lets pi-ai infer the\n * terminal reason when the stream ends; `openai-completions`.\n */\n supportsFinishReason?: boolean\n /** Which output-cap field the endpoint reads; `openai-completions`. */\n maxTokensField?: NonNullable<OpenAICompletionsCompat['maxTokensField']>\n /** Whether tool results must carry `name`; `openai-completions`. */\n requiresToolResultName?: boolean\n /** Whether a user message after tool results needs an assistant message between; `openai-completions`. */\n requiresAssistantAfterToolResult?: boolean\n /** Whether thinking blocks must travel as text in `<thinking>` delimiters; `openai-completions`. */\n requiresThinkingAsText?: boolean\n /** Whether replayed assistant messages need an empty `reasoning_content` while reasoning is on; `openai-completions`. */\n requiresReasoningContentOnAssistantMessages?: boolean\n /** Reasoning parameter format the endpoint expects; `openai-completions`. */\n thinkingFormat?: PiAiThinkingFormat\n /**\n * Kwargs sent as `chat_template_kwargs`, which pi-ai reads only under the\n * two `chat-template` thinking formats; `openai-completions`. Nothing checks\n * that pairing: the format in force may come from the installed catalog\n * entry or from pi-ai's own baseURL detection, neither of which resolution\n * can read, so kwargs set beside another format are sent nowhere.\n */\n chatTemplateKwargs?: NonNullable<OpenAICompletionsCompat['chatTemplateKwargs']>\n /** Arguments sent as `chat_template_args` under the `baseten` thinking format; `openai-completions`. */\n chatTemplateArgs?: NonNullable<OpenAICompletionsCompat['chatTemplateArgs']>\n /** Whether the endpoint accepts `thinking_token_budget` to cap vLLM reasoning; `openai-completions`. */\n supportsThinkingTokenBudget?: boolean\n /**\n * Whether the endpoint accepts `strict` in tool definitions;\n * `openai-completions`, the three Responses protocols, `bedrock-converse-stream`.\n */\n supportsStrictMode?: boolean\n /** Prompt-cache marker convention; `openai-completions`. */\n cacheControlFormat?: NonNullable<OpenAICompletionsCompat['cacheControlFormat']>\n /**\n * Whether the endpoint accepts long prompt-cache retention;\n * `openai-completions`, the three Responses protocols, `anthropic-messages`.\n */\n supportsLongCacheRetention?: boolean\n /** Whether the endpoint accepts per-tool `eager_input_streaming`; `anthropic-messages`. */\n supportsEagerToolInputStreaming?: boolean\n /** Whether the endpoint accepts `cache_control` on tool definitions; `anthropic-messages`. */\n supportsCacheControlOnTools?: boolean\n /** Whether the endpoint accepts the `temperature` request field; `anthropic-messages`. */\n supportsTemperature?: boolean\n /** Whether to force adaptive thinking regardless of model id; `anthropic-messages`. */\n forceAdaptiveThinking?: boolean\n /** Whether to replay an empty thinking signature instead of converting thinking to text; `anthropic-messages`. */\n allowEmptySignature?: boolean\n /** Whether the endpoint accepts Anthropic strict tool schemas; `anthropic-messages`. */\n supportsStrictTools?: boolean\n}\n\n/** Compile-time constraint that `T` is `never`. */\ntype AssertNever<T extends never> = T\n\n/**\n * Proof that every documented field is one a gate offers. A field the profile\n * declares past the gates fails compilation with its own name in the error.\n */\nexport type EveryProfileFieldIsOffered = AssertNever<Exclude<keyof PiAiCompatProfile, OfferedCompatField>>\n\n/**\n * Proof that every offered field is documented. A gate entry flipped to\n * `offer` without a profile field fails compilation with its own name in the\n * error, which is the half a schema alone cannot catch.\n */\nexport type EveryOfferedFieldIsDocumented = AssertNever<Exclude<OfferedCompatField, keyof PiAiCompatProfile>>\n\n/** Compile-time constraint that `T` is `true`. */\ntype AssertTrue<T extends true> = T\n\n/** Every compat type a gate classifies, merged so one `Pick` reaches all offered fields. */\ntype UpstreamCompat = OpenAICompletionsCompat & OpenAIResponsesCompat & AnthropicMessagesCompat & BedrockCompat\n\n/**\n * Proof that each documented field carries its upstream type, not a hand-copied\n * restatement of it. The name gates above pin *which* fields exist; this pins\n * their types, in both directions because each catches a different drift. A\n * profile field wider than upstream accepts a value the provider rejects, and\n * `resolveModelCompat`'s cast to `ModelCompat` would hide it; a narrower one\n * refuses a value the provider accepts, which is how an upgrade that widens a\n * union would otherwise leave configuration silently behind.\n */\nexport type EveryProfileFieldMatchesUpstream = AssertTrue<\n PiAiCompatProfile extends Partial<Pick<UpstreamCompat, OfferedCompatField>>\n ? Partial<Pick<UpstreamCompat, OfferedCompatField>> extends PiAiCompatProfile ? true : false\n : false\n>\n\n/**\n * The compat entries a profile actually set.\n *\n * schemastery materializes an absent dict as `{}` — the behavior\n * `reasoningEfforts` works around with a union — so every parsed profile\n * carries both template-argument keys whether or not anyone wrote them. An\n * empty one states nothing here: it would send no arguments, which is exactly\n * what leaving the field out does, so absent and empty are the same request\n * and neither may make a route look like it configured a switch. A valueless\n * scalar is the other thing schemastery lets through, and it is refused by\n * {@link assertOfferedCompatFields} before this runs rather than filtered.\n * @param compat - the configured switches, when any.\n * @returns the entries carrying a value, in declaration order.\n */\nfunction configuredCompatEntries(compat: PiAiCompatProfile | undefined): readonly (readonly [string, unknown])[] {\n return Object.entries(compat ?? {}).flatMap(([field, value]) => {\n const empty = typeof value === 'object' && value !== null && !Array.isArray(value)\n && Object.keys(value as object).length === 0\n return empty ? [] : [[field, value] as const]\n })\n}\n\n/**\n * The protocols offering one compat field, in {@link COMPAT_GATES} order.\n * @param field - configured compat field name.\n * @returns the protocols whose compat takes it; empty when none does, which\n * is either a withheld field or a name no upstream compat type declares.\n */\nfunction compatProtocols(field: string): readonly string[] {\n return Object.entries(COMPAT_GATES).flatMap(([api, gate]) => gate[field] === 'offer' ? [api] : [])\n}\n\n/**\n * The compat fields one protocol offers, for a diagnostic that has to show\n * what was available instead of the name that missed.\n * @param api - wire protocol.\n * @returns the offered field names, or an empty list for a protocol taking no compat.\n */\nfunction offeredCompatFields(api: string): readonly string[] {\n return Object.entries(compatGate(api) ?? {}).flatMap(([field, disposition]) => disposition === 'offer' ? [field] : [])\n}\n\n/**\n * Every offered field name, deduplicated, for the one diagnostic that cannot\n * narrow by protocol: the vocabulary check runs before any protocol resolves,\n * which is what lets it refuse a misspelling on a route whose models would\n * never have reached the protocol that declares the intended field.\n * @returns the offered field names across every protocol, in gate order.\n */\nfunction allOfferedCompatFields(): readonly string[] {\n const fields = new Set<string>()\n for (const api of Object.keys(COMPAT_GATES)) {\n for (const field of offeredCompatFields(api)) fields.add(field)\n }\n return [...fields]\n}\n\n/**\n * Reject a compat key no protocol offers. Runs before any protocol is\n * resolved, so a withheld field or a misspelling fails even on a route whose\n * models never reach the protocol that would have taken it — the alternative\n * being the silent drop that let an unreadable switch look applied.\n * @param provider - provider route key, for diagnostics.\n * @param site - the configuration site, for diagnostics.\n * @param compat - the configured switches, when any.\n * @throws Error naming the offending key.\n */\nfunction assertOfferedCompatFields(\n provider: string,\n site: string,\n compat: PiAiCompatProfile | undefined,\n): void {\n // Every key, not only the ones carrying a value: a withheld or undeclared\n // name is never in the schema, so schemastery cannot have materialized it —\n // whatever its value, a person wrote it and expects it to do something.\n for (const [field, value] of Object.entries(compat ?? {})) {\n // The name is judged before the value, so a withheld or misspelled key\n // written bare is refused for being that name rather than for being empty:\n // the other order sends someone to supply a value the key would be refused\n // with anyway.\n if (compatProtocols(field).length === 0) {\n const declared = Object.values(COMPAT_GATES).some(gate => gate[field] !== undefined)\n if (declared) {\n invalid(provider, `${site} sets compat \"${field}\", which is not configurable here: pi-ai's installed`\n + ' catalog sets it for the vendors that need it, so name that provider as the route instead')\n }\n invalid(provider, `${site} sets compat \"${field}\", which no wire protocol declares; the configurable`\n + ` switches are ${allOfferedCompatFields().join(', ')}`)\n }\n // A valueless key (`supportsDeveloperRole:`) survives schemastery, which\n // passes nullable data through before any member schema runs — the same\n // behavior `reasoningEfforts` documents — and a `cordis.yml` entry may\n // reach the same state through `!!js undefined`. Either way the key is\n // kept, so carrying it forward writes nothing over whatever the next layer\n // resolved, leaving pi-ai's `??` at its baseURL detection: the \"written but\n // not applied\" outcome this surface exists to refuse.\n if (value == null) {\n invalid(provider, `${site} sets compat \"${field}\" with no value; give it one, or remove the key to`\n + ' leave the field to the next layer — the installed catalog entry, then pi-ai\\'s own detection')\n }\n }\n}\n\n/** One configured model entry: an id plus the catalog fields it overrides. */\nexport interface PiAiModelProfile {\n /** Model id sent to the provider and accepted by {@link GenerateOptions.model}. */\n id: string\n /** Display name for selectors; defaults to the catalog name, then the id. */\n name?: string\n /** Maximum combined request and response context in tokens. */\n contextWindow?: number\n /**\n * Maximum output tokens. Configuring one also makes it this model's\n * per-request default; a value inherited from the installed catalog, or the\n * route's fallback, is the model's capability and never becomes a request\n * default on its own.\n */\n maxTokens?: number\n /**\n * Request modalities this model accepts. Absent — or empty, which describes\n * a model that accepts nothing and so states no answer either — keeps the\n * installed catalog entry's modalities, then the route's `defaultInput`.\n * Declaring images is what makes a hand-declared vision model usable, and\n * declaring text alone corrects a catalog model whose gateway does not serve\n * what the catalog records. This is a claim about the endpoint, not a check\n * of it: nothing interrogates a gateway for what it accepts, so a model\n * claiming images its endpoint refuses is refused by the provider instead,\n * mid-turn.\n */\n input?: PiAiModality[]\n /**\n * Selectable reasoning efforts. Absent inherits the installed catalog\n * entry's capability (a hand-declared model has none and does not reason);\n * `false` declares a non-reasoning model, which is how a profile strips\n * reasoning from a catalog model its gateway cannot serve; a non-empty dict\n * declares the offered levels and their wire spellings.\n */\n reasoningEfforts?: false | PiAiReasoningEfforts\n /** pi-ai wire-compatibility switches for this model, winning over the route's per field; one its protocol does not declare is refused. */\n compat?: PiAiCompatProfile\n}\n\n/**\n * Customization of one installed catalog model, keyed by its id in the\n * route's `modelOverrides` dict — the same fields a `models` entry may set,\n * with the id living in the key. Unlike a `models` list, overrides leave the\n * rest of the catalog serving untouched, which is what makes \"correct one\n * model, keep the other thirty-seven\" a three-line edit.\n */\nexport type PiAiModelOverride = Omit<PiAiModelProfile, 'id'>\n\n/** The route-level facts model materialization reads. */\nexport interface RouteCatalogRequest {\n /** Provider route key, stamped onto every materialized model. */\n provider: string\n /** Wire protocol override; absent defers to each catalog model's own API. */\n api?: string\n /** Endpoint override; absent defers to the catalog model, then the catalog provider. */\n baseURL?: string\n /** Configured catalog; absent means the whole installed catalog for this route. */\n models?: readonly PiAiModelProfile[]\n /** Installed-catalog customizations by model id; only meaningful while `models` is absent. */\n modelOverrides?: Readonly<Record<string, PiAiModelOverride>>\n /** Route-level wire-compatibility switches, landing on each model whose protocol declares them; entries override per field. */\n compat?: PiAiCompatProfile\n /** Context capacity for a model neither the entry nor the catalog sizes. */\n defaultContextWindow: number\n /** Output capability for a model neither the entry nor the catalog sizes. */\n defaultMaxTokens: number\n /** Modalities for a model neither the entry nor the catalog declares. */\n defaultInput: Model<Api>['input']\n}\n\n/** Report a route the deployment cannot serve, naming the settings key at fault. */\nfunction invalid(provider: string, detail: string): never {\n throw new Error(`llm-pi-ai: provider \"${provider}\" ${detail}`)\n}\n\n/**\n * The one wire protocol a catalog route's shipped models agree on. This is what\n * lets a deployment add a model the installed catalog has not caught up with —\n * a provider's newest release — without restating the protocol its siblings\n * already use. A route whose shipped models disagree (an OpenAI-style catalog\n * spanning Responses and Chat Completions) has no such answer, so a model it\n * does not describe must name its protocol at the route.\n */\nfunction sharedCatalogApi(defaults: ReadonlyMap<string, Model<Api>>): string | undefined {\n const apis = new Set<string>()\n for (const model of defaults.values()) apis.add(model.api)\n return apis.size === 1 ? [...apis][0] : undefined\n}\n\n/** The reasoning fields one materialized model carries. */\ninterface ModelReasoning {\n /** Whether the model reasons at all; `false` makes pi-ai ignore the map. */\n reasoning: boolean\n /** The map dispatch reads; absent only when the installed entry's (or none) applies. */\n thinkingLevelMap?: ThinkingLevelMap\n}\n\n/**\n * Resolve one model's reasoning capability from its declared efforts.\n *\n * A declared dict translates to pi-ai's `thinkingLevelMap` with every level\n * decided explicitly: declared levels carry their wire spelling, undeclared\n * levels are pinned to `null` (unsupported). Pinning matters because pi-ai's\n * own defaulting is asymmetric — an absent key means \"supported\" for the five\n * base levels but \"unsupported\" for `xhigh`/`max` — and a profile author\n * should not need to know that. A declared `off` with no value is the one\n * exception: it stays absent from the map, which pi-ai reads as \"supported,\n * send nothing\" — the correct dispatch where not thinking is the parameter's\n * absence — while `off` with a value sends that value.\n * @param provider - provider route key, for diagnostics.\n * @param entry - the configured model entry.\n * @param base - the installed catalog entry of the same id, when one exists.\n * @returns the reasoning fields the materialized model carries.\n */\nfunction resolveModelReasoning(\n provider: string,\n entry: PiAiModelProfile,\n base: Model<Api> | undefined,\n): ModelReasoning {\n const efforts = entry.reasoningEfforts\n if (efforts === undefined) {\n // Reasoning rides the installed entry or is absent: a bare capability flag\n // would make pi-ai advertise effort levels with no `thinkingLevelMap` to\n // spell them, and no listing endpoint reports a model's reasoning\n // protocol. The entry's map (when any) arrives through the `...base`\n // spread in the model literal.\n return { reasoning: base?.reasoning ?? false }\n }\n // The installed entry's map may ride along through `...base`; pi-ai never\n // reads it on a non-reasoning model, so stripping it is not worth a field\n // enumeration here.\n if (efforts === false) return { reasoning: false }\n // A YAML `reasoningEfforts:` left valueless arrives as null through the\n // schema union — outside the field's declared type, hence the widening —\n // while an explicit `{}` arrives as an empty dict. Both declare nothing,\n // and neither is a spelling of \"inherit\" or \"disable\".\n if ((efforts as unknown) === null || Object.keys(efforts).length === 0) {\n invalid(provider, `model \"${entry.id}\" has an empty reasoningEfforts; declare the offered levels, set`\n + ' false for a non-reasoning model, or omit the field to keep the installed catalog\\'s capability')\n }\n const declared = THINKING_LEVELS.flatMap((level) => {\n const wire = efforts[level]\n return wire === undefined ? [] : [[level, wire] as const]\n })\n for (const [level, wire] of declared) {\n if (wire === null) {\n if (level !== 'off') {\n invalid(provider, `model \"${entry.id}\" reasoningEfforts.${level} needs the wire value dispatch`\n + ' should send; only \"off\" may leave it empty')\n }\n } else if (wire.length === 0) {\n invalid(provider, `model \"${entry.id}\" reasoningEfforts.${level} must not be an empty string`)\n }\n }\n if (!declared.some(([level]) => level !== 'off')) {\n invalid(provider, `model \"${entry.id}\" reasoningEfforts offers no level beyond \"off\"; declare a thinking`\n + ' level, or set reasoningEfforts to false for a non-reasoning model')\n }\n const map: ThinkingLevelMap = {}\n for (const level of THINKING_LEVELS) {\n const wire = efforts[level]\n if (wire === undefined) {\n map[level] = null\n } else if (wire !== null) {\n map[level] = wire\n }\n }\n return { reasoning: true, thinkingLevelMap: map }\n}\n\n/** The compat block a materialized model carries, whichever protocol it speaks. */\ntype ModelCompat = OpenAICompletionsCompat | OpenAIResponsesCompat | AnthropicMessagesCompat | BedrockCompat\n\n/**\n * Resolve one model's compat block from the profile's switches.\n *\n * A model switch wins over the route switch field by field; whatever neither\n * sets keeps the installed entry's value, and a field no layer decides falls\n * through to pi-ai's own detection. A model-level switch its protocol does not\n * take fails resolution — about one named model it can only be a mistake —\n * while a route-level one skips past such models, since a route default must\n * stay settable on a route whose models do not all speak one protocol. Every\n * field reaching here is offered by some protocol; {@link\n * assertOfferedCompatFields} has already refused the rest.\n * @param provider - provider route key, for diagnostics.\n * @param entry - the configured model entry.\n * @param route - the route-level switches, when any.\n * @param base - the installed catalog entry of the same id, when one exists.\n * @param api - the model's resolved wire protocol.\n * @returns a `compat` field to spread into the model, or nothing.\n */\nfunction resolveModelCompat(\n provider: string,\n entry: PiAiModelProfile,\n route: PiAiCompatProfile | undefined,\n base: Model<Api> | undefined,\n api: string,\n): { compat: ModelCompat } | Record<string, never> {\n const gate = compatGate(api)\n const configured: Record<string, unknown> = {}\n for (const [field, value] of configuredCompatEntries(route)) {\n if (gate?.[field] !== 'offer') continue\n configured[field] = value\n }\n for (const [field, value] of configuredCompatEntries(entry.compat)) {\n if (gate?.[field] !== 'offer') {\n const offered = offeredCompatFields(api)\n invalid(provider, `model \"${entry.id}\" sets compat \"${field}\", but its api is \"${api}\", which does not`\n + ` take it; that switch exists on ${compatProtocols(field).join(', ')}, and \"${api}\" offers`\n + ` ${offered.length === 0 ? 'no configurable compat' : offered.join(', ')}`)\n }\n configured[field] = value\n }\n if (Object.keys(configured).length === 0) return {}\n // The installed entry's compat matches the entry's OWN api — a route-level\n // `api` repoint (an anthropic catalog served through an OpenAI-compatible\n // gateway) leaves `base.compat` in the other protocol's shape, so it is\n // inherited only while the resolved api still is the entry's. A repointed\n // model starts from pi-ai's baseURL-derived detection instead, which is\n // what a protocol change means for every other compat field too.\n const inherited = base?.api === api ? base.compat : undefined\n return { compat: { ...inherited, ...configured } as ModelCompat }\n}\n\n/** One route's materialized catalog, plus the request caps its profile chose. */\nexport interface RouteCatalog {\n /** The materialized models in configuration order. */\n models: readonly Model<Api>[]\n /**\n * Per-request output caps this profile explicitly configured, by model id.\n *\n * Separate from `Model.maxTokens` because the two answer different\n * questions: pi-ai requires `maxTokens` as the model's output *capability*,\n * while the harness seam's `defaultMaxTokens` is a cap the deployment chose\n * to send on requests that name none. Materializing a catalog capability as\n * a request default would start capping every request at a number nobody\n * picked, so only an explicit configuration lands here.\n */\n configuredMaxTokens: ReadonlyMap<string, number>\n}\n\n/**\n * Materialize one route's catalog by merging the installed catalog defaults\n * under the configured entries. A route with no configured `models` serves the\n * installed catalog unchanged, which is what keeps an existing\n * `providers: { deepseek: { apiKeyEnv: … } }` profile working untouched.\n * @param request - the route-level catalog facts.\n * @returns the materialized models and the explicitly configured request caps.\n */\nexport function resolveRouteModels(request: RouteCatalogRequest): RouteCatalog {\n const { provider } = request\n const defaults = catalogModels(provider)\n const providerBaseUrl = catalogProvider(provider)?.baseUrl\n // An absent `models` key and an empty one are the same request: the config\n // schema materializes `[]` for the absent case, and an empty catalog could\n // serve no request anyway, so both mean \"serve the installed catalog\".\n const configured = request.models ?? []\n const overrides = request.modelOverrides ?? {}\n // Every miss is refused, never skipped: an override that lands nowhere is a\n // typo someone would otherwise hunt for in a silently unchanged model.\n for (const [id, override] of Object.entries(overrides)) {\n if (id.length === 0) invalid(provider, 'has a modelOverrides entry with an empty model id')\n if (defaults.size === 0) {\n invalid(provider, `sets modelOverrides for \"${id}\", but the installed catalog does not describe this route;`\n + ' a declared route spells every model out in its models list')\n }\n if (configured.length > 0) {\n invalid(provider, `sets modelOverrides for \"${id}\" beside a models list; models already replaces the served`\n + ' catalog, so declare the fields on its entries')\n }\n if (!defaults.has(id)) {\n invalid(provider, `modelOverrides names \"${id}\", which the installed catalog does not describe`)\n }\n // The id lives in the dict key; a value carrying its own would quietly\n // rename the model it meant to customize. The static shape already omits\n // it — this guards the schema boundary, which passes unknown keys through.\n if ('id' in override) {\n invalid(provider, `modelOverrides entry \"${id}\" sets \"id\", which is the dict key`)\n }\n }\n // An override becomes the catalog entry's configuration, so everything a\n // models entry may declare — capacities, efforts, compat — resolves through\n // the same path with the same diagnostics and request-default semantics.\n const entries: readonly PiAiModelProfile[] = configured.length > 0\n ? configured\n : [...defaults.values()].map(model => ({ id: model.id, ...overrides[model.id] }))\n if (entries.length === 0) {\n invalid(provider, 'resolves no models; the installed catalog does not describe this route, so its models'\n + ' must be listed in configuration')\n }\n const routeApi = sharedCatalogApi(defaults)\n // Vocabulary before protocols: a withheld or undeclared switch is refused\n // wherever it is written, so it cannot look applied on a route whose models\n // never reach the protocol that would have taken it.\n assertOfferedCompatFields(provider, 'route', request.compat)\n for (const entry of entries) {\n assertOfferedCompatFields(provider, `model \"${entry.id}\"`, entry.compat)\n }\n const seen = new Set<string>()\n const configuredMaxTokens = new Map<string, number>()\n const models = entries.map((entry) => {\n if (entry.id.length === 0) invalid(provider, 'has a model with an empty id')\n if (seen.has(entry.id)) invalid(provider, `lists model \"${entry.id}\" more than once`)\n seen.add(entry.id)\n const base = defaults.get(entry.id)\n const api = request.api ?? base?.api ?? routeApi\n if (api === undefined) {\n invalid(provider, `model \"${entry.id}\" needs an api; the installed catalog does not describe it, so set the`\n + ' route\\'s api to the wire protocol its endpoint speaks')\n }\n const baseUrl = request.baseURL ?? base?.baseUrl ?? providerBaseUrl\n if (baseUrl === undefined) {\n invalid(provider, `model \"${entry.id}\" needs a baseURL; the installed catalog does not describe this route`)\n }\n // Capacities fall back to the route's own defaults, so a model listing that\n // discloses nothing but ids still yields a serviceable route. The fallback\n // is a guess by construction, which is why it is a configurable route field\n // rather than a constant buried here.\n const contextWindow = entry.contextWindow ?? base?.contextWindow ?? request.defaultContextWindow\n if (!Number.isInteger(contextWindow) || contextWindow <= 0) {\n invalid(provider, `model \"${entry.id}\" contextWindow must be a positive integer`)\n }\n const maxTokens = entry.maxTokens ?? base?.maxTokens ?? request.defaultMaxTokens\n if (!Number.isInteger(maxTokens) || maxTokens <= 0) {\n invalid(provider, `model \"${entry.id}\" maxTokens must be a positive integer`)\n }\n // Only a value the profile named is a deployment choice; the catalog's is\n // the model's capability and stays out of request defaults.\n if (entry.maxTokens !== undefined) configuredMaxTokens.set(entry.id, entry.maxTokens)\n return {\n // The installed entry lays the floor, and the fields below override it.\n // Enumerating instead would silently drop every `Model` field this\n // package does not model — reasoning-level spellings, compatibility\n // quirks, model headers, and whatever a pi-ai upgrade adds next. Spread,\n // never enumerate.\n ...base,\n id: entry.id,\n name: entry.name ?? base?.name ?? entry.id,\n api,\n provider,\n baseUrl,\n input: declaredInput(entry.input) ?? base?.input ?? [...request.defaultInput],\n cost: base?.cost ?? NO_COST,\n contextWindow,\n maxTokens,\n ...resolveModelReasoning(provider, entry, base),\n ...resolveModelCompat(provider, entry, request.compat, base, api),\n }\n })\n // Per field, not per block: a route may default a switch its completions\n // models take beside one only its anthropic models do, and neither should\n // fail for the other's sake. What is refused is a route default no model on\n // the route could ever read, which is a route that will not behave as written.\n for (const [field] of configuredCompatEntries(request.compat)) {\n const takers = compatProtocols(field)\n if (models.some(model => takers.includes(model.api))) continue\n invalid(provider, `sets compat \"${field}\", but no model on the route speaks a protocol that takes it;`\n + ` it exists on ${takers.join(', ')}`)\n }\n return { models, configuredMaxTokens }\n}\n","/**\n * Construction of the pi-ai `Provider` that one configured route registers into\n * the adapter's `Models` collection.\n *\n * Two constructions, one decision: a route the installed catalog ships, whose\n * profile does not override the wire protocol, **reuses that catalog provider**\n * with its models replaced — the catalog provider owns API implementations this\n * package cannot reconstruct (Bedrock loads its Smithy module through a\n * separate entry point), so rebuilding it from parts would silently narrow\n * which providers work. Every other route — one pi-ai has never heard of, or a\n * catalog route pointed at a different protocol — is built by `createProvider`\n * over the protocol table below.\n *\n * Credentials never reach this module's storage: the harness resolves a route's\n * key through `ctx.credentials` before the request enters pi-ai and hands it\n * over as a stream option, which `Models` presents to `resolve()` as the\n * credential key.\n *\n * @module dsh-llm-pi-ai/provider\n */\n\nimport { createProvider } from '@earendil-works/pi-ai'\nimport type { Api, ApiKeyAuth, Model, Provider, ProviderStreams } from '@earendil-works/pi-ai'\nimport { anthropicMessagesApi } from '@earendil-works/pi-ai/api/anthropic-messages.lazy'\nimport { openAICompletionsApi } from '@earendil-works/pi-ai/api/openai-completions.lazy'\nimport { openAIResponsesApi } from '@earendil-works/pi-ai/api/openai-responses.lazy'\nimport { catalogProvider } from './catalog.ts'\n\n/**\n * Wire protocols a configured route may name, mapped to pi-ai's lazily loaded\n * implementations. Each entry is the factory that pi-ai's matching provider\n * factory uses, so a hand-declared route reaches exactly the implementation a\n * catalog route would.\n *\n * The table is deliberately narrow: the protocols a hand-declared route\n * actually reads, each completely describable with a key, an\n * endpoint, and headers. Bedrock signs with SigV4 over AWS credentials and a\n * region, Vertex needs a project, a location, and application-default\n * credentials, Azure needs provider environment plus an api-version, and Codex\n * authenticates through OAuth — none of which this configuration shape can\n * express, so offering them would hand back a provider that cannot\n * authenticate. The remainder are absent for want of a consumer rather than a\n * blocker: each is one line here once a deployment needs it. Catalog routes\n * still reach every protocol through their own provider; only an explicit\n * override is refused.\n */\nconst PROTOCOLS: Readonly<Record<string, () => ProviderStreams>> = {\n 'openai-completions': openAICompletionsApi,\n 'openai-responses': openAIResponsesApi,\n 'anthropic-messages': anthropicMessagesApi,\n}\n\n/**\n * Every wire protocol a configured route may name, most-reached first. The\n * order is the table's and therefore stable; a configuration surface offering\n * a choice presents the first as its default, which is why the protocol a\n * hand-declared gateway most often speaks — and the one endpoint interrogation\n * can read — leads.\n * @returns the supported protocol identifiers.\n */\nexport function supportedProtocols(): readonly string[] {\n return Object.keys(PROTOCOLS)\n}\n\n/**\n * Api-key auth for a route the harness authenticates itself. `Models` calls\n * this after the adapter has already resolved the route's credential, so a\n * missing key here is not this layer's failure: a named-but-unresolvable\n * reference has already failed the request with `MISSING_CREDENTIAL`, and a\n * route naming no credential at all is deliberately unauthenticated. Reporting\n * it as configured hands the decision to the protocol, which is where the\n * requirement actually lives — pi-ai's OpenAI-compatible implementation, for\n * one, still insists on a key or an `Authorization` header of its own.\n * @param name - display name used as the resolution's status label.\n * @returns the api-key auth for a harness-authenticated route.\n */\nfunction harnessApiKeyAuth(name: string): ApiKeyAuth {\n return {\n name,\n resolve: ({ credential }) => Promise.resolve({\n auth: credential?.key === undefined ? {} : { apiKey: credential.key },\n source: name,\n }),\n }\n}\n\n/** The resolved route facts provider construction reads. */\nexport interface ProviderSpec {\n /** Provider route key; also the `Models` collection key and each model's `provider`. */\n provider: string\n /** Display name for selectors and status labels. */\n displayName: string\n /** Wire protocol override; absent means each model keeps its catalog protocol. */\n api?: string\n /** Endpoint override already applied to {@link models}; kept for provider-level display. */\n baseURL?: string\n /** The route's materialized models, in configuration order. */\n models: readonly Model<Api>[]\n /**\n * Whether the profile names a credential, which it does through `apiKeyEnv`\n * alone: configuration carries the reference, never the secret. Only that\n * decides whether {@link routeAuth} adds the harness's own api-key method to\n * a catalog provider that offers none; the key itself still arrives per\n * request, never at construction.\n */\n namesCredential: boolean\n}\n\n/**\n * The auth one route resolves its credential through.\n *\n * A catalog route keeps the installed provider's own auth, which is what\n * preserves provider-native ambient discovery for a profile naming no\n * credential. That holds even when the profile repoints the protocol: which\n * environment a provider reads is a property of the provider, not of the wire\n * format its models speak.\n *\n * The single addition covers a catalog provider that offers no api-key method\n * at all. pi-ai resolves a request's `apiKey` override only when the provider\n * declares one (`resolveProviderAuth` checks `provider.auth.apiKey` before\n * honouring the override), so an OAuth-only provider — `openai-codex` is the\n * one the installed catalog ships — would refuse a profile's explicit key with\n * `Provider is not configured` before any request went out. Adding the harness\n * method beside the provider's own restores that route. A keyless profile adds\n * nothing and still reports the honest refusal, because this adapter resolves\n * credentials through its own seam and holds no OAuth store to fall back on.\n * @param spec - the resolved route facts.\n * @param catalog - the installed catalog provider, when pi-ai ships one.\n * @returns the auth to construct this route's provider with.\n */\nfunction routeAuth(spec: ProviderSpec, catalog: Provider | undefined): Provider['auth'] {\n if (catalog === undefined) return { apiKey: harnessApiKeyAuth(spec.displayName) }\n if (catalog.auth.apiKey !== undefined || !spec.namesCredential) return catalog.auth\n return { ...catalog.auth, apiKey: harnessApiKeyAuth(spec.displayName) }\n}\n\n/**\n * Reuse an installed catalog provider with this route's models and identity.\n * Model dispatch stays with the catalog provider, so its API implementations,\n * compatibility quirks, and ambient credential discovery are preserved exactly.\n * Catalog-owned dynamic refresh is dropped: this route's catalog is the\n * settings document, and a background refresh would contradict it.\n */\nfunction reuseCatalogProvider(base: Provider, spec: ProviderSpec): Provider {\n // Provider-level `baseUrl` is display metadata: pi-ai routes every request\n // through `Model.baseUrl`, which model resolution has already overridden.\n const baseUrl = spec.baseURL ?? base.baseUrl\n return {\n id: spec.provider,\n name: spec.displayName,\n ...baseUrl === undefined ? {} : { baseUrl },\n auth: routeAuth(spec, base),\n getModels: () => spec.models,\n // Delegated rather than copied: the catalog provider stays the receiver, so\n // an implementation holding state on itself keeps working.\n stream: (model, context, options) => base.stream(model, context, options),\n streamSimple: (model, context, options) => base.streamSimple(model, context, options),\n }\n}\n\n/**\n * Build the pi-ai provider for one resolved route.\n * @param spec - the resolved route facts.\n * @returns the provider to register in the adapter's `Models` collection.\n * @throws Error when the route names a wire protocol this build cannot serve.\n */\nexport function buildProvider(spec: ProviderSpec): Provider {\n const catalog = catalogProvider(spec.provider)\n // A catalog route keeping its catalog protocol reuses the catalog provider;\n // an explicit protocol means the deployment is repointing the route at a\n // different wire format, which only the protocol table can serve.\n if (catalog !== undefined && spec.api === undefined) return reuseCatalogProvider(catalog, spec)\n\n // Every model on this path carries the route's protocol: model resolution\n // requires one for a route the catalog cannot default, and an explicit one\n // replaces each catalog model's own. So the route has a single API.\n const factory = spec.api === undefined ? undefined : PROTOCOLS[spec.api]\n if (factory === undefined) {\n throw new Error(\n `llm-pi-ai: provider \"${spec.provider}\" names api \"${spec.api}\", which this build cannot serve;`\n + ` supported protocols are ${supportedProtocols().join(', ')}`,\n )\n }\n return createProvider({\n id: spec.provider,\n name: spec.displayName,\n ...spec.baseURL === undefined ? {} : { baseUrl: spec.baseURL },\n auth: routeAuth(spec, catalog),\n models: spec.models,\n api: factory(),\n })\n}\n","/**\n * Configuration schema and provider-profile validation for the pi-ai adapter.\n * Profiles are a dict keyed by provider route, so the composition base and a\n * user-settings layer merge per provider and the route set is structural.\n *\n * A route key is not required to name an installed pi-ai provider. When it does,\n * that provider's endpoint, protocol, display name, and model catalog are the\n * profile's defaults and the profile overrides them field by field; when it does\n * not, the profile is the whole provider declaration. Resolution therefore ends\n * in a built pi-ai `Provider` per route: everything a request needs is decided\n * once, while the configuration key that made a route unserviceable can still be\n * named in the failure.\n *\n * @module dsh-llm-pi-ai/config\n */\n\nimport type { CacheRetention, ChatTemplateKwargValue, ModelThinkingLevel, Provider, ThinkingBudgets, Transport } from '@earendil-works/pi-ai'\nimport z from '@deepseek-ai/schemastery'\nimport { credentialRef } from '@deepseek-ai/dsh-credentials'\nimport type { CredentialRef } from '@deepseek-ai/dsh-credentials'\nimport { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'\nimport { resolveRetryPolicy, RetryPolicySchema } from '@deepseek-ai/dsh-llm'\nimport type { ResolvedRetryPolicy, RetryPolicyConfig } from '@deepseek-ai/dsh-llm'\nimport {\n CACHE_CONTROL_FORMATS,\n CHAT_TEMPLATE_VARS,\n MAX_TOKENS_FIELDS,\n MODALITIES,\n resolveRouteModels,\n SUPPORTED_THINKING_FORMATS,\n THINKING_LEVELS,\n} from './catalog.ts'\nimport type {\n PiAiCompatProfile,\n PiAiModality,\n PiAiModelOverride,\n PiAiModelProfile,\n PiAiReasoningEfforts,\n} from './catalog.ts'\nimport { buildProvider, supportedProtocols } from './provider.ts'\n\n/** Default maximum idle interval while an adapter stream read is outstanding. */\nexport const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 600_000\n\n/**\n * Default request-level bound on base64-encoded image payload. Every image in\n * history is re-encoded into every request body, so an unbounded conversation\n * eventually exceeds a provider or gateway request-size cap and the session\n * can never complete another request. The 20MiB default admits fifteen 1MiB\n * request versions after base64 expansion and reserves request capacity for\n * system prompts, history, tools, and JSON.\n * Deployments behind stricter gateways lower it per route.\n */\nexport const DEFAULT_MAX_REQUEST_IMAGE_BYTES = 20 * 1024 * 1024\n/** Default total-pixel budget preserves the complete 2048px normalized attachment. */\nexport const DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET = 2048 * 2048\n/** Default raw encoded-byte target before inline base64 expansion; the smallest quality-ladder output is used when no quality fits. */\nexport const DEFAULT_REQUEST_IMAGE_MAX_BYTES = 1024 * 1024\n\n/** Context capacity assumed for a model neither configuration nor the catalog sizes. */\nexport const DEFAULT_CONTEXT_WINDOW = 262_144\n\n/** Output capability assumed for a model neither configuration nor the catalog sizes. */\nexport const DEFAULT_MAX_TOKENS = 32_768\n\n/**\n * Modalities assumed for a model neither configuration nor the catalog\n * declares. Text is the floor every supported protocol certainly carries, so\n * this is the absence of a declaration rather than a guess at the endpoint:\n * nothing can interrogate a gateway for its modalities, and the two wrong\n * answers do not cost the same. Under-claiming refuses the image before it is\n * attached, naming the model. Over-claiming admits one the provider then\n * rejects mid-turn, after the message is durable, leaving the session\n * repeating a request that cannot succeed.\n */\nexport const DEFAULT_INPUT: readonly PiAiModality[] = ['text']\n\nexport type {\n PiAiCompatProfile,\n PiAiModality,\n PiAiModelOverride,\n PiAiModelProfile,\n PiAiReasoningEfforts,\n PiAiThinkingFormat,\n} from './catalog.ts'\n\n/** Configuration for one pi-ai provider route; the `providers` dict key IS the route. */\nexport interface PiAiProviderProfile {\n /** Credential reference (environment-variable name) resolved per request through `ctx.credentials`. */\n apiKeyEnv?: string\n /** Name shown by configuration surfaces; defaults to the route key. */\n displayName?: string\n /**\n * Wire protocol every model on this route speaks. Omission keeps each\n * installed catalog model's own protocol, which is why a catalog route needs\n * no protocol at all; a route the catalog does not ship must name one.\n */\n api?: string\n /** Endpoint for this route's models; defaults to the installed catalog's endpoint. */\n baseURL?: string\n /**\n * This route's model catalog. Omission serves the installed catalog for the\n * route unchanged; an explicit list replaces it, each entry defaulting its\n * unset fields from the installed model of the same id.\n */\n models?: PiAiModelProfile[]\n /**\n * Installed-catalog customizations by model id: each entry reshapes that\n * one model with the same fields a {@link models} entry takes, while the\n * rest of the catalog keeps serving untouched. Only meaningful on a catalog\n * route with no `models` list — `models` already replaces the catalog, so\n * an override beside it, on a route the catalog does not ship, or naming a\n * model the catalog does not describe is refused rather than skipped.\n */\n modelOverrides?: Record<string, PiAiModelOverride>\n /**\n * pi-ai wire-compatibility switches defaulting every model on this route\n * whose protocol declares them; each model's own `compat` overrides per\n * field. What neither sets keeps the installed catalog entry's value, then\n * pi-ai's own detection. A switch no model on the route could read is\n * refused rather than left looking applied.\n */\n compat?: PiAiCompatProfile\n /**\n * Context capacity for a model this route lists that neither the entry nor\n * the installed catalog sizes (default 262,144). A guess by construction, so\n * a deployment whose gateway serves smaller models corrects it here.\n */\n defaultContextWindow?: number\n /**\n * Output capability for a model this route lists that neither the entry nor\n * the installed catalog sizes (default 32,768). This sizes the model; it\n * never becomes a per-request cap on its own.\n */\n defaultMaxTokens?: number\n /**\n * Request modalities for a model this route lists that neither its entry's\n * {@link PiAiModelProfile.input} nor the installed catalog declares (default\n * `[text]`). A fallback like the capacities above, not an override: a\n * catalog model keeps the modalities the catalog records for it, and this\n * value never narrows one. A gateway serving vision models the catalog does\n * not describe declares `[text, image]` once here instead of on every entry.\n * Unlike an entry's list, this one may not be empty — nothing sits below it\n * to answer instead.\n */\n defaultInput?: PiAiModality[]\n /** Provider request headers; host attribution wins reserved names. */\n headers?: Record<string, string>\n /** Provider-neutral pi-ai reasoning level. */\n reasoning?: ModelThinkingLevel\n /** Send reasoning_split to an OpenAI Chat Completions gateway; omission leaves its response format unchanged. */\n reasoningSplit?: boolean\n /** Token budgets used by reasoning providers that support them. */\n thinkingBudgets?: ThinkingBudgets\n /** Prompt-cache retention preference. */\n cacheRetention?: CacheRetention\n /** Streaming transport preference. */\n transport?: Transport\n /** HTTP/provider SDK timeout in milliseconds. */\n timeoutMs?: number\n /** WebSocket connection timeout in milliseconds. */\n websocketConnectTimeoutMs?: number\n /** Maximum provider idle time while one stream read is outstanding. */\n streamIdleTimeoutMs?: number\n /**\n * Maximum base64-encoded image payload per request. When a request's\n * accumulated images exceed it, the oldest images are replaced by text\n * placeholders until the request fits, so a long session keeps completing\n * requests instead of being rejected by a request-size cap.\n */\n maxRequestImageBytes?: number\n /** Total-pixel budget for each deterministic inline request version. */\n requestImagePixelBudget?: number\n /**\n * Raw encoded-byte target for each deterministic inline request version;\n * the smallest quality-ladder output is used when no quality fits.\n */\n requestImageMaxBytes?: number\n /** Provider-owned model-request retry policy; omission uses normal mode with five retries. */\n retryPolicy?: RetryPolicyConfig\n}\n\n/** Validated profile with its route stamped and every adapter-owned default resolved. */\nexport interface ResolvedPiAiProviderProfile\n extends Omit<PiAiProviderProfile, 'apiKeyEnv' | 'retryPolicy' | 'models' | 'displayName'> {\n /** ChatCode CLI route key and the `Models` collection key (the configuration dict key). */\n provider: string\n /** Resolved display name for selectors and configuration surfaces. */\n displayName: string\n /** Validated credential reference, when one is configured. */\n apiKeyEnv?: CredentialRef\n /** Positive finite provider-idle interval after defaulting. */\n streamIdleTimeoutMs: number\n /** Positive request-level base64 image payload bound after defaulting. */\n maxRequestImageBytes: number\n /** Positive total-pixel request-version budget after defaulting. */\n requestImagePixelBudget: number\n /** Positive raw request-version byte target after defaulting; the smallest quality-ladder output is used when no quality fits. */\n requestImageMaxBytes: number\n /** Immutable retry policy captured with this provider route. */\n retryPolicy: ResolvedRetryPolicy\n /**\n * The pi-ai provider this route registers, built from the resolved models.\n * Construction happens here so an unserviceable protocol or an underspecified\n * model fails with the rest of resolution, leaving the last good route set\n * serving requests.\n */\n piProvider: Provider\n /**\n * Per-request output caps this profile explicitly configured, by model id.\n * The seam materializes one only into a request that names no cap of its\n * own, so a catalog capability must not appear here.\n */\n configuredMaxTokens: ReadonlyMap<string, number>\n}\n\n/** Plugin configuration: the provider routes this instance owns. */\nexport interface Config {\n /**\n * pi-ai provider routes, keyed by provider. An empty (or omitted) dict is\n * the dormant settings-driven posture: the adapter mounts with no routes\n * and registers them the moment a settings section supplies profiles.\n */\n providers?: Record<string, PiAiProviderProfile>\n}\n\nconst thinkingBudgets = z.object({\n minimal: z.number(),\n low: z.number(),\n medium: z.number(),\n high: z.number(),\n})\n\n/**\n * One `chat_template_kwargs` or `chat_template_args` value. The `$var` member\n * is pi-ai's placeholder for a value dispatch fills from the request's\n * thinking state, which makes a template-driven gateway configurable without\n * restating its template.\n */\nconst chatTemplateKwarg: z<ChatTemplateKwargValue> = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.const(null),\n z.object({\n $var: z.union(CHAT_TEMPLATE_VARS).required(),\n omitWhenOff: z.boolean(),\n }),\n])\n\nconst compatProfile: z<PiAiCompatProfile> = z.object({\n supportsStore: z.boolean(),\n supportsDeveloperRole: z.boolean(),\n supportsReasoningEffort: z.boolean(),\n supportsUsageInStreaming: z.boolean(),\n supportsFinishReason: z.boolean(),\n maxTokensField: z.union(MAX_TOKENS_FIELDS),\n requiresToolResultName: z.boolean(),\n requiresAssistantAfterToolResult: z.boolean(),\n requiresThinkingAsText: z.boolean(),\n requiresReasoningContentOnAssistantMessages: z.boolean(),\n thinkingFormat: z.union(SUPPORTED_THINKING_FORMATS),\n chatTemplateKwargs: z.dict(chatTemplateKwarg),\n chatTemplateArgs: z.dict(chatTemplateKwarg),\n supportsThinkingTokenBudget: z.boolean(),\n supportsStrictMode: z.boolean(),\n cacheControlFormat: z.union(CACHE_CONTROL_FORMATS),\n supportsLongCacheRetention: z.boolean(),\n supportsEagerToolInputStreaming: z.boolean(),\n supportsCacheControlOnTools: z.boolean(),\n supportsTemperature: z.boolean(),\n forceAdaptiveThinking: z.boolean(),\n allowEmptySignature: z.boolean(),\n supportsStrictTools: z.boolean(),\n})\n\n/**\n * Keys are the offered levels, values their wire spellings. A valueless key\n * (`off:`) survives validation because schemastery passes nullable data\n * through before any member schema runs — `z.const(null)` only controls the\n * error for non-null wrong values and what a configuration UI renders.\n * Only resolution decides which levels may leave the value empty, so the\n * diagnostic can name the route and model. The assertion narrows\n * schemastery's `Dict`, which types every literal key as required; dict\n * validation checks only present keys, so the runtime value is a partial record.\n */\nconst reasoningEfforts = z.dict(\n z.union([z.string(), z.const(null)]),\n z.union(THINKING_LEVELS),\n) as unknown as z<PiAiReasoningEfforts>\n\n/** The fields a `models` entry and a `modelOverrides` value share; only the id's home differs. */\nconst modelFields = {\n name: z.string(),\n contextWindow: z.number().step(1).min(1),\n maxTokens: z.number().step(1).min(1),\n // No explicit default, unlike the route's `defaultInput`: schemastery\n // materializes `[]` for an absent array, and resolution reads that as \"no\n // answer here\" so the catalog entry below still applies.\n input: z.array(z.union(MODALITIES)),\n // The union, not a bare dict: schemastery materializes an absent dict as\n // `{}`, and absent must stay distinguishable — it means \"inherit the\n // installed catalog's capability\", while `false` disables reasoning.\n reasoningEfforts: z.union([z.const(false), reasoningEfforts]),\n compat: compatProfile,\n}\n\nconst modelProfile: z<PiAiModelProfile> = z.object({\n id: z.string().required(),\n ...modelFields,\n})\n\n/** A {@link modelProfile} whose id lives in the `modelOverrides` dict key. */\nconst modelOverride: z<PiAiModelOverride> = z.object(modelFields)\n\nconst profile = z.object({\n apiKeyEnv: z.string().role('credential-ref'),\n displayName: z.string(),\n api: z.union(supportedProtocols()),\n baseURL: z.string(),\n models: z.array(modelProfile),\n modelOverrides: z.dict(modelOverride),\n compat: compatProfile,\n defaultContextWindow: z.number().step(1).min(1).default(DEFAULT_CONTEXT_WINDOW),\n defaultMaxTokens: z.number().step(1).min(1).default(DEFAULT_MAX_TOKENS),\n defaultInput: z.array(z.union(MODALITIES)).default([...DEFAULT_INPUT]),\n headers: z.dict(z.string()),\n reasoning: z.union(THINKING_LEVELS),\n reasoningSplit: z.boolean(),\n thinkingBudgets,\n cacheRetention: z.union(['none', 'short', 'long']),\n transport: z.union(['sse', 'websocket', 'websocket-cached', 'auto']),\n timeoutMs: z.natural(),\n websocketConnectTimeoutMs: z.natural(),\n streamIdleTimeoutMs: z.number().min(Number.MIN_VALUE).max(MAX_TIMER_DELAY_MS).default(DEFAULT_STREAM_IDLE_TIMEOUT_MS),\n maxRequestImageBytes: z.number().step(1).min(1).default(DEFAULT_MAX_REQUEST_IMAGE_BYTES),\n requestImagePixelBudget: z.number().step(1).min(1).default(DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET),\n requestImageMaxBytes: z.number().step(1).min(1).default(DEFAULT_REQUEST_IMAGE_MAX_BYTES),\n retryPolicy: RetryPolicySchema,\n})\n\n/** Runtime schema for {@link Config}. */\nexport const Config: z<Config> = z.object({\n providers: z.dict(profile).default({}),\n})\n\n/**\n * Reject a section this adapter could not serve. Registered as the settings\n * namespace's validator, so an unserviceable profile is refused where it is\n * *written* — `settings.mutate` answers `settings-rejected` with the offending\n * route and model named — instead of being stored and then quietly disabling\n * every route in the namespace. It stays a validator rather than a schema\n * transform because the schema is also the shape a configuration surface\n * renders and the value an absent section resolves to; wrapping it would break\n * both.\n * @param config - the resolved section to check.\n * @throws Error naming the route and model that cannot be served.\n */\nexport function assertServiceable(config: Config): void {\n resolveProfiles(config.providers)\n}\n\n/** Reject removed pre-release profile fields and name their replacements. */\nfunction rejectRemovedFields(provider: string, source: PiAiProviderProfile): void {\n const legacy = source as PiAiProviderProfile & {\n provider?: unknown\n maxRetries?: unknown\n maxRetryDelayMs?: unknown\n }\n if ('provider' in legacy) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" sets \"provider\", which moved to the providers dict key`)\n }\n if ('maxRetries' in legacy || 'maxRetryDelayMs' in legacy) {\n throw new Error(\n `llm-pi-ai: provider \"${provider}\" sets maxRetries or maxRetryDelayMs, which were removed;`\n + ' compose agent recovery with dsh-llm-retry',\n )\n }\n}\n\n/**\n * Validate profiles and return a detached route-keyed map suitable for\n * per-request reads. This is the one explicit resolve step, so an omitted dict\n * resolves to the empty (dormant) route set here rather than through a hidden\n * fallback, and each route's models and pi-ai provider are materialized once.\n * @param providers - configured provider profiles keyed by route.\n * @returns validated profiles in configuration order.\n */\nexport function resolveProfiles(\n providers: Readonly<Record<string, PiAiProviderProfile>> | undefined,\n): Map<string, ResolvedPiAiProviderProfile> {\n if (Array.isArray(providers)) {\n throw new Error('llm-pi-ai: providers is now a dict keyed by provider route, not an array of profiles')\n }\n const entries = Object.entries(providers ?? {})\n const resolved = new Map<string, ResolvedPiAiProviderProfile>()\n for (const [provider, source] of entries) {\n rejectRemovedFields(provider, source)\n if (provider.length === 0) throw new Error('llm-pi-ai: provider names must be non-empty')\n if (source.baseURL !== undefined && source.baseURL.length === 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" has an empty baseURL`)\n }\n if (source.displayName !== undefined && source.displayName.length === 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" has an empty displayName`)\n }\n const streamIdleTimeoutMs = source.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS\n if (!Number.isFinite(streamIdleTimeoutMs)\n || streamIdleTimeoutMs <= 0\n || streamIdleTimeoutMs > MAX_TIMER_DELAY_MS) {\n throw new Error(\n `llm-pi-ai: provider \"${provider}\" streamIdleTimeoutMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`,\n )\n }\n const maxRequestImageBytes = source.maxRequestImageBytes ?? DEFAULT_MAX_REQUEST_IMAGE_BYTES\n if (!Number.isInteger(maxRequestImageBytes) || maxRequestImageBytes <= 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" maxRequestImageBytes must be a positive integer`)\n }\n const requestImagePixelBudget = source.requestImagePixelBudget ?? DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET\n if (!Number.isSafeInteger(requestImagePixelBudget) || requestImagePixelBudget <= 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" requestImagePixelBudget must be a positive safe integer`)\n }\n const requestImageMaxBytes = source.requestImageMaxBytes ?? DEFAULT_REQUEST_IMAGE_MAX_BYTES\n if (!Number.isSafeInteger(requestImageMaxBytes) || requestImageMaxBytes <= 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" requestImageMaxBytes must be a positive safe integer`)\n }\n // Detached from the configuration object because pi-ai types `Model.input`\n // mutable. The schema's explicit default covers an absent key, so an empty\n // list here is always one someone typed — and unlike an entry's, nothing\n // below it can answer instead — so it is refused rather than read as \"no\n // answer\".\n const defaultInput = [...source.defaultInput ?? DEFAULT_INPUT]\n if (defaultInput.length === 0) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" defaultInput must name at least one modality`)\n }\n // The route key, not the installed provider's own name: the directory has\n // always shown route keys, and a catalog route must not silently rename\n // itself on every configuration surface just because it gained a profile.\n const displayName = source.displayName ?? provider\n const catalog = resolveRouteModels({\n provider,\n ...source.api === undefined ? {} : { api: source.api },\n ...source.baseURL === undefined ? {} : { baseURL: source.baseURL },\n ...source.models === undefined ? {} : { models: source.models },\n ...source.modelOverrides === undefined ? {} : { modelOverrides: source.modelOverrides },\n ...source.compat === undefined ? {} : { compat: source.compat },\n defaultInput,\n defaultContextWindow: source.defaultContextWindow ?? DEFAULT_CONTEXT_WINDOW,\n defaultMaxTokens: source.defaultMaxTokens ?? DEFAULT_MAX_TOKENS,\n })\n if (source.reasoningSplit !== undefined && catalog.models.some(model => model.api !== 'openai-completions')) {\n throw new Error(`llm-pi-ai: provider \"${provider}\" reasoningSplit requires every model to use openai-completions`)\n }\n const { apiKeyEnv, retryPolicy, models: _models, displayName: _displayName, ...rest } = source\n resolved.set(provider, {\n ...rest,\n provider,\n displayName,\n ...apiKeyEnv === undefined ? {} : { apiKeyEnv: credentialRef(apiKeyEnv) },\n streamIdleTimeoutMs,\n maxRequestImageBytes,\n requestImagePixelBudget,\n requestImageMaxBytes,\n retryPolicy: resolveRetryPolicy(retryPolicy, `llm-pi-ai: provider \"${provider}\" retryPolicy`),\n ...rest.headers === undefined ? {} : { headers: { ...rest.headers } },\n ...rest.thinkingBudgets === undefined ? {} : { thinkingBudgets: { ...rest.thinkingBudgets } },\n configuredMaxTokens: catalog.configuredMaxTokens,\n piProvider: buildProvider({\n provider,\n displayName,\n ...source.api === undefined ? {} : { api: source.api },\n ...source.baseURL === undefined ? {} : { baseURL: source.baseURL },\n models: catalog.models,\n namesCredential: apiKeyEnv !== undefined,\n }),\n })\n }\n return resolved\n}\n","/**\n * ChatCode CLI request-history conversion into pi-ai's Context vocabulary.\n *\n * @module dsh-llm-pi-ai/context\n */\n\nimport { brandString } from '@deepseek-ai/dsh-brand'\nimport { contentHasImage, IMAGE_OFFLOAD_REQUIRED_CODE, LlmError, offloadedImageText, projectOffloadedImages, requestImageHandleText, requiredImageOffload } from '@deepseek-ai/dsh-llm'\nimport type { ContentBlock, GenerateOptions, ImageAttachmentAccessResolver, Message, ToolCallId } from '@deepseek-ai/dsh-llm'\nimport type {\n AttachmentId,\n AttachmentStore,\n ImageAttachmentRef,\n ImageRequestTarget,\n RequestImageAttachment,\n} from '@deepseek-ai/dsh-attachment'\nimport type { Context as PiContext, ImageContent, Message as PiMessage, TextContent, Tool as PiTool } from '@earendil-works/pi-ai'\nimport { toPiAssistant } from './replay.ts'\nimport { requestImageDimensions } from '@deepseek-ai/dsh-attachment'\nimport { DEFAULT_REQUEST_IMAGE_MAX_BYTES, DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET } from './config.ts'\n\n/** Join the text blocks of a harness message. */\nfunction flattenText(message: Message): string {\n return message.content\n .filter(block => block.type === 'text')\n .map(block => block.text)\n .join('')\n}\n\n\n/** Flatten text recursively inside one tool result. */\nfunction toolResultText(blocks: readonly ContentBlock[]): string {\n return blocks.map(block => block.type === 'text'\n ? block.text\n : block.type === 'tool-result' ? toolResultText(block.content) : '').join('')\n}\n\n/** Reject image roles that pi-ai cannot replay before request-size offloading can replace them. */\nfunction assertSupportedImageRoles(messages: readonly Message[]): void {\n for (const message of messages) {\n if (message.role !== 'user' && contentHasImage(message.content)) {\n throw new LlmError(\n `pi-ai cannot represent an image in an in-history ${message.role} message`,\n 'UNSUPPORTED_CONTENT',\n )\n }\n }\n}\n\nasync function userContent(\n blocks: readonly ContentBlock[],\n requestImages: ReadonlyMap<AttachmentId, RequestImageAttachment>,\n resolveImageAccess: ImageAttachmentAccessResolver,\n): Promise<string | (TextContent | ImageContent)[]> {\n const content: (TextContent | ImageContent)[] = []\n for (const block of blocks) {\n switch (block.type) {\n case 'text':\n if (block.text.length > 0) content.push({ type: 'text', text: block.text })\n break\n case 'image': {\n const version = requestImages.get(block.attachment.attachmentId) as RequestImageAttachment\n content.push({\n type: 'text',\n text: requestImageHandleText(block.attachment, version, resolveImageAccess(block.attachment)),\n })\n content.push({\n type: 'image',\n data: Buffer.from(version.data).toString('base64'),\n mimeType: version.mediaType,\n })\n break\n }\n case 'tool-result':\n {\n const nested = await userContent(block.content, requestImages, resolveImageAccess)\n if (typeof nested === 'string') {\n if (nested.length > 0) content.push({ type: 'text', text: nested })\n } else {\n content.push(...nested)\n }\n }\n break\n default:\n // Other merge-extensible blocks are not user-input vocabulary for pi-ai.\n break\n }\n }\n if (content.every(block => block.type === 'text')) return content.map(block => block.text).join('')\n return content\n}\n\nfunction collectImageRefs(\n blocks: readonly ContentBlock[],\n refs: Map<AttachmentId, ImageAttachmentRef>,\n): void {\n for (const block of blocks) {\n if (block.type === 'image') {\n if (block.offloaded !== true) refs.set(block.attachment.attachmentId, block.attachment)\n } else if (block.type === 'tool-result') {\n collectImageRefs(block.content, refs)\n }\n }\n}\n\nasync function prepareRequestImages(\n messages: readonly Message[],\n attachments: AttachmentStore,\n budget: PiImageRequestBudget,\n signal?: AbortSignal,\n): Promise<Map<AttachmentId, RequestImageAttachment>> {\n const refs = new Map<AttachmentId, ImageAttachmentRef>()\n for (const message of messages) collectImageRefs(message.content, refs)\n const orderedRefs = [...refs.values()]\n const prepared = await Promise.all(orderedRefs.map(\n ref => attachments.readImageRequest(ref, requestImageTarget(ref, budget), signal),\n ))\n const versions = new Map<AttachmentId, RequestImageAttachment>()\n for (const [index, ref] of orderedRefs.entries()) {\n versions.set(ref.attachmentId, prepared[index] as RequestImageAttachment)\n }\n return versions\n}\n\nfunction toolsOf(options: GenerateOptions): PiTool[] | undefined {\n return options.tools?.map(tool => ({\n name: tool.name,\n description: tool.description,\n // ToolSchema.parameters is a JSON Schema object; pi-ai's TSchema\n // (TypeBox) is structurally JSON Schema, so it assigns directly.\n parameters: tool.parameters,\n }))\n}\n\n/** The request split into pi-ai's single `systemPrompt` slot and the history that converts to `messages`. */\ninterface SystemPromptSplit {\n /** Text for pi-ai's `systemPrompt`; `undefined` sends no system prompt. */\n systemPrompt: string | undefined\n /** History messages that convert to pi-ai `messages`. */\n messages: readonly Message[]\n}\n\n/** Select the pi-ai system prompt source shared by both conversion paths. */\nfunction splitSystemPrompt(options: GenerateOptions): SystemPromptSplit {\n if (options.system !== undefined) return { systemPrompt: options.system, messages: options.messages }\n const [first, ...rest] = options.messages\n if (first?.role !== 'system') return { systemPrompt: undefined, messages: options.messages }\n const text = flattenText(first)\n return { systemPrompt: text.length > 0 ? text : undefined, messages: rest }\n}\n\n/** Assemble the request-level pi-ai context envelope shared by both conversion paths. */\nfunction piContext(systemPrompt: string | undefined, options: GenerateOptions, messages: PiMessage[]): PiContext {\n const tools = toolsOf(options)\n return {\n ...systemPrompt !== undefined ? { systemPrompt } : {},\n messages,\n ...tools !== undefined && tools.length > 0 ? { tools } : {},\n }\n}\n\nfunction appendAssistant(\n message: Message,\n messages: PiMessage[],\n toolNames: Map<ToolCallId, string>,\n onReplayDegrade?: (reason: string) => void,\n): void {\n const assistant = toPiAssistant(message, onReplayDegrade)\n for (const block of assistant.content) {\n if (block.type === 'toolCall') toolNames.set(brandString<ToolCallId>(block.id), block.name)\n }\n messages.push(assistant)\n}\n\nfunction textOnlyContext(options: GenerateOptions, onReplayDegrade?: (reason: string) => void): PiContext {\n assertSupportedImageRoles(options.messages)\n const split = splitSystemPrompt(options)\n const toolNames = new Map<ToolCallId, string>()\n const messages: PiMessage[] = []\n for (const message of split.messages) {\n if (contentHasImage(message.content)) {\n throw new LlmError('pi-ai image conversion requires the durable attachment service', 'UNSUPPORTED_CONTENT')\n }\n if (message.role === 'system') {\n messages.push({ role: 'user', content: flattenText(message), timestamp: 0 })\n continue\n }\n if (message.role === 'assistant') {\n appendAssistant(message, messages, toolNames, onReplayDegrade)\n continue\n }\n const text = flattenText(message)\n const results = message.content.filter(block => block.type === 'tool-result')\n if (text.length > 0 || results.length === 0) messages.push({ role: 'user', content: text, timestamp: 0 })\n for (const result of results) {\n messages.push({\n role: 'toolResult',\n toolCallId: result.toolCallId,\n toolName: toolNames.get(result.toolCallId) ?? 'unknown',\n content: [{\n type: 'text',\n text: toolResultText(result.content) || '(no output)',\n }],\n isError: result.isError ?? false,\n timestamp: 0,\n })\n }\n }\n return piContext(split.systemPrompt, options, messages)\n}\n\n/** Inputs that bind deterministic request images to one current tool execution world. */\nexport interface PiImageRequestContext {\n /** Durable provider that resolves request-image bytes and provider-owned host objects. */\n attachments: AttachmentStore\n /** Resolve current tool access separately from deterministic request-image versions. */\n resolveImageAccess: ImageAttachmentAccessResolver\n /** Request-level bound on the base64-encoded payload of retained images; omission leaves the bound unchecked. */\n maxRequestImageBytes?: number\n /** Route pixel and raw encoded-byte budgets. */\n requestImagePolicy?: PiImageRequestBudget\n}\n\n/** Per-route budgets from which each request image's target is derived. */\nexport interface PiImageRequestBudget {\n /** Total-pixel budget; larger sources are downscaled proportionally. */\n maxPixels: number\n /** Encoded-byte target for one request image. */\n maxBytes: number\n}\n\n/** Deterministic request target for one source under the route budgets. */\nfunction requestImageTarget(ref: ImageAttachmentRef, budget: PiImageRequestBudget): ImageRequestTarget {\n return { ...requestImageDimensions(ref.width, ref.height, budget.maxPixels), maxBytes: budget.maxBytes }\n}\n\n/**\n * Convert text-only harness history to a synchronous pi-ai Context. Tool\n * result names are recovered from preceding assistant tool calls.\n * @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.\n * @param images - absent; selects the synchronous conversion.\n * @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.\n * @returns the pi-ai context; `tools` is omitted when the request declares none.\n * @throws {LlmError} `UNSUPPORTED_CONTENT` for images in any history role, including a leading system message.\n */\nexport function toPiContext(\n options: GenerateOptions,\n images?: undefined,\n onReplayDegrade?: (reason: string) => void,\n): PiContext\n/**\n * Convert harness history to a pi-ai Context while resolving durable images.\n * Tool result names are recovered from preceding assistant tool calls. Image\n * occurrences the surface marks offloaded become text placeholders; when the\n * retained occurrences' exact base64 payload still exceeds\n * `maxRequestImageBytes`, the call fails with `IMAGE_OFFLOAD_REQUIRED` naming\n * how many more oldest occurrences must be offloaded.\n * @param options - the harness request; `options.system`, else a leading `system` message, maps to pi-ai's single `systemPrompt` slot.\n * @param images - attachment provider, current path resolver, and request limits.\n * @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.\n * @returns the asynchronously resolved pi-ai context.\n */\nexport function toPiContext(\n options: GenerateOptions,\n images: PiImageRequestContext,\n onReplayDegrade?: (reason: string) => void,\n): Promise<PiContext>\nexport function toPiContext(\n options: GenerateOptions,\n images?: PiImageRequestContext,\n onReplayDegrade?: (reason: string) => void,\n): PiContext | Promise<PiContext> {\n return images === undefined\n ? textOnlyContext(options, onReplayDegrade)\n : toPiContextWithImages(options, images, onReplayDegrade)\n}\n\nasync function toPiContextWithImages(\n options: GenerateOptions,\n images: PiImageRequestContext,\n onReplayDegrade?: (reason: string) => void,\n): Promise<PiContext> {\n const { attachments, resolveImageAccess, maxRequestImageBytes } = images\n const requestImagePolicy = images.requestImagePolicy ?? {\n maxPixels: DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET,\n maxBytes: DEFAULT_REQUEST_IMAGE_MAX_BYTES,\n }\n assertSupportedImageRoles(options.messages)\n const split = splitSystemPrompt(options)\n const requestImages = await prepareRequestImages(split.messages, attachments, requestImagePolicy, options.signal)\n if (maxRequestImageBytes !== undefined) {\n const offloadImages = requiredImageOffload(\n split.messages,\n { representation: 'base64', maxBytes: maxRequestImageBytes },\n block => (requestImages.get(block.attachment.attachmentId) as RequestImageAttachment).bytes,\n )\n if (offloadImages > 0) {\n throw new LlmError(\n `pi-ai request images exceed the ${maxRequestImageBytes}-byte base64 bound; ${offloadImages} more oldest occurrence(s) must be offloaded.`,\n IMAGE_OFFLOAD_REQUIRED_CODE,\n { offloadImages },\n )\n }\n }\n const exactMessages = projectOffloadedImages(\n split.messages,\n ref => offloadedImageText(ref, resolveImageAccess(ref)),\n )\n const toolNames = new Map<ToolCallId, string>()\n const messages: PiMessage[] = []\n\n for (const message of exactMessages) {\n if (message.role === 'system') {\n // pi-ai has a single systemPrompt slot; in-history system messages are\n // folded into user messages to preserve order (rare in practice — the\n // harness sends the system prompt via options.system).\n messages.push({ role: 'user', content: flattenText(message), timestamp: 0 })\n continue\n }\n if (message.role === 'assistant') {\n appendAssistant(message, messages, toolNames, onReplayDegrade)\n continue\n }\n // user role: text + tool results (each result becomes its own message).\n const regular = message.content.filter(block => block.type !== 'tool-result')\n const content = await userContent(regular, requestImages, resolveImageAccess)\n const results = message.content.filter((block): block is Extract<ContentBlock, { type: 'tool-result' }> => (\n block.type === 'tool-result'\n ))\n if (content.length > 0 || results.length === 0) {\n messages.push({ role: 'user', content, timestamp: 0 })\n }\n for (const result of results) {\n const resultContent = await userContent(result.content, requestImages, resolveImageAccess)\n messages.push({\n role: 'toolResult',\n toolCallId: result.toolCallId,\n toolName: toolNames.get(result.toolCallId) ?? 'unknown',\n content: typeof resultContent === 'string'\n ? [{ type: 'text', text: resultContent || '(no output)' }]\n : resultContent,\n isError: result.isError ?? false,\n timestamp: 0,\n })\n }\n }\n\n return piContext(split.systemPrompt, options, messages)\n}\n","/**\n * pi-ai assistant event translation into the ChatCode CLI streaming protocol.\n *\n * pi-ai tool-call arguments are parsed objects while ChatCode CLI keeps their\n * raw JSON representation. pi-ai also reports failures as terminal stream\n * events, which this module maps into ChatCode CLI finish chunks.\n *\n * @module dsh-llm-pi-ai/stream\n */\n\nimport { brandString } from '@deepseek-ai/dsh-brand'\nimport { CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError, QUOTA_EXCEEDED_CODE } from '@deepseek-ai/dsh-llm'\nimport type { FinishReason, StreamChunk, TokenUsage, ToolCallId } from '@deepseek-ai/dsh-llm'\nimport { isContextOverflow } from '@earendil-works/pi-ai'\nimport type { AssistantMessage, AssistantMessageEvent, Usage as PiUsage } from '@earendil-works/pi-ai'\nimport { toPiReplayState } from './replay.ts'\n\n/**\n * Map pi-ai usage (reasoning folded into output by pi-ai).\n * @param usage - cumulative usage from the terminal pi-ai event.\n * @returns harness counts with pi-ai's exact total; cache fields appear only\n * when non-zero (pi-ai reports zeros, not absence).\n */\nexport function mapUsage(usage: PiUsage): TokenUsage {\n return {\n inputTokens: usage.input,\n outputTokens: usage.output,\n totalTokens: usage.totalTokens,\n ...usage.cacheRead > 0 ? { cacheReadTokens: usage.cacheRead } : {},\n ...usage.cacheWrite > 0 ? { cacheWriteTokens: usage.cacheWrite } : {},\n }\n}\n\n// XXX(pi-ai upstream): pi-ai flattens the caught error to `error.message`\n// (api/anthropic-messages.js: `errorMessage = error instanceof Error ?\n// error.message : JSON.stringify(error)`), discarding the original Error and its\n// `cause` chain before it reaches us. undici carries the actionable transport\n// detail on `cause` (e.g. `SocketError: other side closed`) but hands the fetch\n// wrapper a bare `terminated`, so we are left pattern-matching terse words here.\n// If pi-ai ever forwards the original Error (or a fetch/dispatcher hook that lets\n// us capture the cause ourselves), classify on `code`/`cause` instead of text.\nfunction classifyPiAiError(message: string): string {\n if (/\\b(?:401|403)\\b/.test(message)) return 'AUTH'\n if (isQuotaExceededError(message)) return QUOTA_EXCEEDED_CODE\n if (/\\b429\\b|rate.?limit/i.test(message)) return 'RATE_LIMIT'\n // A rejected request body (gateway or provider size cap): resending the\n // same request cannot succeed, so it is invalid, not transient.\n if (/\\b413\\b|failed to buffer the request body:\\s*length limit exceeded|payload too large|request body too large/i.test(message)) return 'INVALID_REQUEST'\n if (/\\b400\\b|invalid.?request/i.test(message)) return 'INVALID_REQUEST'\n if (/\\b5\\d\\d\\b/.test(message)) return 'SERVER'\n if (/\\btime(?:d)?\\s*out\\b|timeout/i.test(message)) return 'TIMEOUT'\n // A stream truncated before the provider's terminal event: each pi-ai provider\n // throws its own wording when the wire closes mid-response without a terminal\n // event (`… stream ended before message_stop`, `… before a terminal response\n // event`, `… ended without a terminal event`, `Stream ended without\n // finish_reason`). The connection dropped mid-response, so this is a transport\n // truncation, not a model-level error.\n if (/stream ended (?:before|without)\\b/i.test(message)) return 'TRANSPORT'\n if (/\\b(?:network|connection|socket|fetch)\\b|\\bECONN[A-Z]+\\b/i.test(message)\n || /\\b(?:other side closed|HTTP2 request did not get a response|WebSocket closed unexpectedly)\\b/i.test(message)\n // undici renders a mid-stream socket drop as a bare `terminated` (its\n // `cause` — the real SocketError — was flattened away upstream); Node's\n // stream layer says `Premature close`.\n || /\\bterminated\\b|premature close/i.test(message)) {\n return 'TRANSPORT'\n }\n return 'PI_AI_ERROR'\n}\n\n/**\n * Map a terminal pi-ai event to the harness finish reason.\n * @param message - the assistant message carried by the `done` or `error` event.\n * @param contextWindow - resolved catalog capacity for usage-based overflow detection.\n * @returns the mapped harness reason. Recognized error text, `stop` usage above\n * `contextWindow`, and zero-output `length` usage that fills the window map\n * to `CONTEXT_WINDOW_EXCEEDED`; a `stop` with no content blocks maps to an\n * `EMPTY_RESPONSE` error, while terminal `pending` and `deferred` states map\n * to non-retryable `PI_AI_ERROR` failures.\n */\nexport function mapStopReason(message: AssistantMessage, contextWindow?: number): FinishReason {\n const piAiOverflow = isContextOverflow(message, contextWindow)\n const harnessOverflow = message.stopReason === 'error'\n && message.errorMessage !== undefined\n && isContextWindowExceededError(message.errorMessage)\n if (piAiOverflow || harnessOverflow) {\n return {\n kind: 'error',\n failure: {\n message: message.errorMessage ?? `pi-ai detected context overflow for model \"${message.model}\"`,\n code: CONTEXT_WINDOW_EXCEEDED_CODE,\n },\n }\n }\n\n switch (message.stopReason) {\n case 'stop':\n // A terminal stop that produced no content blocks is a degenerate\n // provider completion, not a successful (empty) assistant message.\n if (message.content.length === 0) {\n return {\n kind: 'error',\n failure: {\n message: `model \"${message.model}\" returned a completed response with no content`,\n code: EMPTY_RESPONSE_CODE,\n },\n }\n }\n return { kind: 'stop' }\n case 'length': return { kind: 'max-tokens' }\n case 'toolUse': return { kind: 'tool-calls' }\n case 'pending': return {\n kind: 'error',\n failure: { message: `pi-ai stream for model \"${message.model}\" ended pending`, code: 'PI_AI_ERROR' },\n }\n case 'deferred': return {\n kind: 'error',\n failure: { message: `pi-ai deferred response for model \"${message.model}\" is not supported`, code: 'PI_AI_ERROR' },\n }\n case 'aborted': return {\n kind: 'aborted',\n failure: { message: message.errorMessage ?? 'pi-ai stream aborted', code: 'ABORTED' },\n }\n case 'error': {\n const text = message.errorMessage ?? 'pi-ai stream error'\n return { kind: 'error', failure: { message: text, code: classifyPiAiError(text) } }\n }\n }\n}\n\n/**\n * Translate the pi-ai event stream into StreamChunks. pi-ai never throws\n * mid-stream — failures arrive as `error` events, which become error/aborted\n * `finish` chunks (the harness protocol's other error-delivery style).\n * @param events - one assistant turn's pi-ai event stream.\n * @param contextWindow - resolved catalog capacity for usage-based overflow detection.\n * @param callerSignal - caller cancellation state; an aborted caller makes any\n * in-band terminal error an aborted finish.\n * @returns the harness chunks, ending with `usage` then `finish`; throws\n * `LlmError` (`STREAM_CLOSED`) if the source ends without a terminal event.\n */\nexport async function* toStreamChunks(\n events: AsyncIterable<AssistantMessageEvent>,\n contextWindow?: number,\n callerSignal?: AbortSignal,\n): AsyncGenerator<StreamChunk> {\n // pi-ai contentIndex ↔ our block index map 1:1 (both count blocks from 0\n // in stream order), but we track ids per index for tool calls.\n const toolIds = new Map<number, { id: string; name: string }>()\n\n for await (const event of events) {\n switch (event.type) {\n case 'start':\n break\n case 'text_start':\n yield { type: 'block-start', index: event.contentIndex, blockType: 'text' }\n break\n case 'text_delta':\n yield { type: 'text-delta', index: event.contentIndex, text: event.delta }\n break\n case 'text_end':\n yield { type: 'block-end', index: event.contentIndex, block: { type: 'text', text: event.content } }\n break\n case 'thinking_start':\n yield { type: 'block-start', index: event.contentIndex, blockType: 'reasoning' }\n break\n case 'thinking_delta':\n yield { type: 'reasoning-delta', index: event.contentIndex, text: event.delta }\n break\n case 'thinking_end':\n yield { type: 'block-end', index: event.contentIndex, block: { type: 'reasoning', text: event.content } }\n break\n case 'toolcall_start': {\n // The id/name live on the partial's content at this index.\n const partial = event.partial.content[event.contentIndex]\n const id = partial?.type === 'toolCall' ? partial.id : ''\n const name = partial?.type === 'toolCall' ? partial.name : ''\n toolIds.set(event.contentIndex, { id, name })\n yield { type: 'block-start', index: event.contentIndex, blockType: 'tool-call' }\n break\n }\n case 'toolcall_delta': {\n const known = toolIds.get(event.contentIndex)\n yield {\n type: 'tool-call-delta',\n index: event.contentIndex,\n id: brandString<ToolCallId>(known?.id ?? ''),\n ...known?.name !== undefined && known.name.length > 0 ? { name: known.name } : {},\n argumentsDelta: event.delta,\n }\n break\n }\n case 'toolcall_end':\n yield {\n type: 'block-end',\n index: event.contentIndex,\n block: {\n type: 'tool-call',\n id: brandString<ToolCallId>(event.toolCall.id),\n name: event.toolCall.name,\n // pi-ai hands back the PARSED arguments; the harness vocabulary\n // keeps the raw string.\n arguments: JSON.stringify(event.toolCall.arguments),\n },\n }\n break\n case 'done':\n yield { type: 'usage', usage: mapUsage(event.message.usage) }\n yield {\n type: 'finish',\n reason: mapStopReason(event.message, contextWindow),\n replayState: toPiReplayState(event.message),\n }\n return\n case 'error':\n // In-stream error delivery (pi-ai's style) → error finish chunk\n // (the harness's other sanctioned error path besides throwing).\n yield { type: 'usage', usage: mapUsage(event.error.usage) }\n yield {\n type: 'finish',\n reason: mapStopReason(\n callerSignal?.aborted ? { ...event.error, stopReason: 'aborted' } : event.error,\n contextWindow,\n ),\n }\n return\n // no default: AssistantMessageEvent is pi-ai's closed union; a new\n // event type should fail compilation here via tsc's exhaustiveness\n // when one is added (switch covers all current variants).\n }\n }\n throw new LlmError('pi-ai event stream ended without done/error', 'STREAM_CLOSED')\n}\n","/**\n * Generic pi-ai-backed implementation of the ChatCode CLI LLM seam.\n *\n * Each resolution produces one **immutable** snapshot — the profiles plus a\n * `Models` collection holding the `Provider` each route built — and an\n * operation captures a whole snapshot before its first `await`. A\n * configuration change builds a *new* collection rather than mutating the one\n * in use, because `Models.streamSimple()` is lazy: it resolves the provider\n * when the stream is first consumed, which is after the credential await, so a\n * mutated collection would let a request that started under one configuration\n * finish under another — or fail with a provider that no longer exists. This is\n * what makes the seam's per-step call freeze (`llm.prepareCall()`) hold all the\n * way down: switching models mid-reply takes effect on the next step, never\n * inside the one in flight.\n *\n * A route naming a credential reference still resolves it through the harness\n * seam and passes it as the request's `apiKey` option, which pi-ai treats as\n * the highest-priority auth override — that is what keeps the fail-loud\n * reference semantics. Everything that override does not cover reaches pi-ai\n * through the collection's own auth: the credential store holds the records a\n * login wrote and a refresh rotates, and the auth context answers the ambient\n * questions a provider asks while resolving. Both are stable across snapshots,\n * so a configuration change rebuilds the collection without forgetting who is\n * signed in.\n *\n * @module dsh-llm-pi-ai/adapter\n */\n\nimport { createModels, getSupportedThinkingLevels } from '@earendil-works/pi-ai'\nimport type {\n Api,\n AuthContext,\n CredentialStore,\n Model,\n Models,\n ModelThinkingLevel,\n MutableModels,\n SimpleStreamOptions,\n ThinkingLevel,\n} from '@earendil-works/pi-ai'\nimport {\n attributionHeaders,\n contentHasImage,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\n} from '@deepseek-ai/dsh-llm'\nimport type {\n GenerateOptions,\n ImageAttachmentAccess,\n LlmModelInfo,\n LlmProviderInfo,\n LlmResolvedModelInfo,\n PreparedAdapterCall,\n ReasoningEffortId as ReasoningEffortIdType,\n ResolvedRetryPolicy,\n StreamChunk,\n} from '@deepseek-ai/dsh-llm'\nimport type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\nimport { idleWatchdog, timeoutOf } from '@deepseek-ai/dsh-timeout'\nimport type { ResolvedPiAiProviderProfile } from './config.ts'\nimport { toPiContext } from './context.ts'\nimport { toStreamChunks } from './stream.ts'\n\n/** One resolution's frozen view: the profiles and the collection built from them. */\ninterface PiAiSnapshot {\n /** The resolved profiles this collection was built from, used as its identity. */\n profiles: ReadonlyMap<string, ResolvedPiAiProviderProfile>\n /** Providers for exactly those profiles; never mutated once published. */\n models: Models\n}\n\n/** Credentials and headers resolved privately for one request, never advertised as model metadata. */\nexport interface PiAiRequestAuth {\n /** Request API key; omission leaves authentication to provider auth or the supplied headers. */\n apiKey?: string\n /** Authentication headers overriding profile headers; host attribution remains reserved. */\n headers?: Record<string, string>\n}\n\n/** Constructor options for {@link PiAiAdapter}: the resolution hooks the plugin owns. */\nexport interface PiAiAdapterOptions {\n /** Current validated profiles by provider route; called once per operation. */\n profiles: () => ReadonlyMap<string, ResolvedPiAiProviderProfile>\n /**\n * Resolve credentials for one already-resolved profile; called once per\n * stream call and frozen for that call. An empty result defers to the route's own\n * pi-ai auth, which for an installed catalog route is its provider-native\n * ambient discovery; the plugin allows that only for a profile naming no\n * credential at all, because a named reference that misses throws `LlmError`\n * `MISSING_CREDENTIAL` rather than falling back.\n */\n resolveAuth: (provider: string, profile: ResolvedPiAiProviderProfile) => Promise<PiAiRequestAuth>\n /**\n * How every collection this adapter builds resolves auth the request-level\n * `apiKey` override does not cover. Required rather than optional: a\n * collection built without them gets pi-ai's in-memory default store, which\n * is empty at every boot and discarded on every configuration change, so a\n * route whose only method is a login would report itself unconfigured on\n * every request no matter how often the human signed in.\n */\n auth: PiAiAuthInjection\n /** Resolve the optional durable attachment service at request time. */\n resolveAttachments?: () => AttachmentStore | undefined\n /** Bridge one attachment reference into the current model-tool execution world. */\n resolveImageAccess?: (attachments: AttachmentStore, ref: ImageAttachmentRef) => ImageAttachmentAccess | undefined\n /**\n * Observe one assistant history message degrading to provider-neutral\n * conversion because its stored replay state is unusable by this build.\n */\n onReplayDegrade?: (detail: { provider: string; model: string; reason: string }) => void\n}\n\n/** The two auth injectables a pi-ai collection is built with. */\nexport interface PiAiAuthInjection {\n /** Durable storage for credentials pi-ai itself writes: logins, and the refreshes it runs under its own lock. */\n credentials: CredentialStore\n /** Ambient lookups a provider performs while resolving its own auth. */\n authContext: AuthContext\n}\n\n/** Copy profile stream knobs into pi-ai's common option vocabulary. */\nfunction profileOptions(\n profile: ResolvedPiAiProviderProfile,\n reasoning: ModelThinkingLevel | undefined,\n apiKey: string | undefined,\n): SimpleStreamOptions {\n const enabledReasoning: ThinkingLevel | undefined = reasoning === 'off' ? undefined : reasoning\n return {\n ...apiKey === undefined ? {} : { apiKey },\n ...enabledReasoning === undefined ? {} : { reasoning: enabledReasoning },\n ...profile.reasoningSplit === undefined ? {} : { samplingParams: { reasoning_split: profile.reasoningSplit } },\n ...profile.thinkingBudgets === undefined ? {} : { thinkingBudgets: profile.thinkingBudgets },\n ...profile.cacheRetention === undefined ? {} : { cacheRetention: profile.cacheRetention },\n ...profile.transport === undefined ? {} : { transport: profile.transport },\n ...profile.timeoutMs === undefined ? {} : { timeoutMs: profile.timeoutMs },\n ...profile.websocketConnectTimeoutMs === undefined ? {} : { websocketConnectTimeoutMs: profile.websocketConnectTimeoutMs },\n // The agent recovery layer owns visible attempts; one adapter call is one SDK attempt.\n maxRetries: 0,\n }\n}\n\n/**\n * The profile default this exact model can actually take, for DESCRIBING it.\n * A configured level the model does not support yields none rather than\n * throwing: `resolveModel` builds the model catalog, and a catalog that fails\n * takes its whole provider out of every picker — so one mis-set profile field\n * would hide every model on the route, including the ones that support the\n * level. The request path still refuses, which is where a bad configuration\n * belongs: describing what a model can do must not fail because a deployment\n * asked it for something it cannot.\n * @param model - the resolved model descriptor.\n * @param effort - the profile's configured level, if any.\n * @returns the level when this model supports it, otherwise undefined.\n */\nfunction describableReasoningLevel(\n model: Model<Api>,\n effort: ReasoningEffortIdType | ModelThinkingLevel | undefined,\n): ModelThinkingLevel | undefined {\n if (effort === undefined) return undefined\n return getSupportedThinkingLevels(model).some(level => level === effort)\n ? effort as ModelThinkingLevel\n : undefined\n}\n\n/** Validate an explicit ChatCode CLI profile effort without invoking pi-ai's clamp. */\nfunction resolveReasoningLevel(\n model: Model<Api>,\n effort: ReasoningEffortIdType | ModelThinkingLevel | undefined,\n): ModelThinkingLevel | undefined {\n if (effort === undefined) return undefined\n const supported = getSupportedThinkingLevels(model)\n if (supported.some(level => level === effort)) return effort as ModelThinkingLevel\n throw new LlmError(\n `pi-ai provider \"${model.provider}\" model \"${model.id}\" does not support reasoning effort \"${effort}\"`,\n 'UNSUPPORTED_REASONING_EFFORT',\n )\n}\n\n/**\n * Selectable reasoning efforts for one model, or nothing at all.\n *\n * A model that carries no reasoning metadata — every hand-declared one, and\n * every catalog model pi-ai marks as non-reasoning — is reported by pi-ai as\n * supporting the single level `off`. Passing that through would offer a control\n * that cannot do what it says: `off` is translated to *omitting* the reasoning\n * option, which for such a model is byte-for-byte the same request as naming no\n * effort — so a provider whose own default is to think would keep thinking with\n * `off` selected. Omitting `reasoning` entirely is the seam's way of saying the\n * capability is unavailable, which leaves the surface offering only the\n * provider's default.\n * @param model - the resolved model descriptor.\n * @param defaultLevel - the profile's configured effort, already validated.\n * @returns the `reasoning` field, or an empty object when none can be offered.\n */\nfunction reasoningInfo(\n model: Model<Api>,\n defaultLevel: ModelThinkingLevel | undefined,\n): Pick<LlmResolvedModelInfo, 'reasoning'> | Record<string, never> {\n if (!model.reasoning) return {}\n const levels = getSupportedThinkingLevels(model)\n return {\n reasoning: {\n efforts: levels.map(level => ({\n id: ReasoningEffortId(level),\n name: `${level.charAt(0).toUpperCase()}${level.slice(1)}`,\n })),\n ...defaultLevel === undefined ? {} : { defaultEffort: ReasoningEffortId(defaultLevel) },\n },\n }\n}\n\n/** Merge deployment headers while removing case-insensitive attribution collisions. */\nfunction requestHeaders(\n headers: Readonly<Record<string, string>> | undefined,\n auth: Readonly<Record<string, string>> | undefined,\n): Record<string, string> {\n const attribution = attributionHeaders()\n const reserved = new Set([...Object.keys(attribution), ...Object.keys(auth ?? {})].map(name => name.toLowerCase()))\n return {\n ...Object.fromEntries(Object.entries(headers ?? {}).filter(([name]) => !reserved.has(name.toLowerCase()))),\n ...Object.fromEntries(Object.entries(auth ?? {}).filter(([name]) =>\n !Object.keys(attribution).some(reservedName => reservedName.toLowerCase() === name.toLowerCase()))),\n ...attribution,\n }\n}\n\n/**\n * pi-ai-backed multi-provider adapter. Each operation reads the current\n * profiles, so a configuration change reaches the next request without a\n * restart; model descriptors come from the collection those profiles built.\n */\nexport class PiAiAdapter extends LlmAdapter {\n private snapshot: PiAiSnapshot | undefined\n\n constructor(private readonly config: PiAiAdapterOptions) {\n super()\n }\n\n /**\n * The snapshot for the current profiles. Resolution memoizes its result, so\n * an unchanged configuration is recognized by identity; a changed one gets a\n * brand-new collection, leaving any snapshot an operation already captured\n * untouched for as long as that operation holds it.\n */\n private current(): PiAiSnapshot {\n const profiles = this.config.profiles()\n if (this.snapshot?.profiles === profiles) return this.snapshot\n const models: MutableModels = createModels(this.config.auth)\n for (const profile of profiles.values()) models.setProvider(profile.piProvider)\n this.snapshot = { profiles, models }\n return this.snapshot\n }\n\n /** The profile for one route within one snapshot, or the not-owned failure. */\n private profileOf(snapshot: PiAiSnapshot, provider: string): ResolvedPiAiProviderProfile {\n const profile = snapshot.profiles.get(provider)\n if (profile === undefined) {\n throw new LlmError(`pi-ai adapter does not own provider \"${provider}\"`, 'NO_ADAPTER')\n }\n return profile\n }\n\n /** The configured descriptor for one exact route/model pair within one snapshot. */\n private modelOf(snapshot: PiAiSnapshot, provider: string, model: string): Model<Api> {\n this.profileOf(snapshot, provider)\n const resolved = snapshot.models.getModel(provider, model)\n if (resolved === undefined) {\n throw new LlmError(`pi-ai provider \"${provider}\" has no configured model \"${model}\"`, 'UNKNOWN_MODEL')\n }\n return resolved\n }\n\n override providerInfo(provider: string): LlmProviderInfo {\n // The configured name, not the route key: `displayName` exists so a\n // deployment can label a route, and a label only the configuration surface\n // reads would leave every selector showing the raw key.\n return { id: provider, name: this.current().profiles.get(provider)?.displayName ?? provider }\n }\n\n override providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {\n return this.current().profiles.get(provider)?.retryPolicy\n }\n\n override listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n return Promise.resolve().then(() => {\n const snapshot = this.current()\n this.profileOf(snapshot, provider)\n return snapshot.models.getModels(provider).map(model => ({\n provider,\n id: model.id,\n name: model.name,\n inputModalities: [...model.input],\n }))\n })\n }\n\n override resolveModel(\n provider: string,\n model: string,\n _signal?: AbortSignal,\n ): Promise<LlmResolvedModelInfo> {\n return Promise.resolve().then(() => {\n const snapshot = this.current()\n return this.modelInfo(snapshot, provider, model)\n })\n }\n\n private modelInfo(snapshot: PiAiSnapshot, provider: string, model: string): LlmResolvedModelInfo {\n const profile = this.profileOf(snapshot, provider)\n const resolvedModel = this.modelOf(snapshot, provider, model)\n const defaultLevel = describableReasoningLevel(resolvedModel, profile.reasoning)\n // Only a cap the deployment configured is a request default; the\n // catalog's `maxTokens` sizes the model and stops there.\n const configuredMaxTokens = profile.configuredMaxTokens.get(model)\n return {\n provider,\n id: model,\n name: resolvedModel.name,\n inputModalities: [...resolvedModel.input],\n context: { contextWindow: resolvedModel.contextWindow },\n ...configuredMaxTokens === undefined ? {} : { defaultMaxTokens: configuredMaxTokens },\n ...reasoningInfo(resolvedModel, defaultLevel),\n }\n }\n\n override prepareCall(provider: string, model: string, _signal?: AbortSignal): Promise<PreparedAdapterCall> {\n const snapshot = this.current()\n return Promise.resolve({\n model: this.modelInfo(snapshot, provider, model),\n stream: options => this.streamWithSnapshot(options, snapshot),\n })\n }\n\n stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n return this.streamWithSnapshot(options, this.current())\n }\n\n private async * streamWithSnapshot(\n options: GenerateOptions,\n snapshot: PiAiSnapshot,\n ): AsyncIterable<StreamChunk> {\n if (options.stop !== undefined) {\n throw new LlmError('llm-pi-ai does not support GenerateOptions.stop', 'UNSUPPORTED_OPTION')\n }\n // One capture per stream call, taken before any await: the profile, the\n // model descriptor, and the collection all come from the same immutable\n // snapshot, and the credential freezes with them. A configuration change\n // mid-request builds a separate snapshot, so this request finishes under\n // the one it started with and the next call picks up the new one.\n const profile = this.profileOf(snapshot, options.provider)\n const model = this.modelOf(snapshot, options.provider, options.model)\n const reasoning = resolveReasoningLevel(\n model,\n options.reasoningEffort ?? profile.reasoning,\n )\n const auth = await this.config.resolveAuth(options.provider, profile)\n\n const consumer = new AbortController()\n const upstream = options.signal === undefined\n ? consumer.signal\n : AbortSignal.any([options.signal, consumer.signal])\n const streamIdleTimeoutMs = profile.streamIdleTimeoutMs\n using watchdog = idleWatchdog(upstream, streamIdleTimeoutMs, 'LLM_STREAM_IDLE_TIMEOUT')\n\n try {\n const containsImage = options.messages.some(message => contentHasImage(message.content))\n if (containsImage && !model.input.includes('image')) {\n throw new LlmError(`pi-ai model \"${model.id}\" does not support image input`, 'UNSUPPORTED_CONTENT')\n }\n const attachments = containsImage ? this.config.resolveAttachments?.() : undefined\n if (containsImage && attachments === undefined) {\n throw new LlmError('pi-ai image input requires the durable attachment service', 'UNSUPPORTED_CONTENT')\n }\n const onReplayDegrade = (reason: string): void => {\n this.config.onReplayDegrade?.({ provider: options.provider, model: options.model, reason })\n }\n const context = attachments === undefined\n ? toPiContext(options, undefined, onReplayDegrade)\n : await toPiContext({ ...options, signal: watchdog.signal }, {\n attachments,\n resolveImageAccess: ref => this.config.resolveImageAccess?.(attachments, ref),\n maxRequestImageBytes: profile.maxRequestImageBytes,\n requestImagePolicy: {\n maxPixels: profile.requestImagePixelBudget,\n maxBytes: profile.requestImageMaxBytes,\n },\n }, onReplayDegrade)\n const events = snapshot.models.streamSimple(model, context, {\n ...profileOptions(profile, reasoning, auth.apiKey),\n ...options.temperature === undefined ? {} : { temperature: options.temperature },\n ...options.maxTokens === undefined ? {} : { maxTokens: options.maxTokens },\n ...options.sessionId === undefined ? {} : { sessionId: String(options.sessionId) },\n signal: watchdog.signal,\n // Profile headers are deployment-owned; attribution names are\n // Host-owned and therefore win collisions.\n headers: requestHeaders(profile.headers, auth.headers),\n })\n const iterator = toStreamChunks(events, model.contextWindow, options.signal)[Symbol.asyncIterator]()\n let exhausted = false\n try {\n while (true) {\n const result = await watchdog.next(iterator)\n const timeout = timeoutOf(watchdog.signal, 'LLM_STREAM_IDLE_TIMEOUT')\n if (timeout !== undefined) throw timeout\n if (result.done) {\n exhausted = true\n return\n }\n yield result.value\n }\n } finally {\n if (!exhausted) {\n consumer.abort('pi-ai stream consumer stopped')\n try {\n await iterator.return(undefined)\n } catch (_abortedSdkTeardown) {\n // The stable signal already owns SDK termination; return-time abort cannot add an outcome.\n }\n }\n }\n } catch (error: unknown) {\n if (timeoutOf(watchdog.signal, 'LLM_STREAM_IDLE_TIMEOUT') !== undefined) {\n throw new LlmError(`pi-ai stream idle timeout after ${streamIdleTimeoutMs}ms`, 'TIMEOUT', { cause: error })\n }\n if (options.signal?.aborted) {\n throw new LlmError('pi-ai request aborted by caller', 'ABORTED', { cause: error })\n }\n throw error\n } finally {\n consumer.abort('pi-ai stream consumer stopped')\n }\n }\n}\n","/** Aggregate imported models while dispatching each private route through its selected adapter. @module dsh-llm-chatcode-config/adapter */\n\nimport { LlmAdapter, LlmError } from '@deepseek-ai/dsh-llm'\nimport { getOrCreateAnonymousUserId } from '@deepseek-ai/dsh-anonymous-user-id'\nimport { DeepSeekAdapter, resolveAdapterOptions } from '@deepseek-ai/dsh-llm-deepseek'\nimport type {\n GenerateOptions,\n LlmModelInfo,\n LlmProviderInfo,\n LlmResolvedModelInfo,\n PreparedAdapterCall,\n ResolvedRetryPolicy,\n StreamChunk,\n} from '@deepseek-ai/dsh-llm'\nimport { PiAiAdapter } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport type { PiAiAdapterOptions } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport { isolatedPiAiAuth } from '../vendor/dsh-llm-pi-ai/src/auth.ts'\nimport type { ResolvedPiAiProviderProfile } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { ChatCodeModelSelection, ChatCodeSource } from './source.ts'\n\n/** One public provider route containing every imported ChatCode custom model. */\nexport const CHATCODE_PROVIDER = 'chatcode-custom'\n/** Display name for the unified imported-model group. */\nexport const CHATCODE_PROVIDER_NAME = '自定义模型'\n/** Provider route and selector group for centrally managed Coding Plan models. */\nexport const CODING_PLAN_PROVIDER = 'chatcode-codingplan'\nexport const CODING_PLAN_PROVIDER_NAME = '内置模型'\n/** Provider route and selector group for opt-in MAAS models. */\nexport const MAAS_PROVIDER = 'chatcode-maas'\nexport const MAAS_PROVIDER_NAME = '元景'\n\ninterface PrivateSelection extends ChatCodeModelSelection {\n selection: string\n}\n\nconst DEEPSEEK_MODEL = /deepseek/i\n\nfunction privateModelKey(route: string, model: string): string {\n return `${route}\\u0000${model}`\n}\n\nfunction createDeepSeekAdapter(\n route: string,\n profile: ResolvedPiAiProviderProfile,\n model: ReturnType<ResolvedPiAiProviderProfile['piProvider']['getModels']>[number],\n apiKey: string | undefined,\n): DeepSeekAdapter {\n const protocol = profile.api === 'anthropic-messages'\n ? 'messages'\n : profile.api === 'openai-completions'\n ? 'chat-completions'\n : undefined\n if (protocol === undefined || profile.baseURL === undefined) {\n throw new LlmError(`chatcode-config: DeepSeek model route \"${route}\" has no supported protocol or base URL`, 'INVALID_CHATCODE_CONFIG')\n }\n const connection = {\n ...resolveAdapterOptions({\n protocol,\n baseURL: profile.baseURL,\n defaultContextWindow: model.contextWindow,\n maxTokens: model.maxTokens,\n models: [{\n id: model.id,\n name: model.name,\n contextWindow: model.contextWindow,\n maxTokens: model.maxTokens,\n inputModalities: [...model.input],\n }],\n streamIdleTimeoutMs: profile.streamIdleTimeoutMs,\n }),\n retryPolicy: profile.retryPolicy,\n }\n return new DeepSeekAdapter({\n options: () => connection,\n resolveApiKey: () => {\n if (apiKey === undefined) {\n throw new LlmError(`chatcode-config: no API key for DeepSeek model \"${model.id}\"`, 'MISSING_CREDENTIAL')\n }\n return Promise.resolve(apiKey)\n },\n resolveUserId: () => getOrCreateAnonymousUserId(),\n prepareExtensions: () => Promise.resolve({ fields: {}, accept: () => Promise.resolve() }),\n })\n}\n\n/** A static unified ChatCode catalog with request adapters selected from actual model ids. */\nexport class ChatCodeAdapter extends LlmAdapter {\n private readonly piAdapter: PiAiAdapter\n private readonly deepSeekAdapters = new Map<string, LlmAdapter>()\n private readonly routes = new Map<string, PrivateSelection>()\n private readonly publicModels = new Map<string, string>()\n\n constructor(\n options: PiAiAdapterOptions,\n private readonly profiles: ReadonlyMap<string, ResolvedPiAiProviderProfile>,\n private readonly provider = CHATCODE_PROVIDER,\n private readonly providerName = CHATCODE_PROVIDER_NAME,\n selections?: ReadonlyMap<string, ChatCodeModelSelection>,\n apiKeys: ReadonlyMap<string, string> = new Map(),\n ) {\n super()\n this.piAdapter = new PiAiAdapter(options)\n for (const [route, profile] of profiles) for (const model of profile.piProvider.getModels()) {\n const selection = [...(selections ?? new Map<string, ChatCodeModelSelection>())]\n .find(([, target]) => target.route === route && target.model === model.id)?.[0] ?? model.id\n if (this.routes.has(selection)) {\n throw new LlmError(`chatcode-config provider has duplicate public model \"${selection}\"`, 'INVALID_CHATCODE_CONFIG')\n }\n this.routes.set(selection, { selection, route, model: model.id })\n this.publicModels.set(privateModelKey(route, model.id), selection)\n if (DEEPSEEK_MODEL.test(model.id)) {\n this.deepSeekAdapters.set(privateModelKey(route, model.id), createDeepSeekAdapter(route, profile, model, apiKeys.get(route)))\n }\n }\n }\n\n private requestAdapter(target: ChatCodeModelSelection): LlmAdapter {\n return this.deepSeekAdapters.get(privateModelKey(target.route, target.model)) ?? this.piAdapter\n }\n\n /** Reject routes outside the one public provider registered by this adapter. */\n private assertProvider(provider: string): void {\n if (provider !== this.provider) {\n throw new LlmError(`chatcode-config adapter does not own provider \"${provider}\"`, 'NO_ADAPTER')\n }\n }\n\n /** Resolve the private route for one publicly selected model. */\n private routeOf(provider: string, model: string): PrivateSelection {\n this.assertProvider(provider)\n const target = this.routes.get(model)\n if (target === undefined) {\n throw new LlmError(`chatcode-config provider has no configured model \"${model}\"`, 'UNKNOWN_MODEL')\n }\n return target\n }\n\n private validateOutput(options: GenerateOptions, target: PrivateSelection): void {\n const ceiling = this.profiles.get(target.route)?.configuredMaxTokens.get(target.model)\n if (ceiling !== undefined && options.maxTokens !== undefined && options.maxTokens > ceiling) {\n throw new LlmError('chatcode-config: maxTokens exceeds the configured model output limit', 'UNSUPPORTED_OPTION')\n }\n }\n\n override providerInfo(provider: string): LlmProviderInfo {\n this.assertProvider(provider)\n return { id: provider, name: this.providerName }\n }\n\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined {\n return this.profiles.values().next().value?.retryPolicy\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n this.assertProvider(provider)\n const catalogs = await Promise.all([...this.profiles.keys()].map(async route => ({\n route,\n models: await this.piAdapter.listModels(route),\n })))\n return catalogs.flatMap(({ route, models }) => models.map(model => ({\n ...model,\n id: this.publicModels.get(privateModelKey(route, model.id)) ?? model.id,\n provider: this.provider,\n })))\n }\n\n override async resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo> {\n const target = this.routeOf(provider, model)\n const resolved = await this.requestAdapter(target).resolveModel(target.route, target.model, signal)\n return { ...resolved, id: target.selection, provider: this.provider }\n }\n\n override async prepareCall(provider: string, model: string, signal?: AbortSignal): Promise<PreparedAdapterCall> {\n const target = this.routeOf(provider, model)\n const prepared = await this.requestAdapter(target).prepareCall(target.route, target.model, signal)\n return {\n model: { ...prepared.model, id: target.selection, provider: this.provider },\n stream: (options) => {\n const preparedTarget = this.routeOf(options.provider, options.model)\n this.validateOutput(options, preparedTarget)\n return prepared.stream({ ...options, provider: preparedTarget.route, model: preparedTarget.model })\n },\n }\n }\n\n override stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n const target = this.routeOf(options.provider, options.model)\n this.validateOutput(options, target)\n return this.requestAdapter(target).stream({ ...options, provider: target.route, model: target.model })\n }\n}\n\n/** Live custom-model adapter whose prepared calls retain their starting settings snapshot. */\nexport class LiveChatCodeAdapter extends LlmAdapter {\n private snapshot?: { source: ChatCodeSource; adapter: ChatCodeAdapter }\n\n constructor(\n private readonly source: () => ChatCodeSource,\n private readonly provider = CHATCODE_PROVIDER,\n private readonly providerName = CHATCODE_PROVIDER_NAME,\n ) { super() }\n\n private current(): ChatCodeAdapter {\n const source = this.source()\n if (this.snapshot?.source === source) return this.snapshot.adapter\n const adapter = new ChatCodeAdapter({\n profiles: () => source.profiles,\n resolveAuth: (route) => {\n const auth = source.auth.get(route)\n if (auth === undefined) {\n throw new LlmError('chatcode-config: missing auth for resolved profile', 'INVARIANT')\n }\n return Promise.resolve(auth)\n },\n auth: isolatedPiAiAuth(),\n }, source.profiles, this.provider, this.providerName, source.selections, source.apiKeys)\n this.snapshot = { source, adapter }\n return adapter\n }\n\n override providerInfo(provider: string): LlmProviderInfo {\n return this.current().providerInfo(provider)\n }\n\n override providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {\n return this.current().providerRetryPolicy(provider)\n }\n\n override listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n return this.current().listModels(provider)\n }\n\n override resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo> {\n return this.current().resolveModel(provider, model, signal)\n }\n\n override prepareCall(provider: string, model: string, signal?: AbortSignal): Promise<PreparedAdapterCall> {\n return this.current().prepareCall(provider, model, signal)\n }\n\n override stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n return this.current().stream(options)\n }\n}\n","/** ChatCode session login and its shared, host-only credential record. */\nimport { randomUUID } from 'node:crypto'\nimport { setTimeout as wait } from 'node:timers/promises'\nimport { Service } from '@deepseek-ai/cordis'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { credentialKey } from '@deepseek-ai/dsh-credentials'\nimport type { CredentialProvider, CredentialRecord } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\n\n/** Keep the address stable for grants written by the initial implementation. */\nexport const CHATCODE_CREDENTIAL_KEY = credentialKey('chatcode-auth', 'default')\n/** Process-scoped credential accepted from immutable desktop/terminal launchers. */\nexport const CHATCODE_CLI_OAUTH_TOKEN = 'CHATCODE_CLI_OAUTH_TOKEN'\nexport interface ChatCodeGrant {\n version: 1\n accessToken: string\n refreshToken?: string\n longToken?: string\n expiresAtMs?: number\n userName?: string\n emailAddress?: string\n}\nexport interface ChatCodeLoginState {\n sessionId: string\n state: 'pending' | 'succeeded' | 'failed' | 'timed-out' | 'cancelled'\n expiresAtMs: number\n}\n/** Safe UI projection: never add a token or raw upstream response here. */\nexport interface ChatCodeAuthStatus {\n required: boolean\n configured: boolean\n expired: boolean\n validation: 'valid' | 'invalid' | 'unavailable' | 'none'\n expiresAtMs?: number\n userName?: string\n emailAddress?: string\n login?: ChatCodeLoginState\n}\nexport interface ChatCodeLoginStart { sessionId: string; url: string }\nexport interface ChatCodeStatusOptions {\n /** Bypass the short validation cache and contact the account service again. */\n force?: boolean\n}\nexport interface ChatCodeAuthOptions {\n requireLogin?: boolean\n loginUrl: string\n apiBaseUrl: string\n pollIntervalMs: number\n pollTimeoutMs: number\n requestTimeoutMs: number\n}\nexport interface ChatCodeAuthApi {\n status(options?: ChatCodeStatusOptions): Promise<ChatCodeAuthStatus>\n startLogin(): Promise<ChatCodeLoginStart>\n cancelLogin(sessionId: string): Promise<void>\n waitForLogin(sessionId: string, signal?: AbortSignal): Promise<ChatCodeLoginState['state']>\n logout(): Promise<void>\n /** Host-only accessor; presentation adapters must use status(). */\n accessToken(signal?: AbortSignal): Promise<string | undefined>\n /** Host-only launch fact; reveals presence, never the credential value. */\n environmentTokenActive(): boolean\n}\ninterface AccountState {\n version: 2\n grant?: ChatCodeGrant\n login?: ChatCodeLoginState\n validation?: 'valid' | 'invalid' | 'unavailable'\n checkedAtMs?: number\n}\ndeclare module '@deepseek-ai/cordis' {\n interface Context { chatcodeAuth: ChatCodeAuthService }\n}\nconst objectOf = (value: unknown): Record<string, unknown> => value !== null && typeof value === 'object' ? value as Record<string, unknown> : {}\nconst stringOf = (value: unknown): string | undefined => typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined\nconst finiteTime = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value) && value > 0 && value <= 8.64e15\n\nfunction endpoint(value: string): URL {\n const url = new URL(value)\n if (url.username || url.password || (url.protocol !== 'https:' && !(url.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname)))) {\n throw new Error('ChatCode endpoints require HTTPS (HTTP is allowed only on loopback).')\n }\n return url\n}\n/** Preserve the configured hash-router query while adding this attempt's UUID. */\nexport function loginUrlOf(loginUrl: string, sessionId: string): string {\n const url = endpoint(loginUrl)\n if (!url.hash) url.searchParams.set('sessionId', sessionId)\n else {\n const hash = url.hash.slice(1)\n const split = hash.indexOf('?')\n const route = split < 0 ? hash : hash.slice(0, split)\n const params = new URLSearchParams(split < 0 ? '' : hash.slice(split + 1))\n params.set('sessionId', sessionId)\n url.hash = `${route}?${params.toString()}`\n }\n return url.href\n}\n/** Decode both the original payload and the concurrency-safe envelope. */\nexport function grantOf(value: unknown): ChatCodeGrant | undefined {\n const envelope = objectOf(value)\n const candidate = envelope.version === 2 ? objectOf(envelope.grant) : envelope\n if (candidate.version !== 1 || !stringOf(candidate.accessToken)) return undefined\n for (const field of ['refreshToken', 'longToken', 'userName', 'emailAddress']) {\n if (candidate[field] !== undefined && typeof candidate[field] !== 'string') return undefined\n }\n if (candidate.expiresAtMs !== undefined && !finiteTime(candidate.expiresAtMs)) return undefined\n return {\n version: 1, accessToken: stringOf(candidate.accessToken)!,\n ...(candidate.refreshToken === undefined ? {} : { refreshToken: candidate.refreshToken as string }),\n ...(candidate.longToken === undefined ? {} : { longToken: candidate.longToken as string }),\n ...(candidate.userName === undefined ? {} : { userName: candidate.userName as string }),\n ...(candidate.emailAddress === undefined ? {} : { emailAddress: candidate.emailAddress as string }),\n ...(candidate.expiresAtMs === undefined ? {} : { expiresAtMs: candidate.expiresAtMs as number }),\n }\n}\nfunction stateOf(record: CredentialRecord | undefined): AccountState {\n const payload = objectOf(record?.kind === 'grant' ? record.payload : undefined)\n const grant = grantOf(payload)\n const state: AccountState = { version: 2, ...(grant ? { grant } : {}) }\n if (payload.version !== 2) return state\n const login = objectOf(payload.login)\n if (typeof login.sessionId === 'string' && finiteTime(login.expiresAtMs) && ['pending', 'succeeded', 'failed', 'timed-out', 'cancelled'].includes(String(login.state))) {\n state.login = { sessionId: login.sessionId, state: login.state as ChatCodeLoginState['state'], expiresAtMs: login.expiresAtMs }\n }\n if (['valid', 'invalid', 'unavailable'].includes(String(payload.validation)) && finiteTime(payload.checkedAtMs)) {\n state.validation = payload.validation as AccountState['validation'] & string\n state.checkedAtMs = payload.checkedAtMs\n }\n return state\n}\nfunction recordOf(state: AccountState): CredentialRecord {\n // The credentials seam accepts a JSON object; no undefined properties are emitted.\n return { kind: 'grant', payload: { ...state } }\n}\nfunction emailOf(value: unknown): string | undefined {\n const root = objectOf(value)\n const data = objectOf(root.data)\n for (const source of [data, objectOf(data.account), root]) {\n for (const key of ['email', 'emailAddress', 'userEmail', 'mail']) {\n const email = stringOf(source[key])\n if (email && email.length <= 320 && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email\n }\n }\n return undefined\n}\nfunction responseGrant(body: unknown, previous?: ChatCodeGrant): ChatCodeGrant | undefined {\n const data = objectOf(objectOf(body).data)\n const accessToken = stringOf(data.access_token)\n if (!accessToken) return undefined\n const expiresAtMs = typeof data.expires_in === 'number' && data.expires_in > 0 ? Date.now() + data.expires_in * 1000 : undefined\n const grant: ChatCodeGrant = { version: 1, accessToken }\n for (const [target, source] of [['refreshToken', 'refresh_token'], ['longToken', 'longToken'], ['userName', 'userName']] as const) {\n const value = stringOf(data[source]) ?? previous?.[target]\n if (value) grant[target] = value\n }\n if (finiteTime(expiresAtMs)) grant.expiresAtMs = expiresAtMs\n if (previous?.emailAddress) grant.emailAddress = previous.emailAddress\n // No new expiry means unknown; reusing an expired timestamp causes endless refreshes.\n return grant\n}\nfunction stale(grant: ChatCodeGrant): boolean {\n return grant.expiresAtMs !== undefined && grant.expiresAtMs <= Date.now() + 30_000\n}\n\n/**\n * Snapshot the desktop grant only from the inherited process environment.\n * Project/user .env files are deliberately excluded: this credential is an\n * explicit property of one host launch, not durable ChatCode CLI configuration.\n */\nexport function chatCodeEnvironmentToken(ctx: Context): string | undefined {\n return stringOf(launchEnvironmentOf(ctx).getFrom(CHATCODE_CLI_OAUTH_TOKEN, ['process'])?.value)\n}\n\n/** One protocol owner, shared across Web and TUI through credentials-local's file lock. */\nexport class ChatCodeAuthService extends Service implements ChatCodeAuthApi {\n private readonly lifetime = new AbortController()\n private readonly active = new Map<string, AbortController>()\n private readonly failures = new Map<string, ChatCodeLoginState>()\n private readonly tasks = new Set<Promise<void>>()\n /** A new host process must contact ChatCode once before trusting persisted validation metadata. */\n private startupValidationPending = true\n\n private readonly environmentAccessToken: string | undefined\n\n constructor(\n ctx: Context,\n private readonly credentials: CredentialProvider,\n private readonly options: ChatCodeAuthOptions,\n environmentAccessToken?: string,\n ) {\n super(ctx, 'chatcodeAuth')\n this.environmentAccessToken = stringOf(environmentAccessToken)\n endpoint(options.loginUrl)\n endpoint(options.apiBaseUrl)\n ctx.effect(() => async () => {\n this.lifetime.abort()\n await Promise.allSettled(this.tasks)\n }, 'chatcode-auth: stop pending requests')\n }\n\n private async mutate(fn: (state: AccountState) => Promise<AccountState | undefined>): Promise<AccountState> {\n try {\n const result = await this.credentials.modifyRecord(CHATCODE_CREDENTIAL_KEY, async record => {\n const next = await fn(stateOf(record))\n return next === undefined ? undefined : recordOf(next)\n })\n return stateOf(result)\n } catch {\n // Provider errors can include the credential document; never send them to UIs/logs.\n throw new Error('ChatCode credential operation failed; check the ChatCode CLI credential store permissions and availability.')\n }\n }\n\n private async ensure(signal?: AbortSignal, force = false): Promise<AccountState> {\n const combined = AbortSignal.any([this.lifetime.signal, ...(signal ? [signal] : []), AbortSignal.timeout(Math.min(20_000, this.options.requestTimeoutMs * 3))])\n combined.throwIfAborted()\n const state = await this.mutate(async current => {\n combined.throwIfAborted()\n const grant = current.grant\n if (!grant) {\n this.startupValidationPending = false\n return undefined\n }\n // The caller may poll status for presentation, but only the first read\n // in this host process contacts the company network automatically.\n // An explicit retry bypasses this guard after a transient outage.\n if (!force && !this.startupValidationPending) return undefined\n let next = grant\n let result: { validation: 'valid' | 'invalid' | 'unavailable'; emailAddress?: string }\n try {\n if (stale(grant)) {\n const refreshed = await this.refresh(grant, combined)\n if (refreshed.grant) next = refreshed.grant\n result = refreshed.grant ? await this.account(next, combined) : { validation: refreshed.validation }\n } else {\n result = await this.account(grant, combined)\n if (result.validation === 'invalid') {\n const refreshed = await this.refresh(grant, combined)\n if (refreshed.grant) {\n next = refreshed.grant\n result = await this.account(next, combined)\n } else result = { validation: refreshed.validation }\n }\n }\n } finally {\n this.startupValidationPending = false\n }\n // Persist rotated long tokens even if subsequent account validation is temporarily unavailable.\n if (result.emailAddress) next = { ...next, emailAddress: result.emailAddress }\n signal?.throwIfAborted()\n this.lifetime.signal.throwIfAborted()\n return { ...current, grant: next, validation: result.validation, checkedAtMs: Date.now() }\n })\n return state\n }\n\n async status(options: ChatCodeStatusOptions = {}): Promise<ChatCodeAuthStatus> {\n // An inference-scoped desktop token may not be authorized for the account\n // profile endpoint. Its validity is established by managed-catalog I/O;\n // do not read or mutate the durable credential record on this path.\n if (this.environmentAccessToken !== undefined) {\n return {\n required: this.options.requireLogin !== false,\n configured: true,\n expired: false,\n validation: 'valid',\n }\n }\n const state = await this.ensure(undefined, options.force === true)\n const grant = state.grant\n const login = state.login?.state === 'pending' ? this.failures.get(state.login.sessionId) ?? state.login : state.login\n return {\n required: this.options.requireLogin !== false,\n configured: grant !== undefined,\n expired: grant?.expiresAtMs !== undefined && grant.expiresAtMs <= Date.now(),\n validation: grant ? state.validation ?? 'unavailable' : 'none',\n ...(grant?.expiresAtMs === undefined ? {} : { expiresAtMs: grant.expiresAtMs }),\n ...(grant?.userName ? { userName: grant.userName } : {}),\n ...(grant?.emailAddress ? { emailAddress: grant.emailAddress } : {}),\n ...(login ? { login: login.state === 'pending' && login.expiresAtMs <= Date.now() ? { ...login, state: 'timed-out' as const } : login } : {}),\n }\n }\n\n async accessToken(signal?: AbortSignal): Promise<string | undefined> {\n signal?.throwIfAborted()\n if (this.environmentAccessToken !== undefined) return this.environmentAccessToken\n const state = await this.ensure(signal)\n signal?.throwIfAborted()\n return state.validation === 'valid' && state.grant && (state.grant.expiresAtMs === undefined || state.grant.expiresAtMs > Date.now()) ? state.grant.accessToken : undefined\n }\n\n environmentTokenActive(): boolean {\n return this.environmentAccessToken !== undefined\n }\n\n async startLogin(): Promise<ChatCodeLoginStart> {\n if (this.environmentAccessToken !== undefined) {\n throw new Error('ChatCode authentication is provided by the launch environment.')\n }\n this.lifetime.signal.throwIfAborted()\n const sessionId = randomUUID()\n const url = loginUrlOf(this.options.loginUrl, sessionId)\n const login: ChatCodeLoginState = { sessionId, state: 'pending', expiresAtMs: Date.now() + this.options.pollTimeoutMs }\n // Publish the attempt before returning its URL. A newer process's attempt wins.\n await this.mutate(async current => {\n this.lifetime.signal.throwIfAborted()\n for (const controller of this.active.values()) controller.abort()\n return { ...current, login }\n })\n this.failures.clear()\n const controller = new AbortController()\n this.active.set(sessionId, controller)\n const signal = AbortSignal.any([controller.signal, this.lifetime.signal, AbortSignal.timeout(this.options.pollTimeoutMs)])\n const task = this.pollAndCommit(login, signal).catch(async () => {\n const state = Date.now() >= login.expiresAtMs ? 'timed-out' : signal.aborted ? 'cancelled' : 'failed'\n const failed: ChatCodeLoginState = { ...login, state }\n try { await this.finish(failed) } catch { this.failures.set(sessionId, failed) }\n }).finally(() => { this.active.delete(sessionId); this.tasks.delete(task) })\n this.tasks.add(task)\n return { sessionId, url }\n }\n\n async logout(): Promise<void> {\n // The environment source has strict lifetime precedence. Logging out must\n // neither persist it nor destroy an unrelated stored identity underneath.\n if (this.environmentAccessToken !== undefined) return\n for (const controller of this.active.values()) controller.abort()\n await this.mutate(async current => ({ version: 2, ...(current.login ? { login: { ...current.login, state: 'cancelled' } } : {}) }))\n this.failures.clear()\n // Keep the token-free tombstone: other processes must not resurrect an old attempt.\n }\n\n async cancelLogin(sessionId: string): Promise<void> {\n this.active.get(sessionId)?.abort()\n await this.mutate(async current => current.login?.sessionId === sessionId && current.login.state === 'pending'\n ? { ...current, login: { ...current.login, state: 'cancelled' } } : undefined)\n }\n\n async waitForLogin(sessionId: string, signal?: AbortSignal): Promise<ChatCodeLoginState['state']> {\n const combined = AbortSignal.any([this.lifetime.signal, ...(signal ? [signal] : [])])\n while (true) {\n combined.throwIfAborted()\n const status = await this.status()\n if (status.login?.sessionId !== sessionId) return 'cancelled'\n if (status.login.state !== 'pending') return status.login.state\n await wait(this.options.pollIntervalMs, undefined, { signal: combined })\n }\n }\n\n private async finish(login: ChatCodeLoginState): Promise<void> {\n await this.mutate(async current => current.login?.sessionId === login.sessionId && current.login.state === 'pending' ? { ...current, login } : undefined)\n }\n\n private async pollAndCommit(login: ChatCodeLoginState, signal: AbortSignal): Promise<void> {\n let grant: ChatCodeGrant | undefined\n while (Date.now() < login.expiresAtMs) {\n signal.throwIfAborted()\n const current = await this.mutate(async () => undefined)\n if (current.login?.sessionId !== login.sessionId || current.login.state !== 'pending') return\n if (!grant) {\n const response = await this.request(`/caassist-api-lt/caassist/api/account/session/login?${new URLSearchParams({ sessionId: login.sessionId })}`, { method: 'GET', signal })\n if (response?.ok) grant = responseGrant(response.body)\n }\n if (grant) {\n const account = await this.account(grant, signal)\n if (account.validation === 'invalid') throw new Error('ChatCode rejected the login grant.')\n if (account.validation === 'valid') {\n const validated = { ...grant, ...(account.emailAddress ? { emailAddress: account.emailAddress } : {}) }\n await this.mutate(async latest => {\n // Check AFTER acquiring the file lock: logout may have won while this callback queued.\n signal.throwIfAborted()\n if (latest.login?.sessionId !== login.sessionId || latest.login.state !== 'pending') return undefined\n return { version: 2, grant: validated, validation: 'valid', checkedAtMs: Date.now(), login: { ...login, state: 'succeeded' } }\n })\n return\n }\n }\n await wait(Math.min(this.options.pollIntervalMs, Math.max(1, login.expiresAtMs - Date.now())), undefined, { signal })\n }\n await this.finish({ ...login, state: 'timed-out' })\n }\n\n private async account(grant: ChatCodeGrant, signal: AbortSignal): Promise<{ validation: 'valid' | 'invalid' | 'unavailable'; emailAddress?: string }> {\n const response = await this.request('/caassist-api-lt/caassist/api/account/info', {\n method: 'POST', headers: { authorization: `Bearer ${grant.accessToken}`, 'content-type': 'application/json' }, body: '{}', signal,\n })\n const body = objectOf(response?.body)\n if (response?.status === 401 || response?.status === 403 || body.code === '76021501') return { validation: 'invalid' }\n if (!response?.ok || !(body.success === true || body.code === '00000000')) return { validation: 'unavailable' }\n const emailAddress = emailOf(body)\n return { validation: 'valid', ...(emailAddress ? { emailAddress } : {}) }\n }\n\n private async refresh(current: ChatCodeGrant, signal: AbortSignal): Promise<{ grant?: ChatCodeGrant; validation: 'invalid' | 'unavailable' }> {\n const username = current.userName || current.emailAddress\n if (!username || !current.longToken) return { validation: 'invalid' }\n const response = await this.request('/caassist-api-lt/caassist/api/account/long/login', {\n method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ username, longToken: current.longToken }), signal,\n })\n const body = objectOf(response?.body)\n const grant = response?.ok ? responseGrant(body, current) : undefined\n if (grant) return { grant, validation: 'unavailable' }\n return { validation: response?.status === 401 || response?.status === 403 || body.code === '76021501' || body.success === false ? 'invalid' : 'unavailable' }\n }\n\n private async request(path: string, init: RequestInit): Promise<{ ok: boolean; status: number; body: unknown } | undefined> {\n const signal = AbortSignal.any([this.lifetime.signal, ...(init.signal ? [init.signal] : []), AbortSignal.timeout(this.options.requestTimeoutMs)])\n try {\n const response = await fetch(new URL(path, this.options.apiBaseUrl), { ...init, signal, redirect: 'error' })\n return { ok: response.ok, status: response.status, body: await response.json().catch(() => undefined) }\n } catch { return undefined }\n }\n}\n","/** Mount and settings configuration for ChatCode model sources. @module dsh-llm-chatcode-config/config */\n\nimport z from '@deepseek-ai/schemastery'\nimport { RetryPolicySchema } from '@deepseek-ai/dsh-llm'\nimport type { RetryPolicyConfig } from '@deepseek-ai/dsh-llm'\n\n/** One user-defined model stored in the plugin-owned settings namespace. */\nexport interface CustomModel {\n /** Exact model ID sent to the configured gateway. */\n model: string\n /** Plaintext gateway credential stored in settings.yaml. */\n apiKey: string\n /** Gateway base URL, including any path prefix. */\n baseUrl: string\n /** Optional selector label; the model ID is used when omitted. */\n description?: string\n /** Legacy protocol hint used when protocol is omitted. */\n provider?: string | null\n /** Compatible wire protocol: OpenAI or Anthropic. */\n protocol?: string\n /** Context capacity advertised to ChatCode CLI. */\n contextWindow?: number\n /** Default and maximum output token count. */\n maxTokens?: number\n /** Legacy context-capacity fallback. */\n maxInputTokens?: number\n}\n\n/** One provider/model rule used to classify ChatCode model statistics. */\nexport interface ModelKindRule {\n /** Exact ChatCode CLI provider route; omission matches every provider. */\n provider?: string\n /** Exact provider model id; omission matches every model. */\n model?: string\n /** ChatCode model category. */\n kind: number\n}\n\n/** Operational reporting controls for committed ChatCode CLI Session events. */\nexport interface ReportingConfig {\n /** Enable reporting when the Session service is available. */\n enabled: boolean\n /** Enable durable AI-generated-code reporting. */\n codeSave: boolean\n /** Enable conversation and message database synchronization. */\n conversationSync: boolean\n /** Enable the user-visible ChatCode message chain. */\n chatCodeSession: boolean\n /** Maximum code records in one save request. */\n codeBatchItems: number\n /** Maximum aggregate code characters in one save request. */\n codeBatchChars: number\n /** Delay before retrying the durable code outbox. */\n codeRetryDelayMs: number\n /** Absolute code outbox directory; an empty value uses the resolved ChatCode CLI Home. */\n codeOutboxDir: string\n /** Include subagent Sessions in conversation database synchronization. */\n includeSubagentConversationSync: boolean\n /** Ordered exact-match overrides applied before backend URL classification. */\n modelKindRules: ModelKindRule[]\n}\n\n/** Model sources, account access, and operations-reporting configuration. */\nexport interface Config {\n /** Legacy Host JSON file used only when the settings namespace is absent. */\n settingsPath?: string\n /** User-defined models served from the plugin-owned settings namespace. */\n customModels: CustomModel[]\n /** Context capacity when a managed entry omits its capacity. */\n defaultContextWindow: number\n /** Output default and ceiling when a managed entry omits maxTokens. */\n defaultMaxTokens: number\n /** Retry policy for every imported route; omission uses the LLM service default. */\n retryPolicy?: RetryPolicyConfig\n /** ChatCode account sign-in and refresh endpoint selection. */\n auth: {\n /** Retained for login UI compatibility; it never blocks model calls. */\n requireLogin: boolean\n loginUrl: string\n apiBaseUrl: string\n pollIntervalMs: number\n pollTimeoutMs: number\n requestTimeoutMs: number\n }\n /** CVP backend root for generated code, conversation synchronization, and ChatCode message records. */\n cvpChatCodeApiUrl: string\n /** Optional CVP credential override and timeout for launch admission. */\n startupGate: {\n token: string\n timeoutMs: number\n }\n /** ChatCode operations reporting derived from committed Session events. */\n reporting: ReportingConfig\n\n /** Runtime-config API queried once when the ChatCode CLI profile starts. */\n codingPlanEndpoint: string\n /** Include the separately configured MAAS catalog in the model selector. */\n enableMaas: boolean\n /** MAAS catalog API, queried only when {@link enableMaas} is true. */\n maasEndpoint: string\n /** Bound one catalog request so a failed control plane cannot block startup indefinitely. */\n catalogTimeoutMs: number\n}\n\n/** Mount input accepts independently partial account and reporting sections. */\nexport interface ConfigInput extends Omit<Partial<Config>, 'auth' | 'reporting' | 'startupGate'> {\n auth?: Partial<Config['auth']>\n reporting?: Partial<ReportingConfig>\n startupGate?: Partial<Config['startupGate']>\n}\n\n/** Validate mounting options without exposing control-plane credentials. */\nexport const Config: z<ConfigInput, Config> = z.object({\n settingsPath: z.string(),\n customModels: z.array(z.object({\n model: z.string().required(),\n apiKey: z.string().required().role('secret'),\n baseUrl: z.string().required(),\n description: z.string(),\n provider: z.union([z.string(), z.const(null)]),\n protocol: z.string(),\n contextWindow: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER),\n maxTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER),\n maxInputTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER),\n })).default([]),\n defaultContextWindow: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(262_144),\n defaultMaxTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(4096),\n retryPolicy: RetryPolicySchema,\n\n auth: z.object({\n requireLogin: z.boolean().default(true),\n loginUrl: z.string().default('https://chatcode.chinaunicom.cn/unicode/#/login'),\n apiBaseUrl: z.string().default('https://chatcode.chinaunicom.cn'),\n pollIntervalMs: z.number().step(1).min(250).max(60_000).default(1_000),\n pollTimeoutMs: z.number().step(1).min(1_000).max(7_200_000).default(3_600_000),\n requestTimeoutMs: z.number().step(1).min(1_000).max(60_000).default(5_000),\n }).default({\n requireLogin: true,\n loginUrl: 'https://chatcode.chinaunicom.cn/unicode/#/login',\n apiBaseUrl: 'https://chatcode.chinaunicom.cn',\n pollIntervalMs: 1_000,\n pollTimeoutMs: 3_600_000,\n requestTimeoutMs: 5_000,\n }),\n\n cvpChatCodeApiUrl: z.string().default('https://chatcode.chinaunicom.cn/cvp'),\n startupGate: z.object({\n token: z.string().role('secret').default(''),\n timeoutMs: z.number().step(1).min(1_000).max(60_000).default(5_000),\n }).default({ token: '', timeoutMs: 5_000 }),\n // cvpChatCodeApiUrl: z.string().default('http://127.0.0.1:8080'),\n\n reporting: z.object({\n enabled: z.boolean().default(true),\n codeSave: z.boolean().default(true),\n conversationSync: z.boolean().default(true),\n chatCodeSession: z.boolean().default(true),\n codeBatchItems: z.number().step(1).min(1).max(500).default(50),\n codeBatchChars: z.number().step(1).min(1_024).max(5 * 1024 * 1024).default(512 * 1024),\n codeRetryDelayMs: z.number().step(1).min(1_000).max(300_000).default(5_000),\n codeOutboxDir: z.string().default(''),\n includeSubagentConversationSync: z.boolean().default(false),\n modelKindRules: z.array(z.object({\n provider: z.string(),\n model: z.string(),\n kind: z.number().step(1).min(0).max(3).required(),\n })).default([]),\n }).default({\n enabled: true,\n codeSave: true,\n conversationSync: true,\n chatCodeSession: true,\n codeBatchItems: 50,\n codeBatchChars: 512 * 1024,\n codeRetryDelayMs: 5_000,\n codeOutboxDir: '',\n includeSubagentConversationSync: false,\n modelKindRules: [],\n }),\n\n codingPlanEndpoint: z.string().default('https://chatcode.chinaunicom.cn/cvp/api/cli/v1/model-runtime-configs'),\n enableMaas: z.boolean().default(false),\n maasEndpoint: z.string().default('https://chatcode.chinaunicom.cn/cvp/wanma/api/v1/cli/maas-models'),\n catalogTimeoutMs: z.number().step(1).min(1).max(60_000).default(10_000),\n\n})\n","/** Read centrally managed model catalogs without exposing their credentials. @module dsh-llm-chatcode-config/managed */\n\nimport { createHash } from 'node:crypto'\nimport { userInfo } from 'node:os'\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { PiAiRequestAuth } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport { resolveProfiles } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { PiAiProviderProfile, ResolvedPiAiProviderProfile } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { Config } from './config.ts'\nimport type { ChatCodeModelSelection, ChatCodeSource } from './source.ts'\n\n/** Resolve the OS account that launched the current DSH host. */\nexport function currentUserName(): string {\n const environmentName = process.env.USERNAME?.trim() || process.env.USER?.trim()\n if (environmentName !== undefined && environmentName !== '') return environmentName\n try {\n return userInfo().username.trim()\n } catch {\n return ''\n }\n}\n\n/** Query fields required by the CodingPlan runtime catalogue. */\nfunction runtimeQuery(userName = currentUserName()): Readonly<Record<string, string>> {\n return { userEmail: userName }\n}\n\n/** Host-only authorization for ChatCode control-plane requests. */\nexport interface ManagedCatalogAuthorization {\n accessToken: string\n}\n\n/** Optional host-side diagnostic sink; callers decide where messages are written. */\nexport type ManagedCatalogDiagnostic = (message: string) => void\n\ntype Protocol = 'openai-completions' | 'anthropic-messages'\n\ninterface RuntimeModel {\n logicalModelId: string\n displayName: string\n description?: string\n protocol?: string\n provider?: string\n baseUrl?: string\n providerModelId?: string\n apiKey?: string\n maxToken?: number\n contextWindow?: number\n}\n\ninterface MaasCatalogModel {\n id: number\n logicalModelId: string\n displayName: string\n description?: string\n protocol?: string\n model?: string\n maxTokens?: number\n contextWindow?: number\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : undefined\n}\n\nfunction string(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction positive(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isSafeInteger(value) && value > 0 ? value : undefined\n}\n\nconst DIAGNOSTIC_BODY_LIMIT = 16_000\nconst SENSITIVE_FIELD = /(?:api[-_]?key|access[-_]?token|refresh[-_]?token|long[-_]?token|authorization|password|secret)/i\n\n/** Render enough of a JSON response to diagnose its shape without logging credentials. */\nfunction diagnosticBody(value: unknown): string {\n try {\n const rendered = JSON.stringify(value, (key, item) => SENSITIVE_FIELD.test(key) ? '[REDACTED]' : item)\n if (rendered === undefined) return '<empty>'\n return rendered.length <= DIAGNOSTIC_BODY_LIMIT\n ? rendered\n : `${rendered.slice(0, DIAGNOSTIC_BODY_LIMIT)}...<truncated>`\n } catch {\n return '<unserializable JSON>'\n }\n}\n\nfunction catalogHeaders(\n authorization: ManagedCatalogAuthorization | undefined,\n noCache = false,\n): Record<string, string> {\n const accessToken = authorization?.accessToken.trim()\n if (accessToken !== undefined && accessToken !== '' && !/[\\r\\n]/.test(accessToken)) {\n return {\n Accept: 'application/json',\n ...(noCache ? { 'Cache-Control': 'no-cache' } : {}),\n Authorization: `Bearer ${accessToken}`,\n accessToken,\n }\n }\n return { Accept: 'application/json', ...(noCache ? { 'Cache-Control': 'no-cache' } : {}) }\n}\n\nfunction protocolOf(model: RuntimeModel): Protocol | undefined {\n switch (model.protocol?.trim().toLowerCase()) {\n case 'openai': return 'openai-completions'\n case 'anthropic': return 'anthropic-messages'\n default: return undefined\n }\n}\n\n/** Accept gateway roots and a complete OpenAI chat-completions URL from the control plane. */\nfunction endpointOf(value: string): string | undefined {\n let url: URL\n try { url = new URL(value) } catch { return undefined }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) return undefined\n url.pathname = url.pathname.replace(/\\/chat\\/completions\\/?$/i, '') || '/'\n return url.href.replace(/\\/+$/, '')\n}\n\nfunction requestApiKey(apiKey: string | undefined): string | undefined {\n // Control planes commonly redact a key as \"****\". It is not a credential and\n // must never be sent to a provider or reflected in a diagnostic.\n if (apiKey === undefined || apiKey.trim() === '' || /^\\*+$/.test(apiKey.trim()) || /[\\r\\n]/.test(apiKey)) return undefined\n return apiKey\n}\n\nfunction requestAuth(protocol: Protocol, apiKey: string | undefined): PiAiRequestAuth {\n if (apiKey === undefined) return {}\n return protocol === 'anthropic-messages'\n ? { headers: { Authorization: `Bearer ${apiKey}` } }\n : { apiKey }\n}\n\n/** Fetch the supported control-plane response shape and report only generic, non-secret errors. */\nexport async function fetchRuntimeModels(\n endpoint: string,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n diagnostic?: ManagedCatalogDiagnostic,\n): Promise<readonly RuntimeModel[]> {\n let url: URL\n try { url = new URL(endpoint) } catch {\n throw new LlmError('chatcode-config: managed model endpoint is invalid', 'INVALID_CHATCODE_CONFIG')\n }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) {\n throw new LlmError('chatcode-config: managed model endpoint must be HTTP(S) without credentials', 'INVALID_CHATCODE_CONFIG')\n }\n for (const [key, value] of Object.entries(runtimeQuery())) url.searchParams.set(key, value)\n diagnostic?.(`chatcode-config: CodingPlan request GET ${url.href}`)\n let response: Response\n try {\n response = await fetch(url, { headers: catalogHeaders(authorization), signal: AbortSignal.timeout(timeoutMs) })\n } catch (error) {\n diagnostic?.(`chatcode-config: CodingPlan request failed before a response (${error instanceof Error ? error.message : String(error)})`)\n throw new LlmError('chatcode-config: managed model catalog is unavailable', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n }\n let body: unknown\n try {\n body = await response.json()\n diagnostic?.(`chatcode-config: CodingPlan response status=${response.status} body=${diagnosticBody(body)}`)\n } catch {\n diagnostic?.(`chatcode-config: CodingPlan response status=${response.status} body=<invalid JSON>`)\n throw new LlmError('chatcode-config: managed model catalog returned invalid JSON', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n if (!response.ok) throw new LlmError('chatcode-config: managed model catalog request failed', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n const top = record(body)\n const data = top === undefined ? undefined : record(top.data)\n const rows = data === undefined ? undefined : data.models\n if (top?.code !== '00000000' || !Array.isArray(rows)) {\n throw new LlmError('chatcode-config: managed model catalog returned an invalid response', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const models = rows.flatMap(row => {\n const item = record(row)\n if (item === undefined) return []\n const logicalModelId = string(item.logicalModelId)\n if (logicalModelId === undefined || logicalModelId.trim() === '') return []\n const parsed: RuntimeModel = {\n logicalModelId,\n displayName: string(item.displayName) ?? logicalModelId,\n }\n const description = string(item.description)\n const protocol = string(item.protocol)\n const provider = string(item.provider)\n const baseUrl = string(item.baseUrl)\n const providerModelId = string(item.providerModelId)\n const apiKey = string(item.apiKey)\n const maxToken = positive(item.maxToken)\n const contextWindow = positive(item.contextWindow)\n if (description !== undefined) parsed.description = description\n if (protocol !== undefined) parsed.protocol = protocol\n if (provider !== undefined) parsed.provider = provider\n if (baseUrl !== undefined) parsed.baseUrl = baseUrl\n if (providerModelId !== undefined) parsed.providerModelId = providerModelId\n if (apiKey !== undefined) parsed.apiKey = apiKey\n if (maxToken !== undefined) parsed.maxToken = maxToken\n if (contextWindow !== undefined) parsed.contextWindow = contextWindow\n return [parsed]\n })\n diagnostic?.(`chatcode-config: CodingPlan parsed ${String(rows.length)} response rows into ${String(models.length)} model records`)\n return models\n}\n\n/** Fetch the public MAAS catalog. It intentionally contains no endpoint or credential fields. */\nasync function fetchMaasCatalog(\n endpoint: string,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n): Promise<readonly MaasCatalogModel[]> {\n let url: URL\n try { url = new URL(endpoint) } catch {\n throw new LlmError('chatcode-config: MAAS model endpoint is invalid', 'INVALID_CHATCODE_CONFIG')\n }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) {\n throw new LlmError('chatcode-config: MAAS model endpoint must be HTTP(S) without credentials', 'INVALID_CHATCODE_CONFIG')\n }\n let response: Response\n try {\n response = await fetch(url, { headers: catalogHeaders(authorization, true), signal: AbortSignal.timeout(timeoutMs) })\n } catch {\n throw new LlmError('chatcode-config: MAAS model catalog is unavailable', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n }\n if (!response.ok) throw new LlmError('chatcode-config: MAAS model catalog request failed', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n let body: unknown\n try { body = await response.json() } catch {\n throw new LlmError('chatcode-config: MAAS model catalog returned invalid JSON', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const top = record(body)\n if (top?.code !== 200 || !Array.isArray(top.data)) {\n throw new LlmError('chatcode-config: MAAS model catalog returned an invalid response', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n return top.data.flatMap(row => {\n const item = record(row)\n const id = positive(item?.id)\n const logicalModelId = string(item?.logicalModelId)?.trim()\n if (id === undefined || logicalModelId === undefined || logicalModelId === '') return []\n const parsed: MaasCatalogModel = {\n id,\n logicalModelId,\n displayName: string(item?.displayName)?.trim() || logicalModelId,\n }\n const description = string(item?.description)\n const protocol = string(item?.protocol)\n const model = string(item?.model)\n const maxTokens = positive(item?.maxTokens)\n const contextWindow = positive(item?.contextWindow)\n if (description !== undefined) parsed.description = description\n if (protocol !== undefined) parsed.protocol = protocol\n if (model !== undefined) parsed.model = model\n if (maxTokens !== undefined) parsed.maxTokens = maxTokens\n if (contextWindow !== undefined) parsed.contextWindow = contextWindow\n return [parsed]\n })\n}\n\nfunction maasRuntimeUrl(catalogEndpoint: string, id: number): URL {\n let url: URL\n try { url = new URL(catalogEndpoint) } catch {\n throw new LlmError('chatcode-config: MAAS model endpoint is invalid', 'INVALID_CHATCODE_CONFIG')\n }\n const path = url.pathname.replace(/\\/+$/, '')\n if (!path.endsWith('/maas-models')) {\n throw new LlmError('chatcode-config: MAAS endpoint must end with /maas-models', 'INVALID_CHATCODE_CONFIG')\n }\n url.pathname = `${path}/${String(id)}/runtime-config`\n url.search = ''\n return url\n}\n\n/** Fetch one selected MAAS model's private runtime configuration. */\nasync function fetchMaasRuntime(\n endpoint: string,\n catalog: MaasCatalogModel,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n): Promise<RuntimeModel | undefined> {\n const url = maasRuntimeUrl(endpoint, catalog.id)\n let response: Response\n try {\n response = await fetch(url, { headers: catalogHeaders(authorization, true), signal: AbortSignal.timeout(timeoutMs) })\n } catch {\n throw new LlmError('chatcode-config: MAAS runtime configuration is unavailable', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n }\n if (!response.ok) throw new LlmError('chatcode-config: MAAS runtime configuration request failed', 'MANAGED_MODEL_CATALOG_UNAVAILABLE')\n let body: unknown\n try { body = await response.json() } catch {\n throw new LlmError('chatcode-config: MAAS runtime configuration returned invalid JSON', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const top = record(body)\n const data = top === undefined ? undefined : record(top.data)\n // The runtime resource is addressed by the catalog ID. Some gateways return\n // only private connection fields here, so an omitted `id` is valid; if an ID\n // is supplied it must still agree with the requested catalog row.\n const runtimeId = positive(data?.id)\n if (top?.code !== 200 || data === undefined || (runtimeId !== undefined && runtimeId !== catalog.id)) {\n throw new LlmError('chatcode-config: MAAS runtime configuration returned an invalid response', 'MANAGED_MODEL_CATALOG_INVALID')\n }\n const logicalModelId = string(data.logicalModelId)?.trim() || catalog.logicalModelId\n const providerModelId = string(data.model)?.trim() || catalog.model?.trim()\n const baseUrl = string(data.baseUrl)\n if (logicalModelId === undefined || logicalModelId === '' || providerModelId === undefined || providerModelId === '' || baseUrl === undefined) return undefined\n const parsed: RuntimeModel = {\n logicalModelId,\n displayName: string(data.displayName)?.trim() || catalog.displayName,\n baseUrl,\n providerModelId,\n }\n const description = string(data.description) ?? catalog.description\n const protocol = string(data.protocol) ?? catalog.protocol\n const apiKey = string(data.apiKey)\n const maxToken = positive(data.maxTokens) ?? catalog.maxTokens\n const contextWindow = positive(data.contextWindow) ?? catalog.contextWindow\n if (description !== undefined) parsed.description = description\n if (protocol !== undefined) parsed.protocol = protocol\n if (apiKey !== undefined) parsed.apiKey = apiKey\n if (maxToken !== undefined) parsed.maxToken = maxToken\n if (contextWindow !== undefined) parsed.contextWindow = contextWindow\n return parsed\n}\n\n/** Resolve every public MAAS entry through its private runtime endpoint before publishing it as selectable. */\nexport async function fetchMaasRuntimeModels(\n endpoint: string,\n timeoutMs: number,\n authorization?: ManagedCatalogAuthorization,\n): Promise<readonly RuntimeModel[]> {\n const catalog = await fetchMaasCatalog(endpoint, timeoutMs, authorization)\n const loaded = await Promise.all(catalog.map(async item => {\n try { return await fetchMaasRuntime(endpoint, item, timeoutMs, authorization) } catch (error) {\n if (error instanceof LlmError) return undefined\n throw error\n }\n }))\n return loaded.flatMap(model => model === undefined ? [] : [model])\n}\n\n/** Translate runnable managed entries into detached pi-ai routes. Incomplete public metadata is deliberately not selectable. */\nexport function resolveManagedSource(models: readonly RuntimeModel[], group: string, config: Config): ChatCodeSource {\n const profiles: Record<string, PiAiProviderProfile> = {}\n const auth = new Map<string, PiAiRequestAuth>()\n const apiKeys = new Map<string, string>()\n const selections = new Map<string, ChatCodeModelSelection>()\n for (const entry of models) {\n const protocol = protocolOf(entry)\n const baseURL = entry.baseUrl === undefined ? undefined : endpointOf(entry.baseUrl)\n const providerModelId = entry.providerModelId?.trim()\n // A row such as the documented DeepSeek-V3 public descriptor is display\n // metadata only: without protocol, endpoint and provider model id it cannot\n // make a safe provider request, so it never becomes a broken selector item.\n if (protocol === undefined || baseURL === undefined || providerModelId === undefined || providerModelId === '') continue\n const selection = entry.logicalModelId.trim()\n if (selection === '' || selections.has(selection)) continue\n const route = `managed-${group}-${createHash('sha256').update(JSON.stringify([protocol, baseURL, providerModelId, selection])).digest('hex').slice(0, 20)}`\n profiles[route] = {\n displayName: entry.displayName.trim() || selection,\n api: protocol,\n baseURL,\n models: [{\n id: providerModelId,\n name: entry.displayName.trim() || selection,\n contextWindow: entry.contextWindow ?? entry.maxToken ?? config.defaultContextWindow,\n maxTokens: entry.maxToken ?? config.defaultMaxTokens,\n }],\n ...protocol === 'openai-completions' ? {\n compat: { maxTokensField: 'max_tokens', supportsDeveloperRole: false },\n // The OpenAI SDK defaults Accept to application/json even for streaming\n // calls. ChatCode's forwarding gateway enforces content negotiation and\n // otherwise returns a JSON business error with HTTP 200, which the SSE\n // parser can only report later as a missing finish_reason.\n headers: { Accept: 'text/event-stream' },\n } : {},\n ...config.retryPolicy === undefined ? {} : { retryPolicy: config.retryPolicy },\n }\n const apiKey = requestApiKey(entry.apiKey)\n auth.set(route, requestAuth(protocol, apiKey))\n if (apiKey !== undefined) apiKeys.set(route, apiKey)\n selections.set(selection, { route, model: providerModelId })\n }\n return { profiles: resolveProfiles(profiles), auth, apiKeys, selections }\n}\n","/** Durable file-per-record outbox for generated-code statistics. */\nimport { randomUUID } from 'node:crypto'\nimport { mkdir, open, readdir, readFile, rename, unlink } from 'node:fs/promises'\nimport { basename, join } from 'node:path'\n\ninterface OutboxRecord {\n version: 1\n id: string\n createdAt: number\n codes: string[]\n}\n\n/** One ordered code batch and the files acknowledged with it. */\nexport interface CodeOutboxBatch {\n files: string[]\n codes: string[]\n}\n\n/** Persist generated code until a backend acknowledgement permits deletion. */\nexport class CodeOutbox {\n constructor(private readonly directory: string) {}\n\n /** Atomically append non-empty code strings to the outbox. */\n async enqueue(codes: readonly string[]): Promise<void> {\n const kept = codes.map(code => code.trim()).filter(Boolean)\n if (kept.length === 0) return\n await mkdir(this.directory, { recursive: true, mode: 0o700 })\n for (const code of kept) await this.writeRecord(code)\n }\n\n private async writeRecord(code: string): Promise<void> {\n const id = randomUUID()\n const record: OutboxRecord = { version: 1, id, createdAt: Date.now(), codes: [code] }\n const target = join(this.directory, `${String(record.createdAt).padStart(13, '0')}-${id}.json`)\n const temporary = `${target}.${randomUUID()}.tmp`\n const handle = await open(temporary, 'wx', 0o600)\n try {\n await handle.writeFile(`${JSON.stringify(record)}\\n`, 'utf8')\n await handle.sync()\n } finally {\n await handle.close()\n }\n await rename(temporary, target)\n }\n\n /** Read the oldest complete records within both configured batch limits. */\n async readBatch(maxItems: number, maxChars: number): Promise<CodeOutboxBatch> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 })\n const entries = (await readdir(this.directory, { withFileTypes: true }))\n .filter(entry => entry.isFile() && entry.name.endsWith('.json'))\n .map(entry => entry.name)\n .sort()\n const batch: CodeOutboxBatch = { files: [], codes: [] }\n let chars = 0\n for (const name of entries) {\n const path = join(this.directory, name)\n const record = await this.readRecord(path)\n if (!record) continue\n const nextChars = record.codes.reduce((sum, code) => sum + code.length, 0)\n if (batch.codes.length > 0 && (batch.codes.length + record.codes.length > maxItems || chars + nextChars > maxChars)) break\n batch.files.push(path)\n batch.codes.push(...record.codes)\n chars += nextChars\n if (batch.codes.length >= maxItems || chars >= maxChars) break\n }\n return batch\n }\n\n /** Delete only records included in a backend-acknowledged batch. */\n async acknowledge(files: readonly string[]): Promise<void> {\n for (const file of files) {\n try {\n await unlink(file)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n }\n }\n\n private async readRecord(path: string): Promise<OutboxRecord | undefined> {\n try {\n const value = JSON.parse(await readFile(path, 'utf8')) as unknown\n if (isRecord(value)\n && value.version === 1\n && typeof value.id === 'string'\n && Number.isSafeInteger(value.createdAt)\n && Array.isArray(value.codes)\n && value.codes.length > 0\n && value.codes.every(code => typeof code === 'string' && code.trim().length > 0)) {\n return value as unknown as OutboxRecord\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined\n }\n const invalidDirectory = join(this.directory, 'invalid')\n await mkdir(invalidDirectory, { recursive: true, mode: 0o700 })\n await rename(path, join(invalidDirectory, `${basename(path)}.${randomUUID()}.invalid`))\n return undefined\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/** Pure extraction of code that is safe to count as AI-generated output. */\nimport { extname } from 'node:path'\n\n/** Code attributed to one successful model response or mutating tool call. */\nexport interface ExtractedCode {\n /** Code text without surrounding Markdown fences. */\n code: string\n /** Optional Markdown language identifier. */\n language?: string\n /** Optional path supplied to a first-party file mutation tool. */\n filePath?: string\n}\n\nconst EXCLUDED_FENCE_LABELS = new Set([\n 'text', 'plaintext', 'plain', 'output', 'result', 'log', 'example', 'sample',\n 'demo', 'note', 'notice', 'warning', 'error', 'exception', 'stacktrace', 'trace',\n])\n\n/** Extract reportable fenced code blocks from assistant-visible Markdown. */\nexport function extractMarkdownCode(markdown: string): ExtractedCode[] {\n const result: ExtractedCode[] = []\n const pattern = /(?:^|\\n)(`{3,}|~{3,})[ \\t]*([^\\r\\n]*)\\r?\\n([\\s\\S]*?)\\r?\\n?\\1(?=\\r?\\n|$)/g\n for (const match of markdown.matchAll(pattern)) {\n const label = match[2]?.trim().split(/[ \\t]/, 1)[0]?.toLowerCase() ?? ''\n const code = match[3]?.trim()\n if (!code || EXCLUDED_FENCE_LABELS.has(label) || (!label && looksLikeConsoleResult(code))) continue\n result.push({ code, ...(label ? { language: label } : {}) })\n }\n return result\n}\n\n/** Extract code from one successful first-party mutation request. */\nexport function extractMutationCode(name: string, args: unknown): ExtractedCode | undefined {\n if (!isRecord(args)) return undefined\n if (name === 'write') {\n return codeAt(args, 'file_path', 'content')\n }\n if (name === 'edit') {\n if (typeof args.old_string !== 'string' || args.old_string.length === 0) return undefined\n return codeAt(args, 'file_path', 'new_string')\n }\n if (name !== 'str_replace_editor') return undefined\n if (args.command === 'create') return codeAt(args, 'path', 'file_text')\n if (args.command === 'str_replace') {\n if (typeof args.old_str !== 'string' || args.old_str.length === 0) return undefined\n return codeAt(args, 'path', 'new_str')\n }\n if (args.command === 'insert' && Number.isInteger(args.insert_line)) {\n return codeAt(args, 'path', 'new_str')\n }\n return undefined\n}\n\n/** Parse model-produced JSON arguments before mutation extraction. */\nexport function extractMutationCodeFromJson(name: string, raw: string): ExtractedCode | undefined {\n try {\n return extractMutationCode(name, JSON.parse(raw) as unknown)\n } catch {\n return undefined\n }\n}\n\n/** Infer a stable Markdown language name from a file path. */\nexport function inferLanguage(filePath: string): string | undefined {\n const extension = extname(filePath).slice(1).toLowerCase()\n if (!extension) return undefined\n const aliases: Readonly<Record<string, string>> = {\n cjs: 'javascript', htm: 'html', js: 'javascript', mjs: 'javascript',\n py: 'python', ps1: 'powershell', sh: 'bash', ts: 'typescript', yml: 'yaml',\n }\n return aliases[extension] ?? extension\n}\n\nfunction codeAt(args: Readonly<Record<string, unknown>>, pathKey: string, codeKey: string): ExtractedCode | undefined {\n const code = args[codeKey]\n if (typeof code !== 'string' || code.trim().length === 0) return undefined\n const filePath = args[pathKey]\n if (typeof filePath !== 'string' || filePath.trim().length === 0) return { code: code.trim() }\n const language = inferLanguage(filePath)\n return { code: code.trim(), filePath, ...(language ? { language } : {}) }\n}\n\nfunction looksLikeConsoleResult(code: string): boolean {\n const lines = code.split('\\n')\n if (lines.length <= 3) return false\n const resultLines = lines.filter(line => /^[A-Za-z_]\\w*\\(\\d+\\)\\s*=/.test(line.trim()))\n return resultLines.length > lines.length * 0.5\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/** Backend payloads and pure Session-message projections. */\nimport type { ContentBlock, Message, TokenUsage } from '@deepseek-ai/dsh-llm/types'\nimport type { Session } from '@deepseek-ai/dsh-session'\nimport type { ModelKindRule } from '../config.ts'\n\n/** Conversation metadata accepted by the Wanma synchronization endpoint. */\nexport interface ConversationMeta {\n sessionId: string\n userEmail: string\n projectPath: string\n title?: string\n modelName: string\n startTime: string\n}\n\n/** One synchronized conversation message. */\nexport interface ConversationMessagePayload {\n uuid: string\n parentUuid?: string\n sessionId: string\n role: 'user' | 'assistant' | 'system' | 'tool'\n contentType: 'text' | 'think' | 'tool_use' | 'tool_result' | 'image'\n content: string\n toolName?: string\n toolInput?: string\n userEmail?: string\n modelName?: string\n modelKind?: number\n tokenUsage?: {\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheCreationTokens: number\n }\n usageTime?: string\n timestamp: string\n turnIndex: number\n}\n\n/** Request body for conversation synchronization. */\nexport interface ConversationSyncPayload {\n conversation: ConversationMeta\n messages: ConversationMessagePayload[]\n isComplete: boolean\n}\n\n/** Request body for one ChatCode message record. */\nexport interface ChatMessagePayload {\n chatId: string\n questionText: string\n answerText: string\n pluginVersion: string\n tokensIn: number\n tokensOut: number\n modelKind: number\n modelName: string\n baseUrl: string\n}\n\n/** Actual model identity and service address used for operations reporting. */\nexport interface ModelReport {\n modelName: string\n baseUrl: string\n}\n\n/** Resolve one public ChatCode CLI model selection to its private runtime identity. */\nexport type ModelReportResolver = (provider: string, model: string) => ModelReport\n\n/** Return the first explicit model-kind override, if one matches. */\nexport function matchModelKindRule(provider: string, model: string, rules: readonly ModelKindRule[]): number | undefined {\n return rules.find(rule => (rule.provider === undefined || rule.provider === provider)\n && (rule.model === undefined || rule.model === model))?.kind\n}\n\n/** Resolve the first exact model-kind rule, with category 2 as the fallback. */\nexport function resolveModelKind(provider: string, model: string, rules: readonly ModelKindRule[]): number {\n return matchModelKindRule(provider, model, rules) ?? 2\n}\n\n/** Build the immutable conversation fields for one Session. */\nexport function conversationMeta(\n session: Session,\n userEmail: string,\n title: string | undefined,\n modelName: string,\n): ConversationMeta {\n return {\n sessionId: String(session.id),\n userEmail,\n projectPath: session.header.cwd ?? '',\n ...(title ? { title } : {}),\n modelName,\n startTime: new Date(session.header.createdAt).toISOString(),\n }\n}\n\n/** Project one human or assistant message into a single backend row. */\nexport function conversationMessage(\n sessionId: string,\n message: Message,\n timestamp: number,\n turn: number,\n usage?: TokenUsage,\n): ConversationMessagePayload | undefined {\n const projected = projectBlocks(message.content)\n if (!projected) return undefined\n const model = message.source.kind === 'model' ? message.source.model : undefined\n return {\n uuid: String(message.id),\n sessionId,\n role: message.role === 'assistant' ? 'assistant' : message.role === 'system' ? 'system' : 'user',\n contentType: projected.contentType,\n content: projected.content,\n ...(model ? { modelName: model } : {}),\n ...(usage ? { tokenUsage: {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cacheReadTokens: usage.cacheReadTokens ?? 0,\n cacheCreationTokens: usage.cacheWriteTokens ?? 0,\n } } : {}),\n usageTime: new Date(timestamp).toISOString(),\n timestamp: new Date(timestamp).toISOString(),\n turnIndex: turn,\n }\n}\n\n/** Project one durable tool call into a stable conversation row. */\nexport function toolCallMessage(\n sessionId: string,\n callId: string,\n name: string,\n args: string,\n timestamp: number,\n turn: number,\n): ConversationMessagePayload {\n return {\n uuid: callId,\n sessionId,\n role: 'assistant',\n contentType: 'tool_use',\n content: name,\n toolName: name,\n toolInput: args,\n usageTime: new Date(timestamp).toISOString(),\n timestamp: new Date(timestamp).toISOString(),\n turnIndex: turn,\n }\n}\n\n/** Project one durable tool result into a stable conversation row. */\nexport function toolResultMessage(\n sessionId: string,\n message: Message,\n name: string,\n timestamp: number,\n turn: number,\n): ConversationMessagePayload {\n return {\n uuid: String(message.id),\n sessionId,\n role: 'tool',\n contentType: 'tool_result',\n content: textOfBlocks(message.content),\n toolName: name,\n usageTime: new Date(timestamp).toISOString(),\n timestamp: new Date(timestamp).toISOString(),\n turnIndex: turn,\n }\n}\n\n/** Return assistant-visible text without reasoning or tool-call arguments. */\nexport function visibleText(message: Message): string {\n return message.content.filter(block => block.type === 'text').map(block => block.text).join('\\n').trim()\n}\n\n/** Return direct-user text suitable for a title or question. */\nexport function userText(message: Message): string {\n return message.content.map(block => {\n if (block.type === 'text') return block.text\n if (block.type === 'image') return '[image]'\n if (block.type === 'file') return `[file: ${block.attachment.name}]`\n return ''\n }).filter(Boolean).join('\\n').trim()\n}\n\n/** Return a bounded, one-line tool result summary. */\nexport function toolSummary(message: Message, maxChars = 300): string {\n const text = textOfBlocks(message.content).replace(/[\\r\\n]+/g, ' ').trim()\n return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text\n}\n\nfunction projectBlocks(blocks: readonly ContentBlock[]): { contentType: ConversationMessagePayload['contentType']; content: string } | undefined {\n const kept = blocks.filter(block => block.type !== 'tool-call')\n if (kept.length === 0) return undefined\n if (kept.length === 1) {\n const block = kept[0]!\n if (block.type === 'text') return { contentType: 'text', content: block.text }\n if (block.type === 'reasoning') return { contentType: 'think', content: block.text }\n if (block.type === 'image') return { contentType: 'image', content: '[image]' }\n }\n return { contentType: 'text', content: JSON.stringify(kept.map(serializableBlock)) }\n}\n\nfunction serializableBlock(block: ContentBlock): unknown {\n if (block.type === 'image') return { type: 'image', name: block.attachment.name }\n if (block.type === 'file') return { type: 'file', name: block.attachment.name }\n if (block.type === 'tool-result') return { type: 'tool-result', toolCallId: block.toolCallId, content: block.content.map(serializableBlock), isError: block.isError === true }\n return block\n}\n\nfunction textOfBlocks(blocks: readonly ContentBlock[]): string {\n return blocks.map(block => {\n if (block.type === 'text' || block.type === 'reasoning') return block.text\n if (block.type === 'tool-result') return textOfBlocks(block.content)\n if (block.type === 'image') return '[image]'\n if (block.type === 'file') return `[file: ${block.attachment.name}]`\n return `[tool: ${block.name}]`\n }).join('\\n').trim()\n}\n","/** Session-scoped event projection into the three ChatCode reporting sinks. */\nimport type { ContentBlock } from '@deepseek-ai/dsh-llm/types'\nimport type { Session } from '@deepseek-ai/dsh-session'\nimport type { SessionEvent } from '@deepseek-ai/dsh-session/types'\nimport type {} from '@deepseek-ai/dsh-tools/types'\nimport { extractMarkdownCode, extractMutationCode, extractMutationCodeFromJson, type ExtractedCode } from './code.ts'\nimport type { ReportingConfig } from '../config.ts'\nimport { CodeOutbox } from './outbox.ts'\nimport {\n conversationMessage,\n conversationMeta,\n matchModelKindRule,\n toolCallMessage,\n toolResultMessage,\n toolSummary,\n userText,\n visibleText,\n type ChatMessagePayload,\n type ConversationMessagePayload,\n type ConversationSyncPayload,\n type ModelReport,\n type ModelReportResolver,\n} from './payloads.ts'\nimport type { ReportingTransport } from './transport.ts'\n\nconst PLUGIN_VERSION = '0.1.0'\n\ninterface Logger {\n warn(message: string): void\n}\n\ninterface ToolCallState {\n name: string\n code: ExtractedCode | undefined\n}\n\ninterface TurnState {\n turn: number\n pendingQuestion: string | undefined\n}\n\ninterface PendingModelResponse {\n responseId: string\n turn: number\n provider: string\n model: string\n questionText: string\n answerText: string\n tokensIn: number\n tokensOut: number\n report: ModelReport\n pendingToolIds: Set<string>\n codeRecords: { name: string; summary: string; code: ExtractedCode }[]\n}\n\ninterface ReporterSessionState {\n tail: Promise<void>\n topLevel: boolean\n title: string | undefined\n provider: string\n model: string\n chatId: string | undefined\n currentTurn: TurnState | undefined\n toolCalls: Map<string, ToolCallState>\n pendingResponses: Map<string, PendingModelResponse>\n responseByTool: Map<string, string>\n reportedResponses: Set<string>\n warned: Set<string>\n}\n\n/** Web-owned durable selection event consumed without requiring the Web package at runtime. */\ninterface ModelSelectionEvent {\n type: 'model/selection'\n seq: SessionEvent['seq']\n time: number\n data: {\n provider: string\n model: string\n }\n}\n\ntype ReportingSessionEvent = SessionEvent | ModelSelectionEvent\n\n/** Coordinates the durable code outbox without blocking Session event callbacks. */\nexport class CodeOutboxWorker {\n private running: Promise<void> | undefined\n private timer: ReturnType<typeof setTimeout> | undefined\n private stopped = false\n\n constructor(\n private readonly outbox: CodeOutbox,\n private readonly transport: ReportingTransport,\n private readonly maxItems: number,\n private readonly maxChars: number,\n private readonly retryDelayMs: number,\n private readonly logger: Logger,\n ) {}\n\n /** Persist code and trigger asynchronous delivery. */\n async enqueue(codes: readonly string[]): Promise<void> {\n await this.outbox.enqueue(codes)\n this.kick()\n }\n\n /** Resume files left by an earlier process. */\n start(): void {\n this.kick()\n }\n\n /** Wait for the active attempt and trigger one immediate attempt if idle. */\n async flushNow(): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = undefined\n }\n this.kick()\n await this.running\n }\n\n /** Stop retry scheduling after one bounded final attempt. */\n async stop(): Promise<void> {\n if (this.timer) clearTimeout(this.timer)\n this.timer = undefined\n await this.flushNow()\n if (this.timer) clearTimeout(this.timer)\n this.timer = undefined\n this.stopped = true\n }\n\n private kick(): void {\n if (this.stopped || this.running) return\n this.running = this.flushLoop().finally(() => { this.running = undefined })\n }\n\n private async flushLoop(): Promise<void> {\n try {\n while (true) {\n const batch = await this.outbox.readBatch(this.maxItems, this.maxChars)\n if (batch.files.length === 0) return\n await this.transport.saveCodes(batch.codes)\n await this.outbox.acknowledge(batch.files)\n }\n } catch (error) {\n this.logger.warn(`chatcode-reporting: code outbox retained after delivery failure: ${errorMessage(error)}`)\n if (!this.stopped && !this.timer) {\n this.timer = setTimeout(() => {\n this.timer = undefined\n this.kick()\n }, this.retryDelayMs)\n this.timer.unref?.()\n }\n }\n }\n}\n\n/** Project committed Session events while isolating state and ordering by Session. */\nexport class ChatCodeReporter {\n private readonly sessions = new WeakMap<Session, ReporterSessionState>()\n private readonly active = new Set<ReporterSessionState>()\n\n constructor(\n private readonly config: ReportingConfig,\n private readonly transport: ReportingTransport,\n private readonly codeWorker: CodeOutboxWorker,\n private readonly logger: Logger,\n private readonly resolveModelReport: ModelReportResolver = (_provider, model) => ({ modelName: model, baseUrl: '' }),\n ) {}\n\n /** Register Session-local state without starting network work. */\n created(session: Session): void {\n this.state(session)\n }\n\n /**\n * Seed a new Session with the Agent's selected route before its first messages.\n * @param session - Session owned by the newly published Agent.\n * @param provider - selected provider route, when configured.\n * @param model - selected provider-owned model, when configured.\n */\n seedModelRoute(session: Session, provider: string | undefined, model: string | undefined): void {\n if (provider === undefined || model === undefined) return\n const state = this.state(session)\n if (state.provider !== '' || state.model !== '') return\n state.provider = provider\n state.model = model\n }\n\n /** Enqueue one committed event and return immediately. */\n observe(session: Session, event: ReportingSessionEvent): void {\n const state = this.state(session)\n state.tail = state.tail.then(\n () => this.handle(session, state, event),\n () => this.handle(session, state, event),\n ).catch(error => this.warnOnce(state, 'event', error))\n }\n\n /** Wait until all work already queued for one Session has settled. */\n async flush(session: Session): Promise<void> {\n const state = this.sessions.get(session)\n if (state) await state.tail\n if (this.config.codeSave) await this.codeWorker.flushNow()\n }\n\n /** Drain and forget one disposed Session. */\n async disposed(session: Session): Promise<void> {\n const state = this.sessions.get(session)\n if (!state) return\n await state.tail\n await this.finalizePendingResponses(state)\n if (this.config.codeSave) await this.codeWorker.flushNow()\n this.sessions.delete(session)\n this.active.delete(state)\n }\n\n /** Drain every active Session and stop code retry scheduling. */\n async shutdown(): Promise<void> {\n await Promise.allSettled([...this.active].map(state => state.tail))\n await Promise.allSettled([...this.active].map(state => this.finalizePendingResponses(state)))\n if (this.config.codeSave) await this.codeWorker.stop()\n }\n\n private state(session: Session): ReporterSessionState {\n const current = this.sessions.get(session)\n if (current) return current\n const header = session.requestHeader()\n const created: ReporterSessionState = {\n tail: Promise.resolve(),\n topLevel: session.header.origin !== 'subagent',\n title: undefined,\n provider: header?.config.provider ?? '',\n model: header?.config.model ?? '',\n chatId: undefined,\n currentTurn: undefined,\n toolCalls: new Map(),\n pendingResponses: new Map(),\n responseByTool: new Map(),\n reportedResponses: new Set(),\n warned: new Set(),\n }\n this.sessions.set(session, created)\n this.active.add(created)\n return created\n }\n\n private async handle(session: Session, state: ReporterSessionState, event: ReportingSessionEvent): Promise<void> {\n if (event.type === 'turn/start') {\n state.currentTurn = { turn: event.data.turn, pendingQuestion: undefined }\n return\n }\n switch (event.type) {\n case 'model/selection':\n state.provider = event.data.provider\n state.model = event.data.model\n return\n case 'request/header':\n state.provider = event.data.header.config.provider\n state.model = event.data.header.config.model\n return\n case 'user/message':\n if (event.data.source.kind !== 'user') return\n await this.onUser(session, state, event)\n return\n case 'system/message':\n await this.onSystem(session, state, event)\n return\n case 'assistant/message':\n await this.onAssistant(session, state, event)\n return\n case 'tool/call':\n await this.onToolCall(session, state, event)\n return\n case 'tool/result':\n await this.onToolResult(session, state, event)\n return\n case 'tool/ptc-dispatch-start':\n await this.onNestedToolCall(session, state, event)\n return\n case 'tool/ptc-dispatch':\n await this.onNestedToolResult(session, state, event)\n return\n case 'turn/end':\n await this.onTurnEnd(session, state, event)\n return\n default:\n return\n }\n }\n\n private async onUser(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'user/message' }>): Promise<void> {\n const text = userText(event.data)\n if (!text) return\n state.title ??= text.slice(0, 200)\n const turn = state.currentTurn\n if (turn) turn.pendingQuestion = text\n if (this.shouldSync(state)) {\n const message = conversationMessage(String(session.id), event.data, event.time, state.currentTurn?.turn ?? 0)\n if (message) await this.sync(session, state, [message], false)\n }\n }\n\n private async onAssistant(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'assistant/message' }>): Promise<void> {\n state.provider = event.data.message.source.provider\n state.model = event.data.message.source.model\n const text = visibleText(event.data.message)\n if (this.config.codeSave && text) {\n const codes = extractMarkdownCode(text).map(item => item.code)\n if (codes.length > 0) await this.codeWorker.enqueue(codes)\n }\n if (this.shouldSync(state)) {\n const message = conversationMessage(String(session.id), event.data.message, event.time, event.data.turn, event.data.usage)\n if (message) await this.sync(session, state, [message], false)\n }\n if (!state.topLevel || !this.config.chatCodeSession || event.data.usage === undefined) return\n const { inputTokens, outputTokens } = event.data.usage\n if (inputTokens <= 0 && outputTokens <= 0) return\n const responseId = String(event.data.message.id)\n if (state.reportedResponses.has(responseId) || state.pendingResponses.has(responseId)) return\n const pendingToolIds = new Set(event.data.message.content.flatMap(block => block.type === 'tool-call' ? [String(block.id)] : []))\n const report = this.resolveModelReport(state.provider, state.model)\n const pending: PendingModelResponse = {\n responseId,\n turn: event.data.turn,\n provider: state.provider,\n model: state.model,\n questionText: state.currentTurn?.pendingQuestion ?? '',\n answerText: text,\n tokensIn: inputTokens,\n tokensOut: outputTokens,\n report,\n pendingToolIds,\n codeRecords: [],\n }\n if (state.currentTurn?.pendingQuestion !== undefined) state.currentTurn.pendingQuestion = undefined\n state.pendingResponses.set(responseId, pending)\n for (const callId of pendingToolIds) state.responseByTool.set(callId, responseId)\n await this.finishResponseIfReady(state, pending)\n }\n\n private async onSystem(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'system/message' }>): Promise<void> {\n if (!this.shouldSync(state)) return\n const message = conversationMessage(String(session.id), event.data.message, event.time, event.data.turn)\n if (message) await this.sync(session, state, [message], false)\n }\n\n private async onToolCall(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/call' }>): Promise<void> {\n const callId = String(event.data.callId)\n state.toolCalls.set(callId, {\n name: event.data.name,\n code: extractMutationCodeFromJson(event.data.name, event.data.arguments),\n })\n if (this.shouldSync(state)) {\n await this.sync(session, state, [toolCallMessage(String(session.id), callId, event.data.name, event.data.arguments, event.time, event.data.turn)], false)\n }\n }\n\n private async onToolResult(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/result' }>): Promise<void> {\n const callId = String(event.data.message.source.callId)\n const call = state.toolCalls.get(callId)\n const failed = event.data.error !== undefined || event.data.message.content.some(\n block => block.type === 'tool-result' && block.isError === true,\n )\n if (!failed && call?.code && this.config.codeSave) await this.codeWorker.enqueue([call.code.code])\n if (this.shouldSync(state)) {\n await this.sync(session, state, [toolResultMessage(String(session.id), event.data.message, call?.name ?? 'unknown', event.time, event.data.turn)], false)\n }\n await this.completeTool(state, callId, call?.name ?? 'unknown', failed, toolSummary(event.data.message), call?.code)\n }\n\n private async onNestedToolCall(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/ptc-dispatch-start' }>): Promise<void> {\n const callId = String(event.data.subCallId)\n state.toolCalls.set(callId, {\n name: event.data.name,\n code: extractMutationCode(event.data.name, event.data.arguments),\n })\n if (this.shouldSync(state)) {\n const raw = JSON.stringify(event.data.arguments)\n await this.sync(session, state, [toolCallMessage(String(session.id), callId, event.data.name, raw, event.time, state.currentTurn?.turn ?? 0)], false)\n }\n }\n\n private async onNestedToolResult(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'tool/ptc-dispatch' }>): Promise<void> {\n const callId = String(event.data.subCallId)\n const call = state.toolCalls.get(callId)\n if (!event.data.isError && call?.code && this.config.codeSave) await this.codeWorker.enqueue([call.code.code])\n const summary = summaryOfBlocks(event.data.content)\n if (this.shouldSync(state)) {\n const timestamp = new Date(event.time).toISOString()\n const message: ConversationMessagePayload = {\n uuid: `${callId}:result`, sessionId: String(session.id), role: 'tool', contentType: 'tool_result',\n content: summary, toolName: event.data.name, usageTime: timestamp, timestamp,\n turnIndex: state.currentTurn?.turn ?? 0,\n }\n await this.sync(session, state, [message], false)\n }\n if (!event.data.isError && call?.code) {\n const rootResponseId = state.responseByTool.get(String(event.data.rootCallId))\n const pending = rootResponseId === undefined ? undefined : state.pendingResponses.get(rootResponseId)\n if (pending !== undefined) pending.codeRecords.push({ name: event.data.name, summary, code: call.code })\n }\n }\n\n private async onTurnEnd(session: Session, state: ReporterSessionState, event: Extract<SessionEvent, { type: 'turn/end' }>): Promise<void> {\n if (this.shouldSync(state)) await this.sync(session, state, [], true)\n await this.finalizePendingResponses(state, event.data.turn)\n state.toolCalls.clear()\n state.currentTurn = undefined\n }\n\n private shouldSync(state: ReporterSessionState): boolean {\n return this.config.conversationSync && (state.topLevel || this.config.includeSubagentConversationSync)\n }\n\n private async sync(session: Session, state: ReporterSessionState, messages: ConversationMessagePayload[], isComplete: boolean): Promise<void> {\n await this.attempt(state, 'conversation-sync', async () => {\n const userEmail = await this.transport.identity()\n const conversationReport = this.resolveModelReport(state.provider, state.model)\n const decorated = await Promise.all(messages.map(async message => {\n const selectedModel = message.modelName ?? state.model\n const report = this.resolveModelReport(state.provider, selectedModel)\n return {\n ...message,\n userEmail,\n modelName: report.modelName,\n modelKind: await this.modelKind(state.provider, selectedModel, report.baseUrl),\n }\n }))\n const payload: ConversationSyncPayload = {\n conversation: conversationMeta(session, userEmail, state.title, conversationReport.modelName),\n messages: decorated,\n isComplete,\n }\n await this.transport.syncConversation(payload)\n })\n }\n\n private async completeTool(\n state: ReporterSessionState,\n callId: string,\n name: string,\n failed: boolean,\n summary: string,\n code?: ExtractedCode,\n ): Promise<void> {\n const responseId = state.responseByTool.get(callId)\n const pending = responseId === undefined ? undefined : state.pendingResponses.get(responseId)\n if (pending === undefined || !pending.pendingToolIds.delete(callId)) return\n state.responseByTool.delete(callId)\n if (!failed && code !== undefined) pending.codeRecords.push({ name, summary, code })\n await this.finishResponseIfReady(state, pending)\n }\n\n private async finishResponseIfReady(state: ReporterSessionState, pending: PendingModelResponse): Promise<void> {\n if (pending.pendingToolIds.size > 0) return\n const answerParts = pending.answerText.trim() ? [pending.answerText.trim()] : []\n for (const record of pending.codeRecords) answerParts.push(formatToolRecord(record.name, 'success', record.summary, record.code))\n if (answerParts.length === 0) answerParts.push('ChatCode CLI 模型响应(工具调用)')\n state.pendingResponses.delete(pending.responseId)\n state.reportedResponses.add(pending.responseId)\n for (const [callId, responseId] of state.responseByTool) {\n if (responseId === pending.responseId) state.responseByTool.delete(callId)\n }\n await this.addChat(state, {\n questionText: pending.questionText,\n answerText: answerParts.join('\\n\\n'),\n tokensIn: pending.tokensIn,\n tokensOut: pending.tokensOut,\n }, pending.provider, pending.model, pending.report, 'chat-message')\n }\n\n private async finalizePendingResponses(state: ReporterSessionState, turn?: number): Promise<void> {\n for (const pending of state.pendingResponses.values()) {\n if (turn !== undefined && pending.turn !== turn) continue\n pending.pendingToolIds.clear()\n await this.finishResponseIfReady(state, pending)\n }\n }\n\n private async addChat(\n state: ReporterSessionState,\n content: Pick<ChatMessagePayload, 'questionText' | 'answerText' | 'tokensIn' | 'tokensOut'>,\n provider: string,\n model: string,\n report: ModelReport,\n warningKey: string,\n ): Promise<void> {\n await this.attempt(state, warningKey, async () => {\n const modelKind = await this.modelKind(provider, model, report.baseUrl)\n state.chatId ??= await this.transport.createChat()\n await this.transport.addChatMessage({\n chatId: state.chatId,\n ...content,\n pluginVersion: PLUGIN_VERSION,\n modelKind,\n modelName: report.modelName,\n baseUrl: report.baseUrl,\n })\n })\n }\n\n private async modelKind(provider: string, model: string, baseUrl: string): Promise<number> {\n return matchModelKindRule(provider, model, this.config.modelKindRules) ?? this.transport.modelKind(baseUrl)\n }\n\n private async attempt(state: ReporterSessionState, key: string, action: () => Promise<void>): Promise<void> {\n try {\n await action()\n } catch (error) {\n this.warnOnce(state, key, error)\n }\n }\n\n private warnOnce(state: ReporterSessionState, key: string, error: unknown): void {\n if (state.warned.has(key)) return\n state.warned.add(key)\n this.logger.warn(`chatcode-reporting: ${key} failed: ${errorMessage(error)}`)\n }\n}\n\nfunction summaryOfBlocks(blocks: readonly ContentBlock[]): string {\n const text = blocks.map(block => {\n if (block.type === 'text' || block.type === 'reasoning') return block.text\n if (block.type === 'tool-result') return summaryOfBlocks(block.content)\n if (block.type === 'image') return '[image]'\n if (block.type === 'file') return `[file: ${block.attachment.name}]`\n return `[tool: ${block.name}]`\n }).join(' ').replace(/\\s+/g, ' ').trim()\n return text.length > 300 ? `${text.slice(0, 300)}…` : text\n}\n\nfunction formatToolRecord(name: string, status: 'success' | 'error', summary: string, code?: ExtractedCode): string {\n const lines = ['ChatCode CLI 工具执行记录', '', `- 工具:${oneLine(name)}`, `- 状态:${status}`]\n if (code?.filePath) lines.push(`- 文件:${oneLine(code.filePath)}`)\n if (summary) lines.push(`- 摘要:${oneLine(summary)}`)\n if (!code?.code) return lines.join('\\n')\n const fence = '`'.repeat(Math.max(3, longestBacktickRun(code.code) + 1))\n return `${lines.join('\\n')}\\n\\n${fence}${code.language ?? ''}\\n${code.code}\\n${fence}`\n}\n\nfunction oneLine(value: string): string {\n return value.replace(/[\\r\\n]+/g, ' ').trim()\n}\n\nfunction longestBacktickRun(value: string): number {\n let longest = 0\n for (const match of value.matchAll(/`+/g)) longest = Math.max(longest, match[0].length)\n return longest\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","/** ChatCode model-source classification by normalized runtime base URL. */\n\n/** Model categories accepted by ChatCode operations reporting. */\nexport type ChatCodeModelKind = 0 | 1 | 2 | 3\n\n/** URL sets loaded from ChatCode system configuration. */\nexport type ModelKindUrls = Readonly<Record<0 | 1 | 3, ReadonlySet<string>>>\n\n/** Create an empty model-source configuration whose fallback category is `2`. */\nexport function emptyModelKindUrls(): ModelKindUrls {\n return { 0: new Set(), 1: new Set(), 3: new Set() }\n}\n\n/**\n * Normalize configured and runtime model URLs for exact source classification.\n * @param value - A configured gateway root or complete model request URL.\n * @returns A credential-free, query-free URL without a known request suffix.\n */\nexport function normalizeModelBaseUrl(value: string): string {\n const trimmed = value.trim()\n if (!trimmed) return ''\n try {\n const url = new URL(trimmed)\n url.username = ''\n url.password = ''\n url.search = ''\n url.hash = ''\n url.protocol = url.protocol.toLowerCase()\n url.hostname = url.hostname.toLowerCase()\n let pathname = url.pathname.replace(/\\/+$/u, '')\n for (const suffix of ['/chat/completions', '/chat/completion', '/v1/messages']) {\n if (!pathname.toLowerCase().endsWith(suffix)) continue\n pathname = pathname.slice(0, -suffix.length).replace(/\\/+$/u, '')\n break\n }\n url.pathname = pathname || '/'\n return url.toString().replace(/\\/$/u, '')\n } catch {\n return trimmed.toLowerCase().replace(/\\/+$/u, '')\n }\n}\n\n/**\n * Parse the semicolon-separated value returned by one ChatCode system setting.\n * @param value - Raw system setting value.\n * @returns Exact normalized URL members.\n */\nexport function parseModelBaseUrls(value: string): ReadonlySet<string> {\n return new Set(value.split(';').map(normalizeModelBaseUrl).filter(Boolean))\n}\n\n/**\n * Classify a runtime model URL; conflicting or absent matches use category `2`.\n * @param baseUrl - Actual model service address.\n * @param configured - URL sets for categories 0, 1, and 3.\n * @returns The unique matching category, or `2`.\n */\nexport function classifyModelBaseUrl(baseUrl: string, configured: ModelKindUrls): ChatCodeModelKind {\n const normalized = normalizeModelBaseUrl(baseUrl)\n if (!normalized) return 2\n const matches = ([0, 1, 3] as const).filter(kind =>\n [...configured[kind]].some(value => normalizeModelBaseUrl(value) === normalized))\n return matches.length === 1 ? matches[0] ?? 2 : 2\n}\n","/** Authenticated ChatCode HTTP protocol client. */\nimport { randomUUID } from 'node:crypto'\nimport type { ChatCodeAuthApi } from '../chatcode-auth.ts'\nimport { classifyModelBaseUrl, emptyModelKindUrls, parseModelBaseUrls, type ChatCodeModelKind, type ModelKindUrls } from './model-kind.ts'\nimport type { ChatMessagePayload, ConversationSyncPayload } from './payloads.ts'\n\nconst MODEL_KIND_CONFIG_KEYS = {\n 0: 'chatcode.cli.model.kind.0.baseurls',\n 1: 'chatcode.cli.model.kind.1.baseurls',\n 3: 'chatcode.cli.model.kind.3.baseurls',\n} as const\n\ninterface Logger {\n warn(message: string): void\n}\n\n/** Narrow transport operations consumed by the event projector. */\nexport interface ReportingTransport {\n /** Return the safe account label associated with the current grant. */\n identity(): Promise<string>\n /** Save generated code; success means the durable outbox may acknowledge it. */\n saveCodes(codes: readonly string[]): Promise<void>\n /** Synchronize conversation metadata and zero or more messages. */\n syncConversation(payload: ConversationSyncPayload): Promise<void>\n /** Create one ChatCode conversation and return its opaque id. */\n createChat(): Promise<string>\n /** Append one token-bearing model response to a ChatCode conversation. */\n addChatMessage(payload: ChatMessagePayload): Promise<void>\n /** Classify an actual model service URL through the cached ChatCode system configuration. */\n modelKind(baseUrl: string): Promise<ChatCodeModelKind>\n}\n\n/** Expected reporting failure without response-body or credential disclosure. */\nexport class ReportingRequestError extends Error {\n constructor(message: string, readonly kind: 'auth' | 'request' | 'response') {\n super(message)\n this.name = 'ReportingRequestError'\n }\n}\n\n/** Fetch-based implementation of the ChatCode reporting endpoints. */\nexport class ChatCodeTransport implements ReportingTransport {\n private readonly baseUrl: URL\n private modelKindUrls: ModelKindUrls = emptyModelKindUrls()\n private modelKindLoaded = false\n private modelKindLoad: Promise<void> | undefined\n\n constructor(\n private readonly auth: ChatCodeAuthApi,\n cvpChatCodeApiUrl: string,\n private readonly requestTimeoutMs: number,\n private readonly lifetime: AbortSignal,\n private readonly fetcher: typeof fetch = fetch,\n private readonly logger: Logger = { warn: () => undefined },\n ) {\n this.baseUrl = validatedBaseUrl(cvpChatCodeApiUrl)\n }\n\n async identity(): Promise<string> {\n const status = await this.auth.status()\n return status.emailAddress ?? status.userName ?? ''\n }\n\n async saveCodes(codes: readonly string[]): Promise<void> {\n const token = await this.token()\n const response = await this.request('wanma/to/openai/v2/save-code', {\n Authorization: token,\n }, { codes })\n if (!response.ok) throw this.httpError('save-code', response.status)\n await response.body?.cancel()\n }\n\n async syncConversation(payload: ConversationSyncPayload): Promise<void> {\n const token = await this.token()\n const response = await this.request('wanma/api/v1/conversations/sync', {\n Authorization: `Bearer ${token}`,\n }, payload)\n const text = await response.text()\n if (!response.ok) throw this.httpError('conversation sync', response.status)\n if (!text) return\n let body: unknown\n try {\n body = JSON.parse(text) as unknown\n } catch {\n return\n }\n if (isRecord(body) && body.code !== undefined && Number(body.code) !== 200) {\n throw new ReportingRequestError('conversation sync returned a non-success business code', businessKind(body.code))\n }\n }\n\n async createChat(): Promise<string> {\n const token = await this.token()\n const response = await this.request('chatcode/session/create', {\n Authorization: `Bearer ${token}`,\n }, { chatType: 1, sourceType: 5 })\n const body = await jsonBody(response, 'create ChatCode session')\n if (!response.ok) throw this.httpError('create ChatCode session', response.status)\n if (Number(body.code) !== 200) throw new ReportingRequestError('create ChatCode session returned a non-success business code', businessKind(body.code))\n const id = responseId(body)\n if (!id) throw new ReportingRequestError('create ChatCode session succeeded without a chat id', 'response')\n return id\n }\n\n async addChatMessage(payload: ChatMessagePayload): Promise<void> {\n const token = await this.token()\n const response = await this.request('chatcode/session/addMsgRecord', {\n Authorization: `Bearer ${token}`,\n }, payload)\n const body = await jsonBody(response, 'append ChatCode message')\n if (!response.ok) throw this.httpError('append ChatCode message', response.status)\n if (Number(body.code) !== 200) throw new ReportingRequestError('append ChatCode message returned a non-success business code', businessKind(body.code))\n if (!responseId(body)) throw new ReportingRequestError('append ChatCode message succeeded without a message id', 'response')\n }\n\n async modelKind(baseUrl: string): Promise<ChatCodeModelKind> {\n await this.loadModelKinds()\n return classifyModelBaseUrl(baseUrl, this.modelKindUrls)\n }\n\n private async loadModelKinds(): Promise<void> {\n if (this.modelKindLoaded) return\n if (this.modelKindLoad !== undefined) return this.modelKindLoad\n const pending = (async () => {\n try {\n const token = await this.token()\n const values = await Promise.all(([0, 1, 3] as const).map(async kind => {\n const key = MODEL_KIND_CONFIG_KEYS[kind]\n const response = await this.request(`system/config/configKey/${encodeURIComponent(key)}`, {\n Authorization: token,\n }, undefined, 'GET')\n if (!response.ok) throw this.httpError('load model-kind configuration', response.status)\n const body = await jsonBody(response, 'load model-kind configuration')\n return [kind, typeof body.msg === 'string' ? body.msg : ''] as const\n }))\n this.modelKindUrls = {\n 0: parseModelBaseUrls(values.find(([kind]) => kind === 0)?.[1] ?? ''),\n 1: parseModelBaseUrls(values.find(([kind]) => kind === 1)?.[1] ?? ''),\n 3: parseModelBaseUrls(values.find(([kind]) => kind === 3)?.[1] ?? ''),\n }\n } catch (error) {\n this.logger.warn(`chatcode-reporting: model-kind configuration is unavailable; using category 2: ${errorMessage(error)}`)\n } finally {\n this.modelKindLoaded = true\n }\n })()\n this.modelKindLoad = pending\n try {\n await pending\n } finally {\n if (this.modelKindLoad === pending) this.modelKindLoad = undefined\n }\n }\n\n private async token(): Promise<string> {\n const token = await this.auth.accessToken(this.lifetime)\n if (!token) throw new ReportingRequestError('ChatCode login is unavailable for reporting', 'auth')\n return token\n }\n\n private async request(\n path: string,\n extraHeaders: Record<string, string>,\n body: unknown,\n method: 'GET' | 'POST' = 'POST',\n ): Promise<Response> {\n const requestId = randomUUID()\n const signal = AbortSignal.any([this.lifetime, AbortSignal.timeout(this.requestTimeoutMs)])\n try {\n return await this.fetcher(new URL(path, this.baseUrl), {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Request-Id': requestId,\n ...extraHeaders,\n },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n signal,\n redirect: 'error',\n })\n } catch (error) {\n if (signal.aborted) throw new ReportingRequestError(`ChatCode request was aborted (${requestId})`, 'request')\n throw new ReportingRequestError(`ChatCode request failed (${requestId}): ${error instanceof Error ? error.message : String(error)}`, 'request')\n }\n }\n\n private httpError(operation: string, status: number): ReportingRequestError {\n return new ReportingRequestError(`${operation} returned HTTP ${status}`, status === 401 || status === 403 ? 'auth' : 'request')\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction validatedBaseUrl(value: string): URL {\n const url = new URL(value)\n const loopback = ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname)\n if (url.username || url.password || (url.protocol !== 'https:' && !(url.protocol === 'http:' && loopback))) {\n throw new Error('ChatCode reporting requires HTTPS; HTTP is allowed only on loopback.')\n }\n url.pathname = `${url.pathname.replace(/\\/+$/u, '')}/`\n return url\n}\n\nasync function jsonBody(response: Response, operation: string): Promise<Record<string, unknown>> {\n try {\n const body = await response.json() as unknown\n if (isRecord(body)) return body\n } catch {\n // The protocol failure below owns the public diagnostic.\n }\n throw new ReportingRequestError(`${operation} returned invalid JSON`, 'response')\n}\n\nfunction responseId(body: Record<string, unknown>): string {\n const data = typeof body.data === 'string' ? body.data.trim() : ''\n if (data) return data\n const message = typeof body.msg === 'string' ? body.msg.trim() : ''\n return message && message !== '操作成功' && message.toLowerCase() !== 'success' ? message : ''\n}\n\nfunction businessKind(code: unknown): 'auth' | 'request' {\n const numeric = Number(code)\n return numeric === 401 || numeric === 403 ? 'auth' : 'request'\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","/** Install ChatCode operations reporting over committed ChatCode CLI Session events. */\nimport type {} from '@deepseek-ai/dsh-agent'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { dshHomePath } from '@deepseek-ai/dsh-home-paths'\nimport { isAbsolute } from 'node:path'\nimport type { ChatCodeAuthApi } from '../chatcode-auth.ts'\nimport type { ReportingConfig } from '../config.ts'\nimport { CodeOutbox } from './outbox.ts'\nimport type { ModelReportResolver } from './payloads.ts'\nimport { ChatCodeReporter, CodeOutboxWorker } from './reporter.ts'\nimport { ChatCodeTransport } from './transport.ts'\n\n/** Resolved backend and reporting settings for one reporter instance. */\nexport interface ChatCodeReportingConfig extends ReportingConfig {\n /** CVP backend root for all reporting requests. */\n cvpChatCodeApiUrl: string\n /** Maximum duration of one backend request. */\n requestTimeoutMs: number\n}\n\n/** Register the reporter for all Sessions visible to this Cordis scope. */\nexport function installChatCodeReporting(\n ctx: Context,\n auth: ChatCodeAuthApi,\n config: ChatCodeReportingConfig,\n resolveModelReport: ModelReportResolver,\n): void {\n const lifetime = new AbortController()\n const transport = new ChatCodeTransport(auth, config.cvpChatCodeApiUrl, config.requestTimeoutMs, lifetime.signal, fetch, ctx.logger)\n if (config.codeOutboxDir !== '' && !isAbsolute(config.codeOutboxDir)) {\n throw new Error('ChatCode reporting codeOutboxDir must be an absolute path.')\n }\n const outbox = new CodeOutbox(config.codeOutboxDir || dshHomePath('chatcode-reporting', 'code-save-outbox'))\n const codeWorker = new CodeOutboxWorker(\n outbox,\n transport,\n config.codeBatchItems,\n config.codeBatchChars,\n config.codeRetryDelayMs,\n ctx.logger,\n )\n const reporter = new ChatCodeReporter(config, transport, codeWorker, ctx.logger, resolveModelReport)\n if (config.codeSave) codeWorker.start()\n ctx.on('session/created', session => { reporter.created(session) })\n ctx.on('agent/created', ({ agent }) => {\n reporter.seedModelRoute(agent.session, agent.options.provider, agent.options.model)\n return undefined\n })\n ctx.on('session/event', (session, event) => { reporter.observe(session, event) })\n ctx.on('session/disposed', session => reporter.disposed(session))\n ctx.effect(() => async () => {\n try {\n await reporter.shutdown()\n } finally {\n lifetime.abort()\n }\n }, 'chatcode-reporting: drain queued reports')\n}\n","/** Resolve custom-model settings and parse the legacy ChatCode JSON file. @module dsh-llm-chatcode-config/source */\n\nimport { createHash } from 'node:crypto'\nimport { readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport z from '@deepseek-ai/schemastery'\nimport { assertUsableApiKey, LlmError } from '@deepseek-ai/dsh-llm'\nimport type { PiAiRequestAuth } from '../vendor/dsh-llm-pi-ai/src/adapter.ts'\nimport { resolveProfiles } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { PiAiProviderProfile, ResolvedPiAiProviderProfile } from '../vendor/dsh-llm-pi-ai/src/config.ts'\nimport type { Config, CustomModel } from './config.ts'\n\nconst positiveInteger = z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER)\nconst documentSchema = z.object({\n customModels: z.array(z.object({\n model: z.string().required(),\n apiKey: z.string().required(),\n baseUrl: z.string().required(),\n description: z.string(),\n provider: z.union([z.string(), z.const(null)]),\n protocol: z.string(),\n contextWindow: positiveInteger,\n maxTokens: positiveInteger,\n maxInputTokens: positiveInteger,\n })).required(),\n})\n\n/** One activation's model profiles and private request credentials. */\nexport interface ChatCodeSource {\n /** Non-secret route and model metadata; immutable for the plugin's lifetime. */\n profiles: ReadonlyMap<string, ResolvedPiAiProviderProfile>\n /** Credentials are kept outside profile configuration and catalog responses. */\n auth: ReadonlyMap<string, PiAiRequestAuth>\n /** Validated literal keys retained for DeepSeek-native request dispatch. */\n apiKeys: ReadonlyMap<string, string>\n /** Public model identity to private provider/model routing. Never contains credentials. */\n selections: ReadonlyMap<string, ChatCodeModelSelection>\n /** Private source entries retained only by the Host so settings-managed models can merge with file imports. */\n entries?: readonly CustomModel[]\n}\n\n/** One public model selection's private request destination. */\nexport interface ChatCodeModelSelection {\n route: string\n model: string\n}\n\n/** Public reporting identity derived from one private model route. */\nexport interface ChatCodeModelReport {\n modelName: string\n baseUrl: string\n}\n\n/**\n * Resolve the actual provider model and service URL behind a public selection.\n * @param source - Current custom or managed model snapshot.\n * @param selection - Public model id selected through the aggregate provider.\n * @returns Reporting fields, or `undefined` when the selection is absent.\n */\nexport function reportModelFromSource(source: ChatCodeSource, selection: string): ChatCodeModelReport | undefined {\n const target = source.selections.get(selection)\n if (target === undefined) return undefined\n return {\n modelName: target.model,\n baseUrl: source.profiles.get(target.route)?.baseURL ?? '',\n }\n}\n\n/** Report only a field location: JSON/schema diagnostics may quote a credential. */\nfunction invalid(location: string): never {\n throw new LlmError(`chatcode-config: invalid ${location}`, 'INVALID_CHATCODE_CONFIG')\n}\n\n/** Normalize the two legacy wire dialects, retaining the provider=anthropic fallback. */\nfunction protocolOf(entry: CustomModel, location: string): 'openai-completions' | 'anthropic-messages' {\n switch (entry.protocol?.trim().toLowerCase()) {\n case undefined:\n case '':\n return entry.provider?.trim().toLowerCase() === 'anthropic' ? 'anthropic-messages' : 'openai-completions'\n case 'openai': return 'openai-completions'\n case 'anthropic': return 'anthropic-messages'\n default: return invalid(`${location}.protocol (expected OpenAI or Anthropic)`)\n }\n}\n\n/** Validate a complete base URL without discarding the gateway's path prefix. */\nfunction endpointOf(raw: string, location: string): string {\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n // URL parser messages include their input, which may contain credentials.\n return invalid(`${location}.baseUrl`)\n }\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) {\n return invalid(`${location}.baseUrl (expected HTTP(S) without credentials, query, or fragment)`)\n }\n return url.href.replace(/\\/+$/, '')\n}\n\n/**\n * Validate customModels and resolve one detached activation snapshot.\n * @param data - parsed JSON from the external file, never a typed plugin configuration.\n * @param config - validated mount defaults.\n * @returns profiles and private credentials for exactly the declared model entries.\n */\nexport function resolveSource(data: unknown, config: Config): ChatCodeSource {\n let entries: CustomModel[]\n try {\n entries = documentSchema(data as Parameters<typeof documentSchema>[0]).customModels\n } catch {\n // Schema errors can quote source values; only the owning JSON field is public.\n return invalid('customModels (expected an array of models with model, baseUrl, and apiKey)')\n }\n const profiles: Record<string, PiAiProviderProfile> = {}\n const auth = new Map<string, PiAiRequestAuth>()\n const apiKeys = new Map<string, string>()\n const selections = new Map<string, ChatCodeModelSelection>()\n const modelIds = new Set<string>()\n for (const [index, entry] of entries.entries()) {\n const location = `customModels[${index}]`\n if (entry.model.trim() === '') invalid(`${location}.model`)\n if (modelIds.has(entry.model)) invalid(`${location}.model (duplicate model id in unified catalog)`)\n modelIds.add(entry.model)\n const api = protocolOf(entry, location)\n const baseURL = endpointOf(entry.baseUrl, location)\n const provider = `chatcode-${createHash('sha256').update(JSON.stringify([api, baseURL, entry.model])).digest('hex').slice(0, 20)}`\n const apiKey = assertUsableApiKey(entry.apiKey, 'chatcode-config', `${location}.apiKey`)\n profiles[provider] = {\n displayName: entry.description?.trim() || entry.model,\n api,\n baseURL,\n models: [{\n id: entry.model,\n name: entry.description?.trim() || entry.model,\n contextWindow: entry.contextWindow ?? entry.maxTokens ?? entry.maxInputTokens ?? config.defaultContextWindow,\n maxTokens: entry.maxTokens ?? config.defaultMaxTokens,\n }],\n ...api === 'openai-completions' ? { compat: { maxTokensField: 'max_tokens', supportsDeveloperRole: false } } : {},\n ...api === 'openai-completions' && /^minimax-m2(?:[.-]|$)/i.test(entry.model) ? { reasoningSplit: true } : {},\n ...config.retryPolicy === undefined ? {} : { retryPolicy: config.retryPolicy },\n }\n auth.set(provider, api === 'anthropic-messages'\n ? { headers: { Authorization: `Bearer ${apiKey}` } }\n : { apiKey })\n apiKeys.set(provider, apiKey)\n selections.set(entry.model, { route: provider, model: entry.model })\n }\n return { profiles: resolveProfiles(profiles), auth, apiKeys, selections, entries: entries.map(entry => ({ ...entry })) }\n}\n\n/**\n * Resolve the user-defined models in one validated settings snapshot.\n * @param config - Current resolved plugin settings.\n * @returns One immutable model and authentication snapshot.\n */\nexport function resolveConfiguredSource(config: Config): ChatCodeSource {\n return resolveSource({ customModels: config.customModels }, config)\n}\n\n/**\n * Read the configured Host file once; never use the agent's execution filesystem.\n * @param config - validated mount defaults and optional Host path.\n * @returns the complete validated snapshot; malformed JSON never appears in diagnostics.\n */\nexport async function readSource(config: Config): Promise<ChatCodeSource> {\n const filename = resolve(config.settingsPath ?? join(homedir(), '.chatcode-cli', 'settings.json'))\n let text: string\n try {\n text = await readFile(filename, 'utf8')\n } catch {\n // Host filesystem errors may quote sensitive paths; the mount owns the filename.\n throw new LlmError('chatcode-config: cannot read settingsPath', 'CHATCODE_CONFIG_READ_FAILED')\n }\n let data: unknown\n try {\n data = JSON.parse(text)\n } catch {\n // JSON syntax errors may include the source line containing an API key.\n throw new LlmError('chatcode-config: settingsPath is not valid JSON', 'INVALID_CHATCODE_CONFIG')\n }\n return resolveSource(data, config)\n}\n","/** Publish ChatCode-authenticated CodingPlan and MAAS catalogs into the LLM registry. @module dsh-llm-chatcode-config */\n\nimport { Service, type Context } from '@deepseek-ai/cordis'\nimport { LlmError } from '@deepseek-ai/dsh-llm'\nimport type { AdapterRegistrationHandle } from '@deepseek-ai/dsh-llm'\nimport type { CredentialProvider } from '@deepseek-ai/dsh-credentials'\nimport type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands'\nimport type {} from '@deepseek-ai/dsh-cmdline'\nimport type {} from '@deepseek-ai/dsh-settings'\nimport { runUpdate, runUpdateSync } from './update.ts'\nimport { checkVersions, decisionPrompt, promptVersionAction, runDecisionInstall } from './version-check.ts'\nimport { isolatedPiAiAuth } from '../vendor/dsh-llm-pi-ai/src/auth.ts'\nimport {\n CHATCODE_PROVIDER,\n CODING_PLAN_PROVIDER,\n CODING_PLAN_PROVIDER_NAME,\n MAAS_PROVIDER,\n MAAS_PROVIDER_NAME,\n ChatCodeAdapter,\n LiveChatCodeAdapter,\n} from './adapter.ts'\nimport { chatCodeEnvironmentToken, ChatCodeAuthService } from './chatcode-auth.ts'\nimport { ChatCodeStartupGateService } from './startup-gate.ts'\nimport { Config } from './config.ts'\nimport { fetchMaasRuntimeModels, fetchRuntimeModels, resolveManagedSource } from './managed.ts'\nimport { installChatCodeReporting } from './reporting/index.ts'\nimport { readSource, reportModelFromSource, resolveConfiguredSource } from './source.ts'\nimport type { ChatCodeSource } from './source.ts'\n\nexport { Config } from './config.ts'\nexport type { CustomModel, ModelKindRule, ReportingConfig } from './config.ts'\nexport { ChatCodeAuthService } from './chatcode-auth.ts'\nexport { ChatCodeStartupGateService, checkChatCodeStartupGate, startupGateFailureMessage } from './startup-gate.ts'\nexport type { StartupGateResult, StartupGateFailure } from './startup-gate.ts'\n\nexport const name = 'llm-chatcode-config'\nexport const inject = ['llm']\nexport const SETTINGS_NAMESPACE = 'llm-chatcode-config'\n\n/** Optional, host-only refresh seam for terminal and browser clients. */\nexport interface ChatCodeModelCatalogApi {\n /** Reload CodingPlan and, when enabled, MAAS routes into the LLM registry. */\n refresh(): Promise<void>\n /** Current effective MAAS switch value. */\n maasEnabled(): boolean\n /** Persist the MAAS switch and wait for the matching catalog refresh. */\n setMaasEnabled(enabled: boolean): Promise<void>\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { chatcodeModelCatalog: ChatCodeModelCatalogService }\n}\n\n/**\n * Keeps catalog I/O in the host bundle: clients ask for a registry refresh but\n * never receive endpoint or credential-bearing runtime configuration.\n */\nexport class ChatCodeModelCatalogService extends Service implements ChatCodeModelCatalogApi {\n private writeMaas: ((enabled: boolean) => Promise<void>) | undefined\n\n constructor(\n ctx: Context,\n private readonly reload: () => Promise<void>,\n private readonly readMaas: () => boolean,\n ) {\n super(ctx, 'chatcodeModelCatalog')\n }\n\n refresh(): Promise<void> {\n return this.reload()\n }\n\n maasEnabled(): boolean {\n return this.readMaas()\n }\n\n async setMaasEnabled(enabled: boolean): Promise<void> {\n if (this.writeMaas === undefined) {\n throw new Error('ChatCode MAAS settings are not ready; retry after the Host finishes starting.')\n }\n await this.writeMaas(enabled)\n await this.reload()\n }\n\n /** Bind the durable settings writer once the optional settings service mounts. */\n bindMaasSettings(write: (enabled: boolean) => Promise<void>): void {\n this.writeMaas = write\n }\n}\n\n/** Register ChatCode model sources, account access, and operations reporting. */\nexport async function apply(ctx: Context, config: Config): Promise<void> {\n const environmentAccessToken = chatCodeEnvironmentToken(ctx)\n const catalogAuthorization = environmentAccessToken === undefined\n ? undefined\n : { accessToken: environmentAccessToken }\n // `chatcode-cli --update` reaches the tree as an inner argument; refresh the global\n // install and exit before any catalog boot work or interactive surface mounts.\n // First statement on purpose: a self-update must win over every later failure.\n // It is synchronous on purpose too: the profile's other plugins boot\n // concurrently, and `chatcode-cli --update` must finish — and exit — before any of\n // them can print. The final line is written (the console write is issued\n // immediately), then the process dies instead of returning into the boot.\n if ((ctx.get('cmdlineArgs')?.get() ?? []).includes('--update')) {\n const result = runUpdateSync()\n process.stdout.write(`${result.message}\\n`)\n process.exit(result.status === 'error' ? 1 : 0)\n }\n\n new ChatCodeStartupGateService(ctx, config)\n\n // Startup version admission: only a launcher-provided command line reaches\n // this path. Validate the ChatCode CLI package against CVP and, when the server\n // asks for an upgrade or a rollback, resolve the choice before the\n // interactive surface mounts. Network/probe failures leave startup open.\n if (ctx.get('cmdlineArgs') !== undefined) {\n const decision = await checkVersions(config)\n if (decision !== undefined) {\n const choice = await promptVersionAction(decisionPrompt(decision))\n if (choice !== 'perform') {\n ctx.get('appExit')?.(0)\n return\n }\n const verb = decision.action === 'upgrade' ? '升级' : '更换'\n process.stdout.write(`正在${verb}中...\\n`)\n const result = await runDecisionInstall(decision)\n process.stdout.write(`${result.message}\\n`)\n ctx.get('appExit')?.(result.ok ? 0 : 1)\n return\n }\n }\n\n // `/update` slash command, available from both the browser and terminal surfaces.\n ctx.inject(['commands'], commandsCtx => {\n commandsCtx.commands.register({\n name: 'update',\n description: '更新 ChatCode CLI 到最新版本',\n handler: async (invocation: CommandInvocation): Promise<CommandResult> => {\n // Progress lines are broadcast for the terminal surface, which renders\n // them live in an overlay panel; other surfaces (web) ignore the event\n // and just read the returned result text.\n const result = await runUpdate({\n signal: invocation.signal,\n onProgress: line => {\n (ctx.emit as (name: string, ...args: unknown[]) => void)('llm-chatcode-config/update-progress', line)\n },\n })\n return result.status === 'error'\n ? { kind: 'error', text: result.message }\n : { kind: 'success', text: result.message }\n },\n })\n })\n\n const register = (provider: string, providerName: string, source: ChatCodeSource): AdapterRegistrationHandle | undefined => {\n if (source.profiles.size === 0) return undefined\n const adapter = new ChatCodeAdapter({\n profiles: () => source.profiles,\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Profiles and auth share keys; route resolution precedes auth.\n resolveAuth: route => Promise.resolve(source.auth.get(route)!),\n auth: isolatedPiAiAuth(),\n }, source.profiles, provider, providerName, source.selections, source.apiKeys)\n return ctx.llm.registerAdapter([provider], adapter)\n }\n\n let current: () => Config = () => config\n let lastCustomConfig: Config | undefined\n let customSourceSnapshot: ChatCodeSource | undefined\n const customSource = (): ChatCodeSource => {\n const resolved = current()\n if (resolved === lastCustomConfig && customSourceSnapshot !== undefined) return customSourceSnapshot\n const source = resolveConfiguredSource(resolved)\n lastCustomConfig = resolved\n customSourceSnapshot = source\n return source\n }\n const customAdapter = new LiveChatCodeAdapter(customSource)\n let customRegistration: AdapterRegistrationHandle | undefined\n const refreshCustom = (): void => {\n const routes = customSource().profiles.size === 0 ? [] : [CHATCODE_PROVIDER]\n if (customRegistration === undefined) {\n if (routes.length === 0) return\n customRegistration = ctx.llm.registerAdapter(routes, customAdapter)\n return\n }\n customRegistration.replace(routes)\n }\n const managedRegistrations = new Map<string, AdapterRegistrationHandle>()\n const managedSources = new Map<string, ChatCodeSource>()\n const resolveReportingModel = (provider: string, model: string): { modelName: string; baseUrl: string } => {\n const source = provider === CHATCODE_PROVIDER ? customSource() : managedSources.get(provider)\n return source === undefined ? { modelName: model, baseUrl: '' }\n : reportModelFromSource(source, model) ?? { modelName: model, baseUrl: '' }\n }\n\n ctx.inject(['credentials'], authCtx => {\n const auth = new ChatCodeAuthService(\n authCtx,\n authCtx.get('credentials') as CredentialProvider,\n config.auth,\n environmentAccessToken,\n )\n if (config.reporting.enabled) {\n authCtx.inject(['sessions'], reportingCtx => {\n installChatCodeReporting(reportingCtx, auth, {\n ...config.reporting,\n cvpChatCodeApiUrl: config.cvpChatCodeApiUrl,\n requestTimeoutMs: config.auth.requestTimeoutMs,\n }, resolveReportingModel)\n })\n }\n })\n\n let refreshQueued = false\n let refreshInFlight: Promise<void> | undefined\n const clearManaged = (): void => {\n for (const registration of managedRegistrations.values()) registration()\n managedRegistrations.clear()\n managedSources.clear()\n }\n const refreshOnce = async (): Promise<void> => {\n clearManaged()\n const resolved = current()\n const catalogs: { provider: string; name: string; endpoint: string; group: 'codingplan' | 'maas' }[] = [{\n provider: CODING_PLAN_PROVIDER,\n name: CODING_PLAN_PROVIDER_NAME,\n endpoint: resolved.codingPlanEndpoint,\n group: 'codingplan',\n }]\n if (resolved.enableMaas) {\n if (resolved.maasEndpoint.trim() === '') {\n ctx.logger.warn('chatcode-config: MAAS is enabled but no MAAS catalog endpoint is configured')\n } else {\n catalogs.push({ provider: MAAS_PROVIDER, name: MAAS_PROVIDER_NAME, endpoint: resolved.maasEndpoint, group: 'maas' })\n }\n }\n const loaded = await Promise.all(catalogs.map(async catalog => {\n try {\n const models = catalog.group === 'maas'\n ? await fetchMaasRuntimeModels(catalog.endpoint, resolved.catalogTimeoutMs, catalogAuthorization)\n : await fetchRuntimeModels(\n catalog.endpoint,\n resolved.catalogTimeoutMs,\n catalogAuthorization,\n message => ctx.logger.info(message),\n )\n const source = resolveManagedSource(models, catalog.group, resolved)\n if (catalog.group === 'codingplan') {\n ctx.logger.info(`chatcode-config: CodingPlan registered ${String(source.selections.size)} runnable models from ${String(models.length)} parsed records`)\n }\n return { catalog, source }\n } catch (error) {\n if (error instanceof LlmError) {\n ctx.logger.warn(`chatcode-config: ${catalog.name} models were not registered (${error.code})`)\n return undefined\n }\n throw error\n }\n }))\n // Keep the custom adapter available while remote catalogs load, then\n // rebuild all three product-facing groups as one ordered registry block.\n // Web consumes `listProviders()` in registration order, so managed\n // catalogs register first and the user catalog last.\n if (customRegistration !== undefined) {\n customRegistration()\n customRegistration = undefined\n }\n for (const entry of loaded) {\n if (entry === undefined) continue\n const registration = register(entry.catalog.provider, entry.catalog.name, entry.source)\n if (registration !== undefined) {\n managedRegistrations.set(entry.catalog.provider, registration)\n managedSources.set(entry.catalog.provider, entry.source)\n }\n }\n refreshCustom()\n }\n // Settings can invoke `onChange()` during installation, while TUI can ask\n // for the same refresh as it boots. Ordinary callers share one request;\n // only an actual settings change queues a second pass.\n const refreshManaged = (): Promise<void> => {\n if (refreshInFlight !== undefined) return refreshInFlight\n const task = (async () => {\n do {\n refreshQueued = false\n await refreshOnce()\n } while (refreshQueued)\n })()\n const tracked = task.finally(() => {\n if (refreshInFlight === tracked) refreshInFlight = undefined\n })\n refreshInFlight = tracked\n return tracked\n }\n const refreshForSettingsChange = (): void => {\n // Settings edits affect custom calls immediately. The managed refresh\n // later re-registers this adapter at the end to restore display order.\n refreshCustom()\n if (refreshInFlight !== undefined) {\n refreshQueued = true\n return\n }\n void refreshManaged()\n }\n const modelCatalogService = new ChatCodeModelCatalogService(\n ctx,\n refreshManaged,\n () => current().enableMaas,\n )\n\n ctx.logger.info(`chatcode-config: waiting for settings service to register namespace \"${SETTINGS_NAMESPACE}\"`)\n ctx.inject(['settings'], async settingsCtx => {\n ctx.logger.info(`chatcode-config: settings service available; registering namespace \"${SETTINGS_NAMESPACE}\"`)\n try {\n settingsCtx.settings.installSection(ctx, SETTINGS_NAMESPACE, Config, config, {\n setSource: source => { current = source },\n onChange: refreshForSettingsChange,\n validate: value => { resolveConfiguredSource(value) },\n })\n } catch (error) {\n ctx.logger.warn(`chatcode-config: failed to register settings namespace \"${SETTINGS_NAMESPACE}\" (${error instanceof Error ? error.message : String(error)})`)\n throw error\n }\n modelCatalogService.bindMaasSettings(async enabled => {\n ctx.logger.info(`chatcode-config: persisting MAAS setting enableMaas=${String(enabled)}`)\n const ops = [{ op: 'set' as const, path: ['enableMaas'], value: enabled }]\n const revision = (): number | undefined =>\n settingsCtx.settings.describe().find(entry => entry.ns === SETTINGS_NAMESPACE)?.revision\n try {\n await settingsCtx.settings.mutate(SETTINGS_NAMESPACE, ops, revision())\n } catch (error) {\n if ((error as { code?: unknown })?.code !== 'SETTINGS_CONFLICT') throw error\n await settingsCtx.settings.mutate(SETTINGS_NAMESPACE, ops, revision())\n }\n ctx.logger.info(`chatcode-config: persisted MAAS setting enableMaas=${String(enabled)}`)\n })\n const descriptor = settingsCtx.settings.describe().find(entry => entry.ns === SETTINGS_NAMESPACE)\n ctx.logger.info(`chatcode-config: settings namespace \"${SETTINGS_NAMESPACE}\" registered=${String(descriptor !== undefined)} revision=${String(descriptor?.revision ?? 'missing')} enableMaas=${String(current().enableMaas)}`)\n if (descriptor?.user !== undefined) {\n ctx.logger.info(`chatcode-config: settings namespace \"${SETTINGS_NAMESPACE}\" loaded an existing user section`)\n return\n }\n try {\n const imported = await readSource(config)\n await settingsCtx.settings.replace(SETTINGS_NAMESPACE, { customModels: imported.entries ?? [] })\n ctx.logger.info(`chatcode-config: settings namespace \"${SETTINGS_NAMESPACE}\" initialized from the legacy source`)\n } catch (error) {\n if (!(error instanceof LlmError)) throw error\n ctx.logger.warn('chatcode-config: legacy settingsPath is unavailable or invalid; custom models were not imported and import will retry when the Host starts again')\n }\n })\n // Always populate the catalog during host startup. When settings is mounted,\n // its initial onChange may already have started this same single-flight load.\n await refreshManaged()\n}\n"],"mappings":"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"}
|