codealmanac 0.2.4 → 0.2.6

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.
Files changed (51) hide show
  1. package/COMMERCIAL.md +9 -0
  2. package/LICENSE +133 -21
  3. package/README.md +2 -2
  4. package/dist/{agents-4Y7X24WW.js → agents-HYRWRHRX.js} +4 -4
  5. package/dist/{chunk-TT6ZP4GS.js → chunk-2BNDNGUR.js} +8 -4
  6. package/dist/{chunk-TT6ZP4GS.js.map → chunk-2BNDNGUR.js.map} +1 -1
  7. package/dist/{chunk-P5WGG4FJ.js → chunk-3E7JNMTZ.js} +28 -3
  8. package/dist/chunk-3E7JNMTZ.js.map +1 -0
  9. package/dist/{chunk-CW4HRLMS.js → chunk-DW32TL5W.js} +53 -11
  10. package/dist/chunk-DW32TL5W.js.map +1 -0
  11. package/dist/{chunk-UU6FBRQO.js → chunk-GPFVEF6V.js} +24 -6
  12. package/dist/chunk-GPFVEF6V.js.map +1 -0
  13. package/dist/{chunk-TILAKDN6.js → chunk-HJ3WREGP.js} +2 -2
  14. package/dist/{chunk-BF2J4XTC.js → chunk-J7DNV2DH.js} +219 -26
  15. package/dist/chunk-J7DNV2DH.js.map +1 -0
  16. package/dist/{chunk-H6QKCB7M.js → chunk-K2JBCB7R.js} +43 -7
  17. package/dist/chunk-K2JBCB7R.js.map +1 -0
  18. package/dist/{chunk-MRRX4UQB.js → chunk-ODJAAJGZ.js} +2 -2
  19. package/dist/{chunk-447U3GQJ.js → chunk-PDFS5VFE.js} +17 -5
  20. package/dist/chunk-PDFS5VFE.js.map +1 -0
  21. package/dist/{chunk-QRK3JLFX.js → chunk-VXDPUOQ5.js} +381 -126
  22. package/dist/chunk-VXDPUOQ5.js.map +1 -0
  23. package/dist/{cli-MYMZ66EN.js → cli-MKXCNEMW.js} +14 -14
  24. package/dist/codealmanac.js +1 -1
  25. package/dist/{config-ML2RCR7J.js → config-F7FKEQ7F.js} +3 -3
  26. package/dist/doctor-37UH3HT5.js +17 -0
  27. package/dist/{hook-2NP3UE7U.js → hook-4SVX446M.js} +4 -2
  28. package/dist/{register-commands-XTK2G2FB.js → register-commands-2F6SXLDI.js} +28 -19
  29. package/dist/register-commands-2F6SXLDI.js.map +1 -0
  30. package/dist/uninstall-C62ZOK32.js +17 -0
  31. package/dist/{update-P2IPG7RO.js → update-2UGOFN5C.js} +3 -3
  32. package/package.json +4 -3
  33. package/dist/chunk-447U3GQJ.js.map +0 -1
  34. package/dist/chunk-BF2J4XTC.js.map +0 -1
  35. package/dist/chunk-CW4HRLMS.js.map +0 -1
  36. package/dist/chunk-H6QKCB7M.js.map +0 -1
  37. package/dist/chunk-P5WGG4FJ.js.map +0 -1
  38. package/dist/chunk-QRK3JLFX.js.map +0 -1
  39. package/dist/chunk-UU6FBRQO.js.map +0 -1
  40. package/dist/doctor-W5KQQLAX.js +0 -17
  41. package/dist/register-commands-XTK2G2FB.js.map +0 -1
  42. package/dist/uninstall-N7JY7ZV2.js +0 -15
  43. /package/dist/{agents-4Y7X24WW.js.map → agents-HYRWRHRX.js.map} +0 -0
  44. /package/dist/{chunk-TILAKDN6.js.map → chunk-HJ3WREGP.js.map} +0 -0
  45. /package/dist/{chunk-MRRX4UQB.js.map → chunk-ODJAAJGZ.js.map} +0 -0
  46. /package/dist/{cli-MYMZ66EN.js.map → cli-MKXCNEMW.js.map} +0 -0
  47. /package/dist/{config-ML2RCR7J.js.map → config-F7FKEQ7F.js.map} +0 -0
  48. /package/dist/{doctor-W5KQQLAX.js.map → doctor-37UH3HT5.js.map} +0 -0
  49. /package/dist/{hook-2NP3UE7U.js.map → hook-4SVX446M.js.map} +0 -0
  50. /package/dist/{uninstall-N7JY7ZV2.js.map → uninstall-C62ZOK32.js.map} +0 -0
  51. /package/dist/{update-P2IPG7RO.js.map → update-2UGOFN5C.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/doctor-checks/format.ts","../src/commands/doctor-checks/install.ts","../src/commands/doctor-checks/probes.ts","../src/commands/doctor-checks/agents.ts","../src/commands/doctor-checks/updates.ts","../src/commands/doctor.ts"],"sourcesContent":["import { BLUE, BOLD, DIM, GREEN, RED, RST } from \"../../ansi.js\";\nimport type {\n AgentDoctorCheck,\n Check,\n CheckStatus,\n DoctorOptions,\n DoctorReport,\n} from \"./types.js\";\n\nexport function formatReport(\n report: DoctorReport,\n options: DoctorOptions,\n): string {\n const color = options.stdout === undefined && process.stdout.isTTY === true;\n const lines: string[] = [];\n lines.push(`codealmanac v${report.version}`);\n lines.push(\"\");\n if (report.install.length > 0) {\n lines.push(color ? `${BOLD}## Install${RST}` : \"## Install\");\n for (const c of report.install) {\n lines.push(formatCheck(c, color));\n }\n lines.push(\"\");\n }\n if (report.agents.length > 0) {\n lines.push(color ? `${BOLD}## Agents${RST}` : \"## Agents\");\n for (const c of report.agents.map(agentToCheck)) {\n lines.push(formatCheck(c, color));\n }\n lines.push(\"\");\n }\n if (report.updates.length > 0) {\n lines.push(color ? `${BOLD}## Updates${RST}` : \"## Updates\");\n for (const c of report.updates) {\n lines.push(formatCheck(c, color));\n }\n lines.push(\"\");\n }\n if (report.wiki.length > 0) {\n lines.push(color ? `${BOLD}## Current wiki${RST}` : \"## Current wiki\");\n for (const c of report.wiki) {\n lines.push(formatCheck(c, color));\n }\n lines.push(\"\");\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction agentToCheck(agent: AgentDoctorCheck): Check {\n const message = [\n agent.label,\n agent.selected ? \"(default)\" : null,\n agent.recommended ? \"(recommended)\" : null,\n agent.status === \"ok\" ? \"ready\" : readinessMessage(agent),\n `model: ${agent.model ?? \"provider default\"}`,\n agent.account,\n ].filter((part): part is string => part !== null).join(\" \");\n return {\n status: agent.status,\n key: `agents.${agent.id}`,\n message,\n fix: agent.fix,\n };\n}\n\nfunction readinessMessage(agent: AgentDoctorCheck): string {\n if (!agent.installed) return \"missing\";\n if (!agent.authenticated) return `not ready: ${agent.detail}`;\n return agent.detail;\n}\n\nfunction formatCheck(c: Check, color: boolean): string {\n const { icon, tint } = iconFor(c.status, color);\n const head = ` ${tint}${icon}${color ? RST : \"\"} ${c.message}`;\n if (c.fix === undefined) return head;\n const fixLine = color\n ? ` ${DIM}${c.fix}${RST}`\n : ` ${c.fix}`;\n return `${head}\\n${fixLine}`;\n}\n\nfunction iconFor(\n status: CheckStatus,\n color: boolean,\n): { icon: string; tint: string } {\n switch (status) {\n case \"ok\":\n return { icon: \"\\u2713\", tint: color ? GREEN : \"\" };\n case \"problem\":\n return { icon: \"\\u2717\", tint: color ? RED : \"\" };\n case \"info\":\n return { icon: \"\\u25c7\", tint: color ? BLUE : \"\" };\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\n\nimport type { ClaudeAuthStatus } from \"../../agent/providers/claude/index.js\";\nimport {\n hasCodexInstructions,\n resolveCodexAgentsPath,\n} from \"../../agent/providers/codex-instructions.js\";\nimport {\n IMPORT_LINE,\n} from \"../setup.js\";\nimport {\n classifyInstallPath,\n detectInstallPath,\n probeBetterSqlite3,\n safeCheckAuth,\n} from \"./probes.js\";\nimport type { Check, DoctorOptions } from \"./types.js\";\n\nexport async function gatherInstallChecks(\n options: DoctorOptions,\n): Promise<Check[]> {\n const checks: Check[] = [];\n\n const rawPath = options.installPath ?? detectInstallPath();\n const { installPath, isEphemeral } = classifyInstallPath(rawPath);\n checks.push(describeInstallPath(installPath, isEphemeral));\n\n const nodeVersion = options.nodeVersion ?? process.version;\n const sqlite = options.sqliteProbe ?? probeBetterSqlite3();\n checks.push({\n status: sqlite.ok ? \"ok\" : \"problem\",\n key: \"install.sqlite\",\n message: sqlite.ok\n ? `better-sqlite3 native binding OK (Node ${nodeVersion})`\n : `better-sqlite3 native binding failed: ${sqlite.summary}`,\n fix: sqlite.ok\n ? undefined\n : \"run: npm rebuild better-sqlite3 (in the install directory)\",\n });\n\n const auth = await safeCheckAuth(options.spawnCli);\n checks.push(describeAuth(auth));\n\n const settingsPath =\n options.settingsPath ?? path.join(homedir(), \".claude\", \"settings.json\");\n checks.push(await describeHook(settingsPath));\n\n const claudeDir = options.claudeDir ?? path.join(homedir(), \".claude\");\n checks.push(describeGuides(claudeDir));\n checks.push(await describeImportLine(claudeDir));\n const codexDir = options.codexDir ?? path.join(homedir(), \".codex\");\n checks.push(await describeCodexInstructions(codexDir));\n\n return checks;\n}\n\nfunction describeInstallPath(\n installPath: string | null,\n isEphemeral: boolean,\n): Check {\n if (installPath === null) {\n return {\n status: \"problem\",\n key: \"install.path\",\n message: \"could not detect codealmanac install path\",\n fix: \"reinstall with: npm install -g codealmanac\",\n };\n }\n return {\n status: isEphemeral ? \"info\" : \"ok\",\n key: \"install.path\",\n message: isEphemeral\n ? `codealmanac running from ephemeral npx location: ${installPath}`\n : `codealmanac installed at ${installPath}`,\n fix: isEphemeral\n ? \"run: npm install -g codealmanac (to make the install permanent)\"\n : undefined,\n };\n}\n\nfunction describeAuth(auth: ClaudeAuthStatus): Check {\n if (auth.loggedIn) {\n if (auth.authMethod === \"apiKey\") {\n return {\n status: \"ok\",\n key: \"install.auth\",\n message: \"claude auth: ANTHROPIC_API_KEY set\",\n };\n }\n const who = auth.email ?? \"Claude account\";\n const plan =\n auth.subscriptionType !== undefined\n ? ` (${auth.subscriptionType} subscription)`\n : \"\";\n return {\n status: \"ok\",\n key: \"install.auth\",\n message: `claude auth: ${who}${plan}`,\n };\n }\n if (\n process.env.ANTHROPIC_API_KEY !== undefined &&\n process.env.ANTHROPIC_API_KEY.length > 0\n ) {\n return {\n status: \"ok\",\n key: \"install.auth\",\n message: \"claude auth: ANTHROPIC_API_KEY set\",\n };\n }\n return {\n status: \"problem\",\n key: \"install.auth\",\n message: \"claude auth: not signed in\",\n fix: \"run: claude auth login --claudeai (or export ANTHROPIC_API_KEY)\",\n };\n}\n\nasync function describeHook(settingsPath: string): Promise<Check> {\n if (!existsSync(settingsPath)) {\n return {\n status: \"problem\",\n key: \"install.hook\",\n message: \"SessionEnd hook not installed\",\n fix: \"run: almanac setup --yes\",\n };\n }\n try {\n const raw = await readFile(settingsPath, \"utf8\");\n const parsed = JSON.parse(raw) as {\n hooks?: {\n SessionEnd?: {\n command?: string;\n hooks?: { command?: string }[];\n }[];\n };\n };\n const entries = parsed.hooks?.SessionEnd ?? [];\n const found = entries.some((e) => {\n if (\n typeof e?.command === \"string\" &&\n e.command.endsWith(\"almanac-capture.sh\")\n ) {\n return true;\n }\n if (Array.isArray(e?.hooks)) {\n return e.hooks.some(\n (h) =>\n typeof h?.command === \"string\" &&\n h.command.endsWith(\"almanac-capture.sh\"),\n );\n }\n return false;\n });\n if (!found) {\n return {\n status: \"problem\",\n key: \"install.hook\",\n message: \"SessionEnd hook not installed\",\n fix: \"run: almanac setup --yes\",\n };\n }\n return {\n status: \"ok\",\n key: \"install.hook\",\n message: `SessionEnd hook installed at ${settingsPath}`,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n status: \"problem\",\n key: \"install.hook\",\n message: `could not read ${settingsPath}: ${msg}`,\n fix: \"check the file for malformed JSON\",\n };\n }\n}\n\nfunction describeGuides(claudeDir: string): Check {\n const mini = path.join(claudeDir, \"codealmanac.md\");\n const ref = path.join(claudeDir, \"codealmanac-reference.md\");\n const haveMini = existsSync(mini);\n const haveRef = existsSync(ref);\n if (haveMini && haveRef) {\n return {\n status: \"ok\",\n key: \"install.guides\",\n message: `Agent guides installed (${path.basename(mini)}, ${path.basename(ref)})`,\n };\n }\n const missing = [\n haveMini ? null : \"codealmanac.md\",\n haveRef ? null : \"codealmanac-reference.md\",\n ].filter((s): s is string => s !== null);\n return {\n status: \"problem\",\n key: \"install.guides\",\n message: `Agent guides missing (${missing.join(\", \")})`,\n fix: \"run: almanac setup --yes\",\n };\n}\n\nasync function describeImportLine(claudeDir: string): Promise<Check> {\n const claudeMd = path.join(claudeDir, \"CLAUDE.md\");\n if (!existsSync(claudeMd)) {\n return {\n status: \"problem\",\n key: \"install.import\",\n message: \"CLAUDE.md import not present (no ~/.claude/CLAUDE.md)\",\n fix: \"run: almanac setup --yes\",\n };\n }\n try {\n const contents = await readFile(claudeMd, \"utf8\");\n const lines = contents.split(/\\r?\\n/).map((l) => l.trim());\n const present = lines.some((line) => {\n if (line === IMPORT_LINE) return true;\n if (!line.startsWith(IMPORT_LINE)) return false;\n const next = line[IMPORT_LINE.length];\n return next === \" \" || next === \"\\t\";\n });\n if (present) {\n return {\n status: \"ok\",\n key: \"install.import\",\n message: \"CLAUDE.md import present\",\n };\n }\n return {\n status: \"problem\",\n key: \"install.import\",\n message: \"CLAUDE.md import line missing\",\n fix: \"run: almanac setup --yes\",\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n status: \"problem\",\n key: \"install.import\",\n message: `could not read ${claudeMd}: ${msg}`,\n };\n }\n}\n\nasync function describeCodexInstructions(codexDir: string): Promise<Check> {\n const agentsFile = await resolveCodexAgentsPath(codexDir);\n if (!existsSync(agentsFile)) {\n return {\n status: \"problem\",\n key: \"install.codexInstructions\",\n message: `Codex AGENTS instructions missing (${path.basename(agentsFile)} not found)`,\n fix: \"run: almanac setup --yes\",\n };\n }\n try {\n const contents = await readFile(agentsFile, \"utf8\");\n if (hasCodexInstructions(contents)) {\n return {\n status: \"ok\",\n key: \"install.codexInstructions\",\n message: `Codex AGENTS instructions present (${path.basename(agentsFile)})`,\n };\n }\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n status: \"problem\",\n key: \"install.codexInstructions\",\n message: `could not read ${agentsFile}: ${msg}`,\n };\n }\n\n return {\n status: \"problem\",\n key: \"install.codexInstructions\",\n message: `Codex AGENTS instructions missing (${path.basename(agentsFile)})`,\n fix: \"run: almanac setup --yes\",\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport {\n checkClaudeAuth,\n type ClaudeAuthStatus,\n type SpawnCliFn,\n} from \"../../agent/providers/claude/index.js\";\nimport type { SqliteProbeResult } from \"./types.js\";\n\n// Single `createRequire` instance — used by package/binding probes.\nconst req = createRequire(import.meta.url);\n\n/**\n * Detect where codealmanac is installed by walking up from the running\n * module until we find a `package.json` whose `name` is `codealmanac`.\n */\nexport function detectInstallPath(): string | null {\n try {\n const here = fileURLToPath(import.meta.url);\n let dir = path.dirname(here);\n for (let i = 0; i < 6; i++) {\n const pkgPath = path.join(dir, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const raw = readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(raw) as { name?: unknown };\n if (pkg.name === \"codealmanac\") return dir;\n } catch {\n // ignore — keep walking\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Classify the detected install path as permanent or ephemeral.\n * Ephemeral locations (npm npx cache, pnpm dlx cache, /tmp/) are valid\n * installs but will disappear when the cache is evicted or the machine\n * reboots. Doctor reports them as `info` rather than `ok`.\n */\nexport function classifyInstallPath(\n raw: string | null,\n): { installPath: string | null; isEphemeral: boolean } {\n if (raw === null) return { installPath: null, isEphemeral: false };\n const home = homedir();\n const ephemeralPrefixes = [\n path.join(home, \".npm\", \"_npx\"),\n path.join(home, \".local\", \"share\", \"pnpm\", \"dlx\"),\n \"/tmp/\",\n \"/var/folders/\",\n ];\n const isEphemeral = ephemeralPrefixes.some((p) => raw.startsWith(p));\n return { installPath: raw, isEphemeral };\n}\n\n/**\n * Probe the better-sqlite3 native binding by opening an in-memory DB.\n */\nexport function probeBetterSqlite3(): SqliteProbeResult {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const Database = req(\"better-sqlite3\") as typeof import(\"better-sqlite3\");\n const db = new Database(\":memory:\");\n db.close();\n return { ok: true, summary: \"native binding loads cleanly\" };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n const firstLine = msg.split(\"\\n\")[0] ?? msg;\n return { ok: false, summary: firstLine };\n }\n}\n\nexport async function safeCheckAuth(\n spawnCli?: SpawnCliFn,\n): Promise<ClaudeAuthStatus> {\n try {\n return await checkClaudeAuth(spawnCli);\n } catch {\n return { loggedIn: false };\n }\n}\n\nexport function readPackageVersion(): string | null {\n const candidates = [\n \"../../../package.json\",\n \"../../package.json\",\n \"../package.json\",\n ];\n for (const candidate of candidates) {\n try {\n const pkg = req(candidate) as { version?: unknown };\n if (typeof pkg.version === \"string\" && pkg.version.length > 0) {\n return pkg.version;\n }\n } catch {\n // Fall through to the next runtime layout candidate.\n }\n }\n return null;\n}\n","import { buildProviderSetupView } from \"../../agent/provider-view.js\";\nimport { checkClaudeAuth } from \"../../agent/providers/claude/index.js\";\nimport type { ProviderStatus } from \"../../agent/types.js\";\nimport { isCursorEnabled } from \"../../update/config.js\";\nimport type { AgentDoctorCheck, DoctorOptions } from \"./types.js\";\n\nexport async function gatherAgentChecks(\n options: DoctorOptions,\n): Promise<AgentDoctorCheck[]> {\n const view = await buildProviderSetupView({\n spawnCli: options.spawnCli,\n statuses:\n options.providerStatuses ??\n (options.spawnCli === undefined\n ? undefined\n : await injectedProviderStatuses(options)),\n });\n return view.choices.map((choice) => {\n return {\n status: choice.ready ? \"ok\" : \"problem\",\n id: choice.id,\n label: choice.label,\n readiness: choice.readiness,\n selected: choice.selected,\n recommended: choice.recommended,\n installed: choice.installed,\n authenticated: choice.authenticated,\n model: choice.effectiveModel,\n providerDefaultModel: choice.providerDefaultModel,\n configuredModel: choice.configuredModel,\n account: choice.account,\n detail: choice.detail,\n fix: choice.fixCommand ?? undefined,\n };\n });\n}\n\nasync function injectedProviderStatuses(\n options: DoctorOptions,\n): Promise<ProviderStatus[]> {\n const auth = await checkClaudeAuth(options.spawnCli);\n const hasApiKey =\n process.env.ANTHROPIC_API_KEY !== undefined &&\n process.env.ANTHROPIC_API_KEY.length > 0;\n const claudeReady = auth.loggedIn || hasApiKey;\n const statuses: ProviderStatus[] = [\n {\n id: \"claude\",\n installed: true,\n authenticated: claudeReady,\n detail: claudeReady\n ? auth.email ?? (hasApiKey ? \"ANTHROPIC_API_KEY set\" : \"logged in\")\n : \"not logged in\",\n },\n {\n id: \"codex\",\n installed: false,\n authenticated: false,\n detail: \"codex status not injected\",\n },\n ];\n if (isCursorEnabled()) {\n statuses.push({\n id: \"cursor\",\n installed: false,\n authenticated: false,\n detail: \"cursor-agent status not injected\",\n });\n }\n return statuses;\n}\n","import { readConfig } from \"../../update/config.js\";\nimport { readStateForDoctor } from \"../../update/schedule.js\";\nimport { isNewer } from \"../../update/semver.js\";\nimport { formatDuration } from \"./duration.js\";\nimport type { Check, DoctorOptions } from \"./types.js\";\n\nexport async function gatherUpdateChecks(\n options: DoctorOptions,\n installedVersion: string,\n): Promise<Check[]> {\n const checks: Check[] = [];\n const state = readStateForDoctor(options.updateStatePath);\n const config = await readConfig(options.updateConfigPath);\n\n if (state === null || state.latest_version.length === 0) {\n checks.push({\n status: \"info\",\n key: \"update.status\",\n message: `on ${installedVersion}; no update check has run yet`,\n fix: \"run: almanac update --check\",\n });\n } else if (isNewer(state.latest_version, installedVersion)) {\n const dismissed = state.dismissed_versions.includes(state.latest_version)\n ? \" (dismissed — run `almanac update` to install anyway)\"\n : \"\";\n checks.push({\n status: \"problem\",\n key: \"update.status\",\n message:\n `${state.latest_version} available (you're on ${installedVersion})${dismissed}`,\n fix: \"run: almanac update\",\n });\n } else {\n checks.push({\n status: \"ok\",\n key: \"update.status\",\n message: `on latest (${installedVersion})`,\n });\n }\n\n if (state !== null && state.last_check_at > 0) {\n const now = (options.now?.() ?? new Date()).getTime();\n const ageMs = now - state.last_check_at * 1000;\n const failedSuffix =\n state.last_fetch_failed_at !== undefined &&\n state.last_fetch_failed_at === state.last_check_at\n ? \" (last attempt failed — will retry next invocation)\"\n : \"\";\n checks.push({\n status: \"info\",\n key: \"update.last_check\",\n message: `last checked: ${formatDuration(ageMs)} ago${failedSuffix}`,\n });\n } else {\n checks.push({\n status: \"info\",\n key: \"update.last_check\",\n message: \"last checked: never\",\n });\n }\n\n checks.push({\n status: \"info\",\n key: \"update.notifier\",\n message: `update notifier: ${config.update_notifier ? \"enabled\" : \"disabled\"}`,\n fix: config.update_notifier\n ? undefined\n : \"run: almanac config set update_notifier true\",\n });\n\n if (state !== null && state.dismissed_versions.length > 0) {\n checks.push({\n status: \"info\",\n key: \"update.dismissed\",\n message: `dismissed versions: ${state.dismissed_versions.join(\", \")}`,\n });\n }\n\n return checks;\n}\n","import { formatReport } from \"./doctor-checks/format.js\";\nimport { gatherInstallChecks } from \"./doctor-checks/install.js\";\nimport { readPackageVersion } from \"./doctor-checks/probes.js\";\nimport type {\n Check,\n CheckStatus,\n AgentDoctorCheck,\n DoctorOptions,\n DoctorReport,\n DoctorResult,\n SqliteProbeResult,\n} from \"./doctor-checks/types.js\";\nimport { gatherAgentChecks } from \"./doctor-checks/agents.js\";\nimport { gatherUpdateChecks } from \"./doctor-checks/updates.js\";\n\nexport type {\n Check,\n CheckStatus,\n DoctorOptions,\n DoctorReport,\n DoctorResult,\n SqliteProbeResult,\n};\n\n/**\n * `almanac doctor` — install + wiki health report.\n *\n * Separate from `almanac health` (which checks graph integrity of a\n * specific wiki). `doctor` answers the \"is this install even set up\n * correctly?\" question that users hit when first trying the tool or when\n * sessions silently stop getting captured.\n *\n * This file is the command composition root. The section-specific probes\n * and formatting live in `doctor-checks/` so each durable fact has one\n * obvious owner.\n */\nexport async function runDoctor(\n options: DoctorOptions,\n): Promise<DoctorResult> {\n const version =\n options.versionOverride ?? readPackageVersion() ?? \"unknown\";\n\n const install: Check[] = options.wikiOnly === true\n ? []\n : await gatherInstallChecks(options);\n\n const agents: AgentDoctorCheck[] = options.wikiOnly === true\n ? []\n : await gatherAgentChecks(options);\n\n const updates: Check[] = options.wikiOnly === true\n ? []\n : await gatherUpdateChecks(options, version);\n\n const wiki: Check[] = options.installOnly === true\n ? []\n : await safeGatherWikiChecks(options);\n\n const report: DoctorReport = { version, install, agents, updates, wiki };\n\n if (options.json === true) {\n return {\n stdout: `${JSON.stringify(report, null, 2)}\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n }\n\n return {\n stdout: formatReport(report, options),\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nasync function safeGatherWikiChecks(\n options: DoctorOptions,\n): Promise<Check[]> {\n try {\n const { gatherWikiChecks } = await import(\"./doctor-checks/wiki.js\");\n return await gatherWikiChecks(options);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return [\n {\n status: \"problem\",\n key: \"wiki.checks\",\n message: `could not run wiki checks: ${msg.split(\"\\n\")[0] ?? msg}`,\n fix: \"run: npm rebuild better-sqlite3 (in the install directory)\",\n },\n ];\n }\n}\n"],"mappings":"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","names":["existsSync","homedir","path","path","homedir","existsSync"]}
@@ -2,12 +2,15 @@
2
2
  import {
3
3
  buildProviderSetupView,
4
4
  parseAgentSelection
5
- } from "./chunk-BF2J4XTC.js";
5
+ } from "./chunk-J7DNV2DH.js";
6
6
  import {
7
+ disabledAgentProviderMessage,
8
+ formatEnabledAgentProviderList,
7
9
  isAgentProviderId,
10
+ isEnabledAgentProviderId,
8
11
  readConfig,
9
12
  writeConfig
10
- } from "./chunk-P5WGG4FJ.js";
13
+ } from "./chunk-3E7JNMTZ.js";
11
14
 
12
15
  // src/commands/agents.ts
13
16
  async function runAgentsList() {
@@ -30,7 +33,8 @@ async function runAgentsList() {
30
33
  );
31
34
  }
32
35
  lines.push(
33
- "\nUse: almanac agents use <claude|codex|cursor>",
36
+ `
37
+ Use: almanac agents use <${formatEnabledAgentProviderList().replaceAll(", ", "|")}>`,
34
38
  "Set model: almanac agents model <provider> <model>"
35
39
  );
36
40
  return { stdout: `${lines.join("\n")}
@@ -72,12 +76,15 @@ async function setDefaultAgent(opts) {
72
76
  if (parsed.provider === null) {
73
77
  return {
74
78
  stdout: "",
75
- stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
79
+ stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: ${formatEnabledAgentProviderList()}.
76
80
  `,
77
81
  exitCode: 1
78
82
  };
79
83
  }
80
84
  const provider = parsed.provider;
85
+ if (!isEnabledAgentProviderId(provider)) {
86
+ return disabledProviderResult(provider);
87
+ }
81
88
  const config = await readConfig();
82
89
  const next = {
83
90
  ...config,
@@ -116,11 +123,14 @@ async function setProviderModel(opts) {
116
123
  if (!isAgentProviderId(opts.provider)) {
117
124
  return {
118
125
  stdout: "",
119
- stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: claude, codex, cursor.
126
+ stderr: `almanac: unknown agent '${opts.provider}'. Expected one of: ${formatEnabledAgentProviderList()}.
120
127
  `,
121
128
  exitCode: 1
122
129
  };
123
130
  }
131
+ if (!isEnabledAgentProviderId(opts.provider)) {
132
+ return disabledProviderResult(opts.provider);
133
+ }
124
134
  if (opts.defaultModel !== true && (opts.model === void 0 || opts.model.length === 0)) {
125
135
  return {
126
136
  stdout: "",
@@ -156,6 +166,14 @@ function normalizeRequestedModel(opts) {
156
166
  if (opts.model === "default" || opts.model === "null") return null;
157
167
  return opts.model;
158
168
  }
169
+ function disabledProviderResult(provider) {
170
+ return {
171
+ stdout: "",
172
+ stderr: `almanac: ${disabledAgentProviderMessage(provider)}
173
+ `,
174
+ exitCode: 1
175
+ };
176
+ }
159
177
  function readinessLabel(readiness) {
160
178
  switch (readiness) {
161
179
  case "ready":
@@ -184,4 +202,4 @@ export {
184
202
  runDeprecatedSetAgentModel,
185
203
  runAgentsModel
186
204
  };
187
- //# sourceMappingURL=chunk-UU6FBRQO.js.map
205
+ //# sourceMappingURL=chunk-GPFVEF6V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/agents.ts"],"sourcesContent":["import {\n buildProviderSetupView,\n parseAgentSelection,\n type ProviderReadiness,\n} from \"../agent/provider-view.js\";\nimport {\n disabledAgentProviderMessage,\n formatEnabledAgentProviderList,\n isAgentProviderId,\n isEnabledAgentProviderId,\n readConfig,\n writeConfig,\n type AgentProviderId,\n} from \"../update/config.js\";\n\nexport interface AgentsResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport async function runAgentsList(): Promise<AgentsResult> {\n const view = await buildProviderSetupView();\n const lines = [\"codealmanac agents\\n\"];\n for (const choice of view.choices) {\n const selected = choice.selected ? \"*\" : \" \";\n const recommended = choice.recommended ? \"recommended\" : \"\";\n const model = choice.effectiveModel ?? \"provider default\";\n const detail = choice.account ?? choice.fixCommand ?? choice.detail;\n lines.push(\n [\n selected,\n choice.label.padEnd(6),\n readinessLabel(choice.readiness).padEnd(15),\n recommended.padEnd(11),\n `model: ${model}`.padEnd(31),\n detail,\n ].join(\" \").trimEnd(),\n );\n }\n lines.push(\n `\\nUse: almanac agents use <${formatEnabledAgentProviderList().replaceAll(\", \", \"|\")}>`,\n \"Set model: almanac agents model <provider> <model>\",\n );\n return { stdout: `${lines.join(\"\\n\")}\\n`, stderr: \"\", exitCode: 0 };\n}\n\nexport async function runAgentsDoctor(): Promise<AgentsResult> {\n const view = await buildProviderSetupView();\n const lines = [\"codealmanac agent doctor\\n\"];\n for (const choice of view.choices) {\n lines.push(`${choice.ready ? \"✓\" : \"✗\"} ${choice.label}`);\n lines.push(` status: ${readinessLabel(choice.readiness)}`);\n lines.push(` model: ${choice.effectiveModel ?? \"provider default\"}`);\n if (choice.account !== null) {\n lines.push(` account: ${choice.account}`);\n } else if (choice.detail.length > 0) {\n lines.push(` detail: ${choice.detail}`);\n }\n if (choice.fixCommand !== null) lines.push(` fix: ${choice.fixCommand}`);\n lines.push(\"\");\n }\n return { stdout: `${lines.join(\"\\n\").trimEnd()}\\n`, stderr: \"\", exitCode: 0 };\n}\n\nexport interface SetDefaultAgentOptions {\n provider: string;\n}\n\nexport async function runSetDefaultAgent(\n opts: SetDefaultAgentOptions,\n): Promise<AgentsResult> {\n return setDefaultAgent(opts);\n}\n\nexport async function runDeprecatedSetDefaultAgent(\n opts: SetDefaultAgentOptions,\n): Promise<AgentsResult> {\n return withDeprecation(\n await setDefaultAgent(opts),\n \"almanac set default-agent <provider>\",\n \"almanac agents use <provider>\",\n );\n}\n\nexport async function runAgentsUse(opts: SetDefaultAgentOptions): Promise<AgentsResult> {\n return setDefaultAgent(opts);\n}\n\nasync function setDefaultAgent(\n opts: SetDefaultAgentOptions,\n): Promise<AgentsResult> {\n const parsed = parseAgentSelection(opts.provider);\n if (parsed.provider === null) {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown agent '${opts.provider}'. ` +\n `Expected one of: ${formatEnabledAgentProviderList()}.\\n`,\n exitCode: 1,\n };\n }\n const provider = parsed.provider;\n if (!isEnabledAgentProviderId(provider)) {\n return disabledProviderResult(provider);\n }\n const config = await readConfig();\n const next = {\n ...config,\n agent: {\n ...config.agent,\n default: provider,\n models:\n parsed.model === undefined\n ? config.agent.models\n : {\n ...config.agent.models,\n [provider]: parsed.model,\n },\n },\n };\n await writeConfig(next);\n return {\n stdout:\n parsed.model === undefined\n ? `codealmanac: default agent set to ${provider}.\\n`\n : `codealmanac: default agent set to ${provider}; ${provider} model set to ${parsed.model}.\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nexport async function runSetAgentModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n return setProviderModel(opts);\n}\n\nexport async function runDeprecatedSetAgentModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n return withDeprecation(\n await setProviderModel(opts),\n \"almanac set model <provider> <model>\",\n \"almanac agents model <provider> <model>\",\n );\n}\n\nexport async function runAgentsModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n return setProviderModel(opts);\n}\n\nasync function setProviderModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): Promise<AgentsResult> {\n if (!isAgentProviderId(opts.provider)) {\n return {\n stdout: \"\",\n stderr:\n `almanac: unknown agent '${opts.provider}'. ` +\n `Expected one of: ${formatEnabledAgentProviderList()}.\\n`,\n exitCode: 1,\n };\n }\n if (!isEnabledAgentProviderId(opts.provider)) {\n return disabledProviderResult(opts.provider);\n }\n if (\n opts.defaultModel !== true &&\n (opts.model === undefined || opts.model.length === 0)\n ) {\n return {\n stdout: \"\",\n stderr:\n `almanac: missing model for ${opts.provider}. ` +\n \"Pass a model id or --default.\\n\",\n exitCode: 1,\n };\n }\n const provider = opts.provider as AgentProviderId;\n const config = await readConfig();\n const model = normalizeRequestedModel(opts);\n await writeConfig({\n ...config,\n agent: {\n ...config.agent,\n models: {\n ...config.agent.models,\n [provider]: model,\n },\n },\n });\n return {\n stdout:\n model === null\n ? `codealmanac: ${provider} model reset to provider default.\\n`\n : `codealmanac: ${provider} model set to ${model}.\\n`,\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nfunction normalizeRequestedModel(opts: {\n provider: string;\n model?: string;\n defaultModel?: boolean;\n}): string | null {\n if (opts.defaultModel === true) return null;\n if (opts.model === undefined || opts.model.length === 0) return null;\n if (opts.model === \"default\" || opts.model === \"null\") return null;\n return opts.model;\n}\n\nfunction disabledProviderResult(provider: string): AgentsResult {\n return {\n stdout: \"\",\n stderr: `almanac: ${disabledAgentProviderMessage(provider)}\\n`,\n exitCode: 1,\n };\n}\n\nfunction readinessLabel(readiness: ProviderReadiness): string {\n switch (readiness) {\n case \"ready\":\n return \"ready\";\n case \"missing\":\n return \"missing\";\n case \"not-authenticated\":\n return \"not ready\";\n }\n}\n\nfunction withDeprecation(\n result: AgentsResult,\n oldUsage: string,\n newUsage: string,\n): AgentsResult {\n return {\n ...result,\n stderr:\n `almanac: warning: \\`${oldUsage}\\` is deprecated; use \\`${newUsage}\\`.\\n` +\n result.stderr,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,eAAsB,gBAAuC;AAC3D,QAAM,OAAO,MAAM,uBAAuB;AAC1C,QAAM,QAAQ,CAAC,sBAAsB;AACrC,aAAW,UAAU,KAAK,SAAS;AACjC,UAAM,WAAW,OAAO,WAAW,MAAM;AACzC,UAAM,cAAc,OAAO,cAAc,gBAAgB;AACzD,UAAM,QAAQ,OAAO,kBAAkB;AACvC,UAAM,SAAS,OAAO,WAAW,OAAO,cAAc,OAAO;AAC7D,UAAM;AAAA,MACJ;AAAA,QACE;AAAA,QACA,OAAO,MAAM,OAAO,CAAC;AAAA,QACrB,eAAe,OAAO,SAAS,EAAE,OAAO,EAAE;AAAA,QAC1C,YAAY,OAAO,EAAE;AAAA,QACrB,UAAU,KAAK,GAAG,OAAO,EAAE;AAAA,QAC3B;AAAA,MACF,EAAE,KAAK,GAAG,EAAE,QAAQ;AAAA,IACtB;AAAA,EACF;AACA,QAAM;AAAA,IACJ;AAAA,2BAA8B,+BAA+B,EAAE,WAAW,MAAM,GAAG,CAAC;AAAA,IACpF;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA,GAAM,QAAQ,IAAI,UAAU,EAAE;AACpE;AAEA,eAAsB,kBAAyC;AAC7D,QAAM,OAAO,MAAM,uBAAuB;AAC1C,QAAM,QAAQ,CAAC,4BAA4B;AAC3C,aAAW,UAAU,KAAK,SAAS;AACjC,UAAM,KAAK,GAAG,OAAO,QAAQ,WAAM,QAAG,IAAI,OAAO,KAAK,EAAE;AACxD,UAAM,KAAK,aAAa,eAAe,OAAO,SAAS,CAAC,EAAE;AAC1D,UAAM,KAAK,YAAY,OAAO,kBAAkB,kBAAkB,EAAE;AACpE,QAAI,OAAO,YAAY,MAAM;AAC3B,YAAM,KAAK,cAAc,OAAO,OAAO,EAAE;AAAA,IAC3C,WAAW,OAAO,OAAO,SAAS,GAAG;AACnC,YAAM,KAAK,aAAa,OAAO,MAAM,EAAE;AAAA,IACzC;AACA,QAAI,OAAO,eAAe,KAAM,OAAM,KAAK,UAAU,OAAO,UAAU,EAAE;AACxE,UAAM,KAAK,EAAE;AAAA,EACf;AACA,SAAO,EAAE,QAAQ,GAAG,MAAM,KAAK,IAAI,EAAE,QAAQ,CAAC;AAAA,GAAM,QAAQ,IAAI,UAAU,EAAE;AAC9E;AAMA,eAAsB,mBACpB,MACuB;AACvB,SAAO,gBAAgB,IAAI;AAC7B;AAEA,eAAsB,6BACpB,MACuB;AACvB,SAAO;AAAA,IACL,MAAM,gBAAgB,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,aAAa,MAAqD;AACtF,SAAO,gBAAgB,IAAI;AAC7B;AAEA,eAAe,gBACb,MACuB;AACvB,QAAM,SAAS,oBAAoB,KAAK,QAAQ;AAChD,MAAI,OAAO,aAAa,MAAM;AAC5B,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,2BAA2B,KAAK,QAAQ,uBACpB,+BAA+B,CAAC;AAAA;AAAA,MACtD,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,WAAW,OAAO;AACxB,MAAI,CAAC,yBAAyB,QAAQ,GAAG;AACvC,WAAO,uBAAuB,QAAQ;AAAA,EACxC;AACA,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG,OAAO;AAAA,MACV,SAAS;AAAA,MACT,QACE,OAAO,UAAU,SACb,OAAO,MAAM,SACb;AAAA,QACE,GAAG,OAAO,MAAM;AAAA,QAChB,CAAC,QAAQ,GAAG,OAAO;AAAA,MACrB;AAAA,IACR;AAAA,EACF;AACA,QAAM,YAAY,IAAI;AACtB,SAAO;AAAA,IACL,QACE,OAAO,UAAU,SACb,qCAAqC,QAAQ;AAAA,IAC7C,qCAAqC,QAAQ,KAAK,QAAQ,iBAAiB,OAAO,KAAK;AAAA;AAAA,IAC7F,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;AAEA,eAAsB,iBAAiB,MAIb;AACxB,SAAO,iBAAiB,IAAI;AAC9B;AAEA,eAAsB,2BAA2B,MAIvB;AACxB,SAAO;AAAA,IACL,MAAM,iBAAiB,IAAI;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,eAAe,MAIX;AACxB,SAAO,iBAAiB,IAAI;AAC9B;AAEA,eAAe,iBAAiB,MAIN;AACxB,MAAI,CAAC,kBAAkB,KAAK,QAAQ,GAAG;AACrC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,2BAA2B,KAAK,QAAQ,uBACpB,+BAA+B,CAAC;AAAA;AAAA,MACtD,UAAU;AAAA,IACZ;AAAA,EACF;AACA,MAAI,CAAC,yBAAyB,KAAK,QAAQ,GAAG;AAC5C,WAAO,uBAAuB,KAAK,QAAQ;AAAA,EAC7C;AACA,MACE,KAAK,iBAAiB,SACrB,KAAK,UAAU,UAAa,KAAK,MAAM,WAAW,IACnD;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QACE,8BAA8B,KAAK,QAAQ;AAAA;AAAA,MAE7C,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,WAAW,KAAK;AACtB,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,QAAQ,wBAAwB,IAAI;AAC1C,QAAM,YAAY;AAAA,IAChB,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG,OAAO;AAAA,MACV,QAAQ;AAAA,QACN,GAAG,OAAO,MAAM;AAAA,QAChB,CAAC,QAAQ,GAAG;AAAA,MACd;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL,QACE,UAAU,OACN,gBAAgB,QAAQ;AAAA,IACxB,gBAAgB,QAAQ,iBAAiB,KAAK;AAAA;AAAA,IACpD,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;AAEA,SAAS,wBAAwB,MAIf;AAChB,MAAI,KAAK,iBAAiB,KAAM,QAAO;AACvC,MAAI,KAAK,UAAU,UAAa,KAAK,MAAM,WAAW,EAAG,QAAO;AAChE,MAAI,KAAK,UAAU,aAAa,KAAK,UAAU,OAAQ,QAAO;AAC9D,SAAO,KAAK;AACd;AAEA,SAAS,uBAAuB,UAAgC;AAC9D,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ,YAAY,6BAA6B,QAAQ,CAAC;AAAA;AAAA,IAC1D,UAAU;AAAA,EACZ;AACF;AAEA,SAAS,eAAe,WAAsC;AAC5D,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEA,SAAS,gBACP,QACA,UACA,UACc;AACd,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QACE,uBAAuB,QAAQ,2BAA2B,QAAQ;AAAA,IAClE,OAAO;AAAA,EACX;AACF;","names":[]}
@@ -7,7 +7,7 @@ import {
7
7
  getConfigPath,
8
8
  getLegacyConfigPath,
9
9
  parseConfigText
10
- } from "./chunk-P5WGG4FJ.js";
10
+ } from "./chunk-3E7JNMTZ.js";
11
11
 
12
12
  // src/update/schedule.ts
13
13
  import { spawn } from "child_process";
@@ -86,4 +86,4 @@ export {
86
86
  runInternalUpdateCheck,
87
87
  readStateForDoctor
88
88
  };
89
- //# sourceMappingURL=chunk-TILAKDN6.js.map
89
+ //# sourceMappingURL=chunk-HJ3WREGP.js.map
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- AGENT_PROVIDER_IDS,
3
+ getEnabledAgentProviderIds,
4
4
  isAgentProviderId,
5
5
  readConfig
6
- } from "./chunk-P5WGG4FJ.js";
6
+ } from "./chunk-3E7JNMTZ.js";
7
7
 
8
8
  // src/agent/providers/claude/index.ts
9
9
  import { query } from "@anthropic-ai/claude-agent-sdk";
@@ -147,8 +147,52 @@ var claudeProvider = {
147
147
  metadata,
148
148
  checkStatus,
149
149
  assertReady,
150
- run
150
+ run,
151
+ modelChoices
151
152
  };
153
+ var CLAUDE_MODELS = [
154
+ {
155
+ value: "claude-opus-4-7",
156
+ label: "Opus 4.7",
157
+ recommended: false
158
+ },
159
+ {
160
+ value: "claude-sonnet-4-6",
161
+ label: "Sonnet 4.6",
162
+ recommended: true
163
+ },
164
+ {
165
+ value: "claude-haiku-4-5-20251001",
166
+ label: "Haiku 4.5",
167
+ recommended: false
168
+ }
169
+ ];
170
+ function modelChoices(args) {
171
+ const choices = [];
172
+ if (args.configuredModel !== null && !CLAUDE_MODELS.some((model) => model.value === args.configuredModel)) {
173
+ choices.push({
174
+ value: args.configuredModel,
175
+ label: args.configuredModel,
176
+ recommended: false,
177
+ source: "configured"
178
+ });
179
+ }
180
+ for (const model of CLAUDE_MODELS) {
181
+ choices.push({
182
+ value: model.value,
183
+ label: model.label,
184
+ recommended: model.recommended,
185
+ source: "catalog"
186
+ });
187
+ }
188
+ choices.push({
189
+ value: "__custom__",
190
+ label: "Enter a model name",
191
+ recommended: false,
192
+ source: "custom"
193
+ });
194
+ return choices;
195
+ }
152
196
  async function run(opts) {
153
197
  const claudeExecutable = resolveClaudeExecutable();
154
198
  const q = query({
@@ -277,6 +321,47 @@ ${stderr}`.trim();
277
321
  });
278
322
  });
279
323
  }
324
+ function runInjectedStatusCommand(spawnCli, args) {
325
+ return new Promise((resolve) => {
326
+ let stdout = "";
327
+ let stderr = "";
328
+ let settled = false;
329
+ const settle = (value) => {
330
+ if (settled) return;
331
+ settled = true;
332
+ resolve(value);
333
+ };
334
+ try {
335
+ const child = spawnCli(args);
336
+ child.stdout.on("data", (chunk) => {
337
+ stdout += chunk.toString();
338
+ });
339
+ child.stderr.on("data", (chunk) => {
340
+ stderr += chunk.toString();
341
+ });
342
+ child.on("error", (err) => {
343
+ settle({
344
+ ok: false,
345
+ detail: err instanceof Error ? err.message : String(err)
346
+ });
347
+ });
348
+ child.on("close", (codeOrError) => {
349
+ const code = typeof codeOrError === "number" ? codeOrError : 1;
350
+ const text = `${stdout}
351
+ ${stderr}`.trim();
352
+ settle({
353
+ ok: code === 0,
354
+ detail: text.split("\n").find((line) => line.trim().length > 0)?.trim() ?? (code === 0 ? "ready" : `${args[0] ?? "command"} exited ${code}`)
355
+ });
356
+ });
357
+ } catch (err) {
358
+ settle({
359
+ ok: false,
360
+ detail: err instanceof Error ? err.message : String(err)
361
+ });
362
+ }
363
+ });
364
+ }
280
365
 
281
366
  // src/agent/providers/jsonl-cli.ts
282
367
  import { spawn as spawn3 } from "child_process";
@@ -428,8 +513,100 @@ var codexProvider = {
428
513
  metadata: metadata2,
429
514
  checkStatus: checkStatus2,
430
515
  assertReady: assertReady2,
431
- run: run2
516
+ run: run2,
517
+ modelChoices: modelChoices2
432
518
  };
519
+ var CODEX_MODEL_ORDER = [
520
+ "gpt-5.5",
521
+ "gpt-5.4",
522
+ "gpt-5.4-mini",
523
+ "gpt-5.3-codex"
524
+ ];
525
+ var CODEX_MODEL_LABELS = {
526
+ "gpt-5.5": "GPT-5.5",
527
+ "gpt-5.4": "GPT-5.4",
528
+ "gpt-5.4-mini": "GPT-5.4 Mini",
529
+ "gpt-5.3-codex": "GPT-5.3 Codex"
530
+ };
531
+ async function modelChoices2(args) {
532
+ const catalog = await readCodexModelCatalog(args.spawnCli);
533
+ const choices = [];
534
+ if (args.configuredModel !== null) {
535
+ choices.push({
536
+ value: args.configuredModel,
537
+ label: modelLabel(args.configuredModel, catalog),
538
+ recommended: false,
539
+ source: "configured"
540
+ });
541
+ }
542
+ for (const slug of CODEX_MODEL_ORDER) {
543
+ if (choices.some((choice) => choice.value === slug)) continue;
544
+ if (catalog !== void 0 && !catalog.some((model) => model.slug === slug)) {
545
+ continue;
546
+ }
547
+ choices.push({
548
+ value: slug,
549
+ label: modelLabel(slug, catalog),
550
+ recommended: slug === "gpt-5.4",
551
+ source: "catalog"
552
+ });
553
+ }
554
+ choices.push({
555
+ value: "__custom__",
556
+ label: "Enter a model name",
557
+ recommended: false,
558
+ source: "custom"
559
+ });
560
+ return choices;
561
+ }
562
+ async function readCodexModelCatalog(spawnCli) {
563
+ if (spawnCli === void 0) return void 0;
564
+ try {
565
+ const result = await collectSpawn(spawnCli(["codex", "debug", "models"]));
566
+ if (result.code !== 0) return void 0;
567
+ const parsed = JSON.parse(result.stdout);
568
+ if (parsed === null || typeof parsed !== "object") return void 0;
569
+ const models = parsed.models;
570
+ if (!Array.isArray(models)) return void 0;
571
+ const out = [];
572
+ for (const model of models) {
573
+ if (model === null || typeof model !== "object") continue;
574
+ const record = model;
575
+ if (record.visibility !== "list") continue;
576
+ if (typeof record.slug !== "string") continue;
577
+ out.push({
578
+ slug: record.slug,
579
+ displayName: typeof record.display_name === "string" ? record.display_name : record.slug
580
+ });
581
+ }
582
+ return out;
583
+ } catch {
584
+ return void 0;
585
+ }
586
+ }
587
+ function collectSpawn(child) {
588
+ return new Promise((resolve) => {
589
+ let stdout = "";
590
+ let settled = false;
591
+ const settle = (code) => {
592
+ if (settled) return;
593
+ settled = true;
594
+ resolve({ stdout, code });
595
+ };
596
+ child.stdout.on("data", (chunk) => {
597
+ stdout += chunk.toString();
598
+ });
599
+ child.on("error", () => {
600
+ settle(1);
601
+ });
602
+ child.on("close", (codeOrError) => {
603
+ settle(typeof codeOrError === "number" ? codeOrError ?? 1 : 1);
604
+ });
605
+ });
606
+ }
607
+ function modelLabel(slug, catalog) {
608
+ return CODEX_MODEL_LABELS[slug] ?? catalog?.find((model) => model.slug === slug)?.displayName ?? slug;
609
+ }
433
610
  async function run2(opts) {
434
611
  const args = [
435
612
  "exec",
@@ -453,8 +630,8 @@ async function run2(opts) {
453
630
  parseFinal: parseCodexFinal
454
631
  });
455
632
  }
456
- async function checkStatus2() {
457
- if (!commandExists(metadata2.executable)) {
633
+ async function checkStatus2(spawnCli) {
634
+ if (spawnCli === void 0 && !commandExists(metadata2.executable)) {
458
635
  return {
459
636
  id: metadata2.id,
460
637
  installed: false,
@@ -462,7 +639,11 @@ async function checkStatus2() {
462
639
  detail: `${metadata2.executable} not found on PATH`
463
640
  };
464
641
  }
465
- const auth = await runStatusCommand(metadata2.executable, ["login", "status"]);
642
+ const auth = spawnCli !== void 0 ? await runInjectedStatusCommand(spawnCli, [
643
+ metadata2.executable,
644
+ "login",
645
+ "status"
646
+ ]) : await runStatusCommand(metadata2.executable, ["login", "status"]);
466
647
  return {
467
648
  id: metadata2.id,
468
649
  installed: true,
@@ -470,8 +651,8 @@ async function checkStatus2() {
470
651
  detail: auth.detail
471
652
  };
472
653
  }
473
- async function assertReady2() {
474
- const status = await checkStatus2();
654
+ async function assertReady2(spawnCli) {
655
+ const status = await checkStatus2(spawnCli);
475
656
  if (!status.installed || !status.authenticated) {
476
657
  const err = new Error(`${status.id} not ready: ${status.detail}`);
477
658
  err.code = "AGENT_AUTH_MISSING";
@@ -549,8 +730,8 @@ async function run3(opts) {
549
730
  parseFinal: parseCursorFinal
550
731
  });
551
732
  }
552
- async function checkStatus3() {
553
- if (!commandExists(metadata3.executable)) {
733
+ async function checkStatus3(spawnCli) {
734
+ if (spawnCli === void 0 && !commandExists(metadata3.executable)) {
554
735
  return {
555
736
  id: metadata3.id,
556
737
  installed: false,
@@ -558,7 +739,10 @@ async function checkStatus3() {
558
739
  detail: `${metadata3.executable} not found on PATH`
559
740
  };
560
741
  }
561
- const auth = await runStatusCommand(metadata3.executable, ["status"]);
742
+ const auth = spawnCli !== void 0 ? await runInjectedStatusCommand(spawnCli, [
743
+ metadata3.executable,
744
+ "status"
745
+ ]) : await runStatusCommand(metadata3.executable, ["status"]);
562
746
  return {
563
747
  id: metadata3.id,
564
748
  installed: true,
@@ -566,8 +750,8 @@ async function checkStatus3() {
566
750
  detail: auth.detail
567
751
  };
568
752
  }
569
- async function assertReady3() {
570
- const status = await checkStatus3();
753
+ async function assertReady3(spawnCli) {
754
+ const status = await checkStatus3(spawnCli);
571
755
  if (!status.installed || !status.authenticated) {
572
756
  const err = new Error(`${status.id} not ready: ${status.detail}`);
573
757
  err.code = "AGENT_AUTH_MISSING";
@@ -593,7 +777,7 @@ async function assertAgentAuth(args) {
593
777
  }
594
778
  async function listProviderStatuses(spawnCli) {
595
779
  const out = [];
596
- for (const id of AGENT_PROVIDER_IDS) {
780
+ for (const id of getEnabledAgentProviderIds()) {
597
781
  out.push(await getAgentProvider(id).checkStatus(spawnCli));
598
782
  }
599
783
  return out;
@@ -636,13 +820,14 @@ async function buildProviderSetupView(opts = {}) {
636
820
  const statuses = opts.statuses ?? await listProviderStatuses(opts.spawnCli);
637
821
  const statusById = new Map(statuses.map((status) => [status.id, status]));
638
822
  const recommendedProvider = chooseRecommendedProvider(statuses);
639
- const choices = AGENT_PROVIDER_IDS.map((id) => {
823
+ const choices = [];
824
+ for (const id of getEnabledAgentProviderIds()) {
640
825
  const status = statusById.get(id) ?? missingStatus(id);
641
826
  const readiness = getReadiness(status);
642
827
  const configuredModel = normalizeModel(config.agent.models[id]);
643
828
  const providerDefaultModel = getProviderDefaultModel(id);
644
829
  const effectiveModel = configuredModel ?? providerDefaultModel;
645
- return {
830
+ choices.push({
646
831
  id,
647
832
  label: getProviderLabel(id),
648
833
  selected: id === config.agent.default,
@@ -657,16 +842,22 @@ async function buildProviderSetupView(opts = {}) {
657
842
  account: status.authenticated ? accountFromDetail(status.detail) : null,
658
843
  detail: status.detail,
659
844
  fixCommand: fixFor(id, readiness),
660
- modelChoices: buildProviderModelChoices(id, configuredModel)
661
- };
662
- });
845
+ modelChoices: await buildProviderModelChoices(id, configuredModel, {
846
+ spawnCli: opts.spawnCli
847
+ })
848
+ });
849
+ }
663
850
  return {
664
851
  defaultProvider: config.agent.default,
665
852
  recommendedProvider,
666
853
  choices
667
854
  };
668
855
  }
669
- function buildProviderModelChoices(id, configuredModel = null) {
856
+ function buildProviderModelChoices(id, configuredModel = null, opts = {}) {
857
+ const provider = getAgentProvider(id);
858
+ if (provider.modelChoices !== void 0) {
859
+ return provider.modelChoices({ configuredModel, spawnCli: opts.spawnCli });
860
+ }
670
861
  const choices = [];
671
862
  if (configuredModel !== null) {
672
863
  choices.push({
@@ -698,16 +889,16 @@ function buildProviderModelChoices(id, configuredModel = null) {
698
889
  }
699
890
  choices.push({
700
891
  value: "__custom__",
701
- label: "custom model id",
892
+ label: "Enter a model name",
702
893
  recommended: false,
703
894
  source: "custom"
704
895
  });
705
896
  return choices;
706
897
  }
707
898
  function chooseRecommendedProvider(statuses) {
708
- const ready = statuses.filter((status) => status.installed && status.authenticated).map((status) => status.id);
899
+ const ready = statuses.filter((status) => getReadiness(status) === "ready").map((status) => status.id);
709
900
  if (ready.includes("claude")) return "claude";
710
- for (const id of AGENT_PROVIDER_IDS) {
901
+ for (const id of getEnabledAgentProviderIds()) {
711
902
  if (ready.includes(id)) return id;
712
903
  }
713
904
  return "claude";
@@ -725,6 +916,9 @@ function parseAgentSelection(value) {
725
916
  }
726
917
  function getReadiness(status) {
727
918
  if (!status.installed) return "missing";
919
+ if (/not (logged|signed) in|not authenticated/i.test(status.detail)) {
920
+ return "not-authenticated";
921
+ }
728
922
  if (!status.authenticated) return "not-authenticated";
729
923
  return "ready";
730
924
  }
@@ -754,7 +948,6 @@ function missingStatus(id) {
754
948
 
755
949
  export {
756
950
  checkClaudeAuth,
757
- UNAUTHENTICATED_MESSAGE,
758
951
  DEFAULT_AGENT_MODEL,
759
952
  assertAgentAuth,
760
953
  getAgentProvider,
@@ -763,4 +956,4 @@ export {
763
956
  buildProviderModelChoices,
764
957
  parseAgentSelection
765
958
  };
766
- //# sourceMappingURL=chunk-BF2J4XTC.js.map
959
+ //# sourceMappingURL=chunk-J7DNV2DH.js.map