{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../../src/core/long-horizon/adaptive/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAOxE,eAAO,MAAM,iBAAiB,yBAAyB,CAAC;AAExD,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElF;AA+DD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAY5E;AAmLD,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D","sourcesContent":["/**\n * Adaptive runtime CLI surfaces.\n *\n * Deterministic, machine-readable diagnostics for the adaptive long-horizon\n * runtime. Follows the existing `jensen <namespace> <command>` dispatch pattern\n * (e.g. `jensen workspace`, `jensen doctor`). Reads durable run state from a\n * bounded on-disk state directory keyed by run id.\n *\n * Surfaces:\n *   jensen run budget <run-id>\n *   jensen run stats <run-id>\n *   jensen run strategies <run-id>\n *   jensen run stalls <run-id>\n *   jensen run criteria <run-id>\n *   jensen run subagents <run-id>\n *   jensen doctor routing\n *   jensen doctor budgets\n *   jensen skills list\n *   jensen skills inspect <name>\n *\n * Never exposes hidden reasoning, secrets, or raw provider credentials.\n */\n\nimport { existsSync, mkdirSync, readFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { BudgetLedger } from \"./budget-ledger.js\";\nimport { appendEntry, createBudgetLedger, resourcesOfBudget, sumResource } from \"./budget-ledger.js\";\nimport { BUILTIN_SKILLS, type BuiltinSkill } from \"./builtin-skills.js\";\nimport { createCapabilityRegistry, roleCompatibility } from \"./capability-registry.js\";\nimport { deriveRunStatistics } from \"./stats.js\";\nimport type { BudgetResource, ModelCapabilities } from \"./types.js\";\n\ntype BudgetLedgerResources = BudgetResource;\n\nexport const RUN_STATE_DIR_ENV = \"JENSEN_RUN_STATE_DIR\";\n\nexport function defaultRunStateDir(): string {\n\tif (process.env[RUN_STATE_DIR_ENV]) return process.env[RUN_STATE_DIR_ENV]!;\n\treturn path.join(os.homedir(), \".local\", \"state\", \"jensen\", \"runs\");\n}\n\nexport function runStatePath(runId: string, kind: string, stateDir: string): string {\n\treturn path.join(stateDir, `${runId}.${kind}.json`);\n}\n\nfunction readLedger(runId: string, stateDir: string): BudgetLedger {\n\tconst p = runStatePath(runId, \"ledger\", stateDir);\n\tif (!existsSync(p)) {\n\t\treturn createBudgetLedger(runId);\n\t}\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(p, \"utf8\")) as { entries: unknown[] };\n\t\tconst entries = Array.isArray(parsed?.entries) ? parsed.entries : [];\n\t\tlet ledger = createBudgetLedger(runId);\n\t\tfor (const raw of entries) {\n\t\t\tledger = pushLedgerEntry(ledger, raw as never);\n\t\t}\n\t\treturn ledger;\n\t} catch {\n\t\treturn createBudgetLedger(runId);\n\t}\n}\n\nfunction pushLedgerEntry(\n\tledger: BudgetLedger,\n\te: {\n\t\tentryId?: string;\n\t\trunId?: string;\n\t\tphaseId?: string;\n\t\trole?: string;\n\t\tresource?: string;\n\t\tamount?: number;\n\t\testimatedOrActual?: \"estimated\" | \"actual\";\n\t\tprovider?: string;\n\t\tmodel?: string;\n\t\tsourceEventId?: string;\n\t\trecordedAt?: string;\n\t},\n): BudgetLedger {\n\tconst resource = e.resource as BudgetLedgerResources;\n\tconst out = appendEntry(ledger, {\n\t\tentryId: e.entryId ?? \"\",\n\t\trunId: e.runId ?? \"\",\n\t\tphaseId: e.phaseId,\n\t\trole: e.role,\n\t\tresource,\n\t\tamount: e.amount ?? 0,\n\t\testimatedOrActual: e.estimatedOrActual ?? \"estimated\",\n\t\tprovider: e.provider,\n\t\tmodel: e.model,\n\t\tsourceEventId: e.sourceEventId ?? \"\",\n\t\trecordedAt: e.recordedAt ?? \"\",\n\t});\n\treturn out.ledger;\n}\n\nfunction json(v: unknown): string {\n\treturn JSON.stringify(v, null, 2);\n}\n\nfunction usage(namespace: string, subcommands: string[]): string {\n\treturn [`Usage: jensen ${namespace} <command> [args]`, \"\", \"Commands:\", ...subcommands.map((s) => `  ${s}`)].join(\n\t\t\"\\n\",\n\t);\n}\n\nexport async function handleAdaptiveCommand(args: string[]): Promise<boolean> {\n\tconst root = args[0];\n\tif (root === \"run\") {\n\t\treturn handleRunCommand(args.slice(1));\n\t}\n\tif (root === \"doctor\") {\n\t\treturn handleDoctorCommand(args.slice(1));\n\t}\n\tif (root === \"skills\") {\n\t\treturn handleSkillsCommand(args.slice(1));\n\t}\n\treturn false;\n}\n\nasync function handleRunCommand(args: string[]): Promise<boolean> {\n\tconst sub = args[0];\n\tif (![\"budget\", \"stats\", \"strategies\", \"stalls\", \"criteria\", \"subagents\"].includes(sub)) return false;\n\tconst runId = args[1];\n\tif (!runId) {\n\t\tconsole.error(\n\t\t\tusage(\"run\", [\n\t\t\t\t\"budget <run-id>\",\n\t\t\t\t\"stats <run-id>\",\n\t\t\t\t\"strategies <run-id>\",\n\t\t\t\t\"stalls <run-id>\",\n\t\t\t\t\"criteria <run-id>\",\n\t\t\t\t\"subagents <run-id>\",\n\t\t\t]),\n\t\t);\n\t\treturn true;\n\t}\n\tconst stateDir = defaultRunStateDir();\n\tconst ledger = readLedger(runId, stateDir);\n\tif (sub === \"budget\") {\n\t\tconst usageMap: Record<string, number> = {};\n\t\tfor (const resource of resourcesOfBudget()) {\n\t\t\tusageMap[resource] = sumResource(ledger, resource);\n\t\t}\n\t\tconsole.log(\n\t\t\tjson({\n\t\t\t\trunId,\n\t\t\t\tledgerEntries: ledger.entries.length,\n\t\t\t\tusage: usageMap,\n\t\t\t\tnote: \"estimated/actual reconciled in ledger; prices effective-date tagged\",\n\t\t\t}),\n\t\t);\n\t} else if (sub === \"stats\") {\n\t\tconsole.log(json(deriveRunStatistics({ runId, ledger })));\n\t} else if (sub === \"strategies\") {\n\t\tconsole.log(json({ runId, strategies: readList(runId, \"strategies\", stateDir) }));\n\t} else if (sub === \"stalls\") {\n\t\tconsole.log(json({ runId, stalls: readList(runId, \"stalls\", stateDir) }));\n\t} else if (sub === \"criteria\") {\n\t\tconsole.log(json({ runId, criteria: readList(runId, \"criteria\", stateDir) }));\n\t} else if (sub === \"subagents\") {\n\t\tconsole.log(json({ runId, subagents: readList(runId, \"subagents\", stateDir) }));\n\t}\n\treturn true;\n}\n\nfunction readList(runId: string, kind: string, stateDir: string): unknown[] {\n\tconst p = runStatePath(runId, kind, stateDir);\n\tif (!existsSync(p)) return [];\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(p, \"utf8\"));\n\t\treturn Array.isArray(parsed) ? parsed : [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nasync function handleDoctorCommand(args: string[]): Promise<boolean> {\n\tconst sub = args[0];\n\tif (sub === \"routing\") {\n\t\tconst registry = createCapabilityRegistry(DEFAULT_PROFILES.map(profileFor));\n\t\tconst models = registry.profiles.map((p) => ({\n\t\t\tprovider: p.provider,\n\t\t\tmodel: p.model,\n\t\t\texecutor: roleCompatibility(p, [\"supportsTools\", \"supportsCodeGeneration\"]).compatible,\n\t\t\treviewer: roleCompatibility(p, [\"supportsCodeReview\"]).compatible,\n\t\t\tcheapSummarizer: p.supportsCheapSummarization === true,\n\t\t}));\n\t\tconsole.log(json({ routing: models, invariant: \"MODEL_ROUTING_IS_POLICY_CONSTRAINED\" }));\n\t\treturn true;\n\t}\n\tif (sub === \"budgets\") {\n\t\tconsole.log(\n\t\t\tjson({\n\t\t\t\tinvariants: [\n\t\t\t\t\t\"BUDGETS_ARE_DURABLE_AND_AUTHORITATIVE\",\n\t\t\t\t\t\"HARD_LIMITS_CANNOT_BE_OVERRIDDEN_BY_MODELS\",\n\t\t\t\t\t\"FINALIZATION_RESERVE_CANNOT_BE_SPENT_EARLY\",\n\t\t\t\t],\n\t\t\t\tthresholds: \"soft/hard/finalizationReserve applied per resource\",\n\t\t\t}),\n\t\t);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nasync function handleSkillsCommand(args: string[]): Promise<boolean> {\n\tconst sub = args[0];\n\tif (sub === \"list\") {\n\t\tconsole.log(\n\t\t\tjson(\n\t\t\t\tBUILTIN_SKILLS.map((s) => ({\n\t\t\t\t\tname: s.name,\n\t\t\t\t\tversion: s.version,\n\t\t\t\t\tdescription: s.description,\n\t\t\t\t\tmode: s.executionMode,\n\t\t\t\t})),\n\t\t\t),\n\t\t);\n\t\treturn true;\n\t}\n\tif (sub === \"inspect\") {\n\t\tconst name = args[1];\n\t\tconst skill = BUILTIN_SKILLS.find((s) => s.name === name);\n\t\tif (!skill) {\n\t\t\tconsole.error(`Unknown skill: ${name}`);\n\t\t\treturn true;\n\t\t}\n\t\tconsole.log(json(skill));\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction profileFor(m: ModelCapabilities): ModelCapabilities {\n\treturn m;\n}\n\n/** Static read-only default capability profiles used only for diagnostics. */\nconst DEFAULT_PROFILES: ModelCapabilities[] = [\n\t{\n\t\tprovider: \"static\",\n\t\tmodel: \"executor\",\n\t\tsupportsTools: true,\n\t\tsupportsParallelTools: true,\n\t\tsupportsStructuredOutput: true,\n\t\tsupportsVision: false,\n\t\tsupportsPromptCaching: true,\n\t\tsupportsReasoningEffort: true,\n\t\tsupportsStreamingToolCalls: true,\n\t\tsupportsReliableLongContext: true,\n\t\tsupportsCodeGeneration: true,\n\t\tsupportsCodeReview: false,\n\t\tsupportsResearchSynthesis: false,\n\t\tsupportsCheapSummarization: false,\n\t\tsupportsToolCallRepair: true,\n\t\tpricing: { inputPerMillion: 3, outputPerMillion: 15, currency: \"usd\", effectiveAt: \"2026-01-01\" },\n\t},\n\t{\n\t\tprovider: \"static\",\n\t\tmodel: \"reviewer\",\n\t\tsupportsTools: true,\n\t\tsupportsParallelTools: false,\n\t\tsupportsStructuredOutput: true,\n\t\tsupportsVision: false,\n\t\tsupportsPromptCaching: true,\n\t\tsupportsReasoningEffort: true,\n\t\tsupportsStreamingToolCalls: true,\n\t\tsupportsReliableLongContext: true,\n\t\tsupportsCodeGeneration: false,\n\t\tsupportsCodeReview: true,\n\t\tsupportsResearchSynthesis: false,\n\t\tsupportsCheapSummarization: false,\n\t\tsupportsToolCallRepair: false,\n\t\tpricing: { inputPerMillion: 3, outputPerMillion: 15, currency: \"usd\", effectiveAt: \"2026-01-01\" },\n\t},\n\t{\n\t\tprovider: \"static\",\n\t\tmodel: \"cheap-sum\",\n\t\tsupportsTools: \"unknown\",\n\t\tsupportsParallelTools: \"unknown\",\n\t\tsupportsStructuredOutput: \"unknown\",\n\t\tsupportsVision: \"unknown\",\n\t\tsupportsPromptCaching: true,\n\t\tsupportsReasoningEffort: \"unknown\",\n\t\tsupportsStreamingToolCalls: \"unknown\",\n\t\tsupportsReliableLongContext: \"unknown\",\n\t\tsupportsCodeGeneration: false,\n\t\tsupportsCodeReview: false,\n\t\tsupportsResearchSynthesis: false,\n\t\tsupportsCheapSummarization: true,\n\t\tsupportsToolCallRepair: false,\n\t\tpricing: { inputPerMillion: 0.2, outputPerMillion: 0.6, currency: \"usd\", effectiveAt: \"2026-01-01\" },\n\t},\n];\n\nexport { BUILTIN_SKILLS };\nexport type { BuiltinSkill };\n\n/** Ensure the run-state directory exists (used by tests and tooling). */\nexport function ensureRunStateDir(stateDir: string): string {\n\tmkdirSync(stateDir, { recursive: true });\n\treturn stateDir;\n}\n"]}