nexus-agents 2.77.13 → 2.78.0
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/dist/{child-mcp-config-MJMUF7TL.js → child-mcp-config-CTO2MBRM.js} +3 -4
- package/dist/{child-mcp-config-MJMUF7TL.js.map → child-mcp-config-CTO2MBRM.js.map} +1 -1
- package/dist/{chunk-YJ2IGAD2.js → chunk-2UYTFLMO.js} +2 -2
- package/dist/{chunk-6AY5DK4E.js → chunk-2YPG6PDG.js} +3 -3
- package/dist/{chunk-3VWMM6UF.js → chunk-3NIPH6UP.js} +2 -2
- package/dist/{chunk-JX6OI4FS.js → chunk-4N33QZLH.js} +13 -15
- package/dist/{chunk-JX6OI4FS.js.map → chunk-4N33QZLH.js.map} +1 -1
- package/dist/{chunk-JN6UWGHH.js → chunk-5O6XLBPP.js} +2 -2
- package/dist/{chunk-ERWXGXV2.js → chunk-6TFTVW77.js} +3 -3
- package/dist/{chunk-GFKGL2GQ.js → chunk-6WBTNZAY.js} +171 -83
- package/dist/chunk-6WBTNZAY.js.map +1 -0
- package/dist/{chunk-GOT7OAL5.js → chunk-7BMOZJYS.js} +29 -5
- package/dist/chunk-7BMOZJYS.js.map +1 -0
- package/dist/{chunk-C2LLQ6TW.js → chunk-7XCUZI4G.js} +4 -4
- package/dist/chunk-7XCUZI4G.js.map +1 -0
- package/dist/{chunk-TDV5ALHY.js → chunk-D6TM2VHX.js} +3 -3
- package/dist/{chunk-PWTJGGKB.js → chunk-DLXT23AC.js} +2 -2
- package/dist/chunk-DNO2INX5.js +276 -0
- package/dist/chunk-DNO2INX5.js.map +1 -0
- package/dist/{chunk-G2CSKBY5.js → chunk-FJWWSVWB.js} +29 -6
- package/dist/chunk-FJWWSVWB.js.map +1 -0
- package/dist/{chunk-DSQ5XM4O.js → chunk-FVPYP5DD.js} +4 -4
- package/dist/{chunk-MGLWPN2I.js → chunk-GONMG4NM.js} +2 -2
- package/dist/{chunk-RBZ4CDMY.js → chunk-GTGDVBLW.js} +5 -5
- package/dist/{chunk-YQMQSJQK.js → chunk-HYU4GZY6.js} +2 -2
- package/dist/{chunk-3DH5SLFH.js → chunk-K2QILJG4.js} +6 -6
- package/dist/{chunk-5WHWKY32.js → chunk-KT5FIBWS.js} +2 -2
- package/dist/{chunk-DIB6V67T.js → chunk-L6SCKLGO.js} +3 -3
- package/dist/{chunk-IPWCD22D.js → chunk-PLX6FCFC.js} +2 -2
- package/dist/chunk-PQHVC4BD.js +639 -0
- package/dist/chunk-PQHVC4BD.js.map +1 -0
- package/dist/chunk-Q5CFPIJ5.js +5581 -0
- package/dist/chunk-Q5CFPIJ5.js.map +1 -0
- package/dist/{chunk-G6ZPVADX.js → chunk-SD76JZBG.js} +2 -2
- package/dist/{chunk-Y2CP4Z5B.js → chunk-SWFJU3W2.js} +220 -4580
- package/dist/chunk-SWFJU3W2.js.map +1 -0
- package/dist/{chunk-3MRM53T4.js → chunk-WDYCIJWN.js} +640 -470
- package/dist/chunk-WDYCIJWN.js.map +1 -0
- package/dist/{chunk-CM3TORGV.js → chunk-YXWGEIQR.js} +2 -2
- package/dist/{chunk-7NK7BTWP.js → chunk-ZVCED4Z4.js} +2 -2
- package/dist/cli-circuit-breaker-I74ZQ44Q.js +13 -0
- package/dist/cli.js +109 -58
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-S6E26BCI.js → composite-router-V3OC57IE.js} +3 -4
- package/dist/consensus-vote-ESFPGEJE.js +30 -0
- package/dist/context-retriever-MB3D7KS6.js +18 -0
- package/dist/dist-NIXVXYIH.js +42 -0
- package/dist/doctor-deep-KQ765XZA.js +12 -0
- package/dist/expert-bridge-JKLC57IC.js +10 -0
- package/dist/factory-BUUXNGIB.js +14 -0
- package/dist/{factory-X3VKIGKP.js → factory-LHHYDVZX.js} +5 -6
- package/dist/index.d.ts +72 -8
- package/dist/index.js +208 -316
- package/dist/index.js.map +1 -1
- package/dist/{init-opencode-CFE7M6XA.js → init-opencode-GXZN2W5S.js} +6 -7
- package/dist/{init-opencode-CFE7M6XA.js.map → init-opencode-GXZN2W5S.js.map} +1 -1
- package/dist/issue-triage-RMXPDZ2K.js +15 -0
- package/dist/{learning-persistence-N6ILD2HX.js → learning-persistence-Q3HTOGTU.js} +2 -3
- package/dist/outcome-store-adapter-QRFJJIKB.js +57 -0
- package/dist/outcome-store-adapter-QRFJJIKB.js.map +1 -0
- package/dist/{registry-command-RPPC7N2K.js → registry-command-6E4YKAMT.js} +3 -4
- package/dist/{registry-command-RPPC7N2K.js.map → registry-command-6E4YKAMT.js.map} +1 -1
- package/dist/{repo-security-plan-7ZCDVH5O.js → repo-security-plan-AGRU72DL.js} +4 -5
- package/dist/research-helpers-synthesize-K2UCJQQG.js +13 -0
- package/dist/{routing-memory-5VTX7LQX.js → routing-memory-3B6DDZ76.js} +3 -4
- package/dist/{session-memory-7XBV6BMY.js → session-memory-L7EQIY2O.js} +4 -5
- package/dist/{setup-command-W6UKPODL.js → setup-command-VYV4RFWW.js} +11 -12
- package/dist/setup-config-EQT24DD4.js +10 -0
- package/dist/{setup-custom-api-WM5W5AY5.js → setup-custom-api-IBDV654K.js} +5 -6
- package/dist/{setup-custom-api-WM5W5AY5.js.map → setup-custom-api-IBDV654K.js.map} +1 -1
- package/dist/tool-memory-6HCHQLAN.js +19 -0
- package/dist/{weather-report-YJMVKJGA.js → weather-report-ER3WUZ7S.js} +3 -4
- package/package.json +3 -2
- package/dist/adaptive-memory-EI564K4C.js +0 -16
- package/dist/chunk-3MRM53T4.js.map +0 -1
- package/dist/chunk-BJ2OMC7P.js +0 -944
- package/dist/chunk-BJ2OMC7P.js.map +0 -1
- package/dist/chunk-C2LLQ6TW.js.map +0 -1
- package/dist/chunk-G2CSKBY5.js.map +0 -1
- package/dist/chunk-GFKGL2GQ.js.map +0 -1
- package/dist/chunk-GOT7OAL5.js.map +0 -1
- package/dist/chunk-I7ORMAO7.js +0 -32
- package/dist/chunk-I7ORMAO7.js.map +0 -1
- package/dist/chunk-Y2CP4Z5B.js.map +0 -1
- package/dist/cli-circuit-breaker-YX4BWZD5.js +0 -14
- package/dist/consensus-vote-MUQ4HPIF.js +0 -30
- package/dist/doctor-deep-BRU5ZUJI.js +0 -13
- package/dist/expert-bridge-ZPNVLJVN.js +0 -11
- package/dist/factory-A7DTCCUY.js +0 -15
- package/dist/issue-triage-6XD6CVPB.js +0 -16
- package/dist/mobimem-CG2MNS7V.js +0 -14
- package/dist/nexus-data-dir-77UO7N6J.js +0 -12
- package/dist/research-helpers-synthesize-36TUTUUA.js +0 -14
- package/dist/setup-config-EI5KROA3.js +0 -11
- /package/dist/{chunk-YJ2IGAD2.js.map → chunk-2UYTFLMO.js.map} +0 -0
- /package/dist/{chunk-6AY5DK4E.js.map → chunk-2YPG6PDG.js.map} +0 -0
- /package/dist/{chunk-3VWMM6UF.js.map → chunk-3NIPH6UP.js.map} +0 -0
- /package/dist/{chunk-JN6UWGHH.js.map → chunk-5O6XLBPP.js.map} +0 -0
- /package/dist/{chunk-ERWXGXV2.js.map → chunk-6TFTVW77.js.map} +0 -0
- /package/dist/{chunk-TDV5ALHY.js.map → chunk-D6TM2VHX.js.map} +0 -0
- /package/dist/{chunk-PWTJGGKB.js.map → chunk-DLXT23AC.js.map} +0 -0
- /package/dist/{chunk-DSQ5XM4O.js.map → chunk-FVPYP5DD.js.map} +0 -0
- /package/dist/{chunk-MGLWPN2I.js.map → chunk-GONMG4NM.js.map} +0 -0
- /package/dist/{chunk-RBZ4CDMY.js.map → chunk-GTGDVBLW.js.map} +0 -0
- /package/dist/{chunk-YQMQSJQK.js.map → chunk-HYU4GZY6.js.map} +0 -0
- /package/dist/{chunk-3DH5SLFH.js.map → chunk-K2QILJG4.js.map} +0 -0
- /package/dist/{chunk-5WHWKY32.js.map → chunk-KT5FIBWS.js.map} +0 -0
- /package/dist/{chunk-DIB6V67T.js.map → chunk-L6SCKLGO.js.map} +0 -0
- /package/dist/{chunk-IPWCD22D.js.map → chunk-PLX6FCFC.js.map} +0 -0
- /package/dist/{chunk-G6ZPVADX.js.map → chunk-SD76JZBG.js.map} +0 -0
- /package/dist/{chunk-CM3TORGV.js.map → chunk-YXWGEIQR.js.map} +0 -0
- /package/dist/{chunk-7NK7BTWP.js.map → chunk-ZVCED4Z4.js.map} +0 -0
- /package/dist/{adaptive-memory-EI564K4C.js.map → cli-circuit-breaker-I74ZQ44Q.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-YX4BWZD5.js.map → composite-router-V3OC57IE.js.map} +0 -0
- /package/dist/{composite-router-S6E26BCI.js.map → consensus-vote-ESFPGEJE.js.map} +0 -0
- /package/dist/{consensus-vote-MUQ4HPIF.js.map → context-retriever-MB3D7KS6.js.map} +0 -0
- /package/dist/{doctor-deep-BRU5ZUJI.js.map → dist-NIXVXYIH.js.map} +0 -0
- /package/dist/{expert-bridge-ZPNVLJVN.js.map → doctor-deep-KQ765XZA.js.map} +0 -0
- /package/dist/{factory-A7DTCCUY.js.map → expert-bridge-JKLC57IC.js.map} +0 -0
- /package/dist/{factory-X3VKIGKP.js.map → factory-BUUXNGIB.js.map} +0 -0
- /package/dist/{issue-triage-6XD6CVPB.js.map → factory-LHHYDVZX.js.map} +0 -0
- /package/dist/{learning-persistence-N6ILD2HX.js.map → issue-triage-RMXPDZ2K.js.map} +0 -0
- /package/dist/{mobimem-CG2MNS7V.js.map → learning-persistence-Q3HTOGTU.js.map} +0 -0
- /package/dist/{nexus-data-dir-77UO7N6J.js.map → repo-security-plan-AGRU72DL.js.map} +0 -0
- /package/dist/{repo-security-plan-7ZCDVH5O.js.map → research-helpers-synthesize-K2UCJQQG.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-36TUTUUA.js.map → routing-memory-3B6DDZ76.js.map} +0 -0
- /package/dist/{routing-memory-5VTX7LQX.js.map → session-memory-L7EQIY2O.js.map} +0 -0
- /package/dist/{session-memory-7XBV6BMY.js.map → setup-command-VYV4RFWW.js.map} +0 -0
- /package/dist/{setup-command-W6UKPODL.js.map → setup-config-EQT24DD4.js.map} +0 -0
- /package/dist/{setup-config-EI5KROA3.js.map → tool-memory-6HCHQLAN.js.map} +0 -0
- /package/dist/{weather-report-YJMVKJGA.js.map → weather-report-ER3WUZ7S.js.map} +0 -0
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
discoverModels,
|
|
3
3
|
readOpencodeGateway
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-7XCUZI4G.js";
|
|
5
|
+
import "./chunk-L6SCKLGO.js";
|
|
6
|
+
import "./chunk-PLX6FCFC.js";
|
|
7
7
|
import {
|
|
8
8
|
createLogger
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-GOT7OAL5.js";
|
|
9
|
+
} from "./chunk-WDYCIJWN.js";
|
|
10
|
+
import "./chunk-7BMOZJYS.js";
|
|
12
11
|
import "./chunk-UP2VWCW5.js";
|
|
13
12
|
|
|
14
13
|
// src/cli/init-opencode.ts
|
|
@@ -175,4 +174,4 @@ export {
|
|
|
175
174
|
runInitOpencode,
|
|
176
175
|
runOpencodeValidate
|
|
177
176
|
};
|
|
178
|
-
//# sourceMappingURL=init-opencode-
|
|
177
|
+
//# sourceMappingURL=init-opencode-GXZN2W5S.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/init-opencode.ts"],"sourcesContent":["/**\n * `nexus-agents init --opencode <path>` setup helper (#2504, child 4 of #2500).\n *\n * Injects the nexus-agents MCP block + recommended environment into an\n * existing `opencode.json` without overwriting other operator-set keys.\n * Pairs with the existing `init --portable --mcp-config` (which targets\n * Claude Code's `.mcp.json`). Different harness, same merge-not-overwrite\n * pattern.\n *\n * Behaviour:\n * - File exists → merge `mcp.nexus-agents` into the existing JSON.\n * Preserve every other key the operator has set (provider config,\n * model lists, theme, …). Idempotent: re-running produces the same\n * final file.\n * - File missing → write a minimal template with the nexus-agents MCP\n * block + a stubbed `providers.openai-compat` shell the operator\n * fills in (placeholder baseURL + `{env:WORKSPACE_PROXY_KEY}`).\n * - `--dry-run` → print the diff (proposed vs existing) without writing.\n * - `--validate` → after merge (or alongside dry-run), probe\n * `providers.openai-compat.options.baseURL/v1/models` with the\n * resolved apiKey, exit non-zero if unreachable.\n *\n * @module cli/init-opencode\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\nimport { createLogger } from '../core/index.js';\nimport { readOpencodeGateway } from '../config/opencode-bridge.js';\nimport { discoverModels } from '../adapters/openai-compat-adapter.js';\n\nconst logger = createLogger({ component: 'init-opencode' });\n\nexport interface InitOpencodeOptions {\n /** Absolute or relative path to opencode.json. */\n readonly path: string;\n /** Path to the nexus-agents CLI binary that the MCP block will spawn. */\n readonly cliPath: string;\n /** Sandbox flavor written to NEXUS_SANDBOX in the MCP environment. */\n readonly sandboxFlavor?: string;\n /** Print the diff without writing. */\n readonly dryRun?: boolean;\n}\n\nexport interface InitOpencodeResult {\n readonly path: string;\n readonly action: 'created' | 'updated' | 'unchanged' | 'dry-run';\n readonly diff: string;\n}\n\ninterface OpencodeMcpBlock {\n type: 'local';\n command: string[];\n enabled: boolean;\n environment: Record<string, string>;\n}\n\ninterface OpencodeFile {\n $schema?: string;\n providers?: Record<string, unknown>;\n mcp?: Record<string, unknown>;\n permission?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Conservative default OpenCode `permission` block (#2658). OpenCode\n * evaluates a glob map with **last-matching-rule-winning**, so the broad\n * `\"*\"` rule is listed first and the hard `deny` patterns last.\n *\n * - `edit` — everything `ask`s; secrets, keys, and `.git/` are hard-denied\n * regardless of operator confirmation. The deny patterns come after\n * `\"*\"` so last-match-wins makes them stick.\n * - `bash` — `ask` unconditionally. Shell is the highest-risk surface.\n * - `skill` — `allow`. Skills are trusted, in-repo, CI-validated content.\n *\n * Emitted only when the operator has not already set their own\n * `permission` block — never overwrites operator config.\n */\nexport function buildDefaultPermissionBlock(): Record<string, unknown> {\n return {\n edit: {\n '*': 'ask',\n '**/.env': 'deny',\n '**/.env.*': 'deny',\n '**/*.pem': 'deny',\n '**/*.key': 'deny',\n '**/id_rsa*': 'deny',\n '**/secrets/**': 'deny',\n '**/.git/**': 'deny',\n },\n bash: 'ask',\n skill: 'allow',\n };\n}\n\n/**\n * Build the canonical nexus-agents MCP block. Mirrors what\n * `Dockerfile.sandbox` writes today plus the env vars from #2501 + #2503.\n */\nexport function buildNexusMcpBlock(opts: {\n readonly cliPath: string;\n readonly sandboxFlavor?: string;\n readonly opencodeConfigPath: string;\n}): OpencodeMcpBlock {\n const env: Record<string, string> = {\n NEXUS_DATA_DIR: '{env:NEXUS_DATA_DIR}',\n NEXUS_OPENCODE_CONFIG: opts.opencodeConfigPath,\n };\n if (opts.sandboxFlavor !== undefined && opts.sandboxFlavor !== '') {\n env['NEXUS_SANDBOX'] = opts.sandboxFlavor;\n }\n return {\n type: 'local',\n command: ['node', opts.cliPath, '--mode=server'],\n enabled: true,\n environment: env,\n };\n}\n\n/**\n * Execute the merge. Pure with respect to `opts.dryRun: true` — no fs\n * writes. Returns the final-or-proposed JSON + a diff string suitable\n * for printing.\n */\nexport function runInitOpencode(opts: InitOpencodeOptions): InitOpencodeResult {\n const existing = readExisting(opts.path);\n const merged = mergeNexusBlock(existing, opts);\n const before = existing === null ? '' : `${JSON.stringify(existing, null, 2)}\\n`;\n const after = `${JSON.stringify(merged, null, 2)}\\n`;\n const diff = simpleDiff(before, after);\n\n if (opts.dryRun === true) {\n return { path: opts.path, action: 'dry-run', diff };\n }\n\n if (existing !== null && before === after) {\n return { path: opts.path, action: 'unchanged', diff };\n }\n\n writeFileSync(opts.path, after, 'utf8');\n return { path: opts.path, action: existing === null ? 'created' : 'updated', diff };\n}\n\nfunction readExisting(path: string): OpencodeFile | null {\n if (!existsSync(path)) return null;\n try {\n const raw = readFileSync(path, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n if (typeof parsed !== 'object' || parsed === null) {\n throw new Error('opencode.json root must be an object');\n }\n return parsed as OpencodeFile;\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to parse opencode.json at ${path}: ${msg}`);\n }\n}\n\nfunction mergeNexusBlock(existing: OpencodeFile | null, opts: InitOpencodeOptions): OpencodeFile {\n const block = buildNexusMcpBlock({\n cliPath: opts.cliPath,\n ...(opts.sandboxFlavor !== undefined && { sandboxFlavor: opts.sandboxFlavor }),\n opencodeConfigPath: opts.path,\n });\n\n if (existing === null) {\n return {\n $schema: 'https://opencode.ai/config.json',\n providers: { 'openai-compat': stubOpenaiCompatProvider() },\n permission: buildDefaultPermissionBlock(),\n mcp: { 'nexus-agents': block },\n };\n }\n\n // Idempotent merge: preserve user-customised fields if they exist on the\n // current MCP block (e.g. `enabled: false`). Update anything else.\n const existingMcp: Record<string, unknown> = existing.mcp ?? {};\n const rawNexus = existingMcp['nexus-agents'];\n const existingNexus: Partial<OpencodeMcpBlock> =\n typeof rawNexus === 'object' && rawNexus !== null ? rawNexus : {};\n const mergedBlock: OpencodeMcpBlock = {\n type: 'local',\n command: block.command,\n enabled: existingNexus.enabled ?? block.enabled,\n environment: { ...block.environment, ...(existingNexus.environment ?? {}) },\n };\n\n // Add the default permission block only when the operator has not set\n // their own — never overwrite an existing `permission` key.\n const permission = existing.permission ?? buildDefaultPermissionBlock();\n\n return {\n ...existing,\n permission,\n mcp: { ...existingMcp, 'nexus-agents': mergedBlock },\n };\n}\n\n/**\n * Stub for `providers.openai-compat`. Operators replace the placeholder\n * baseURL + key with their workspace-proxy values. Empty by design — we\n * never overwrite an existing provider block (see `mergeNexusBlock`).\n */\nfunction stubOpenaiCompatProvider(): Record<string, unknown> {\n return {\n npm: '@ai-sdk/openai-compatible',\n options: {\n baseURL: '<replace with workspace proxy URL>',\n apiKey: '{env:WORKSPACE_PROXY_KEY}',\n },\n };\n}\n\n/**\n * Cheap line-based diff. Three-line context, +/- prefixes. Good enough\n * for an operator preview; not a unified-diff replacement.\n */\nfunction simpleDiff(before: string, after: string): string {\n if (before === after) return '(no changes)';\n const beforeLines = before.split('\\n');\n const afterLines = after.split('\\n');\n const out: string[] = [];\n const max = Math.max(beforeLines.length, afterLines.length);\n for (let i = 0; i < max; i += 1) {\n const b = beforeLines[i];\n const a = afterLines[i];\n if (b === a) {\n out.push(` ${b ?? ''}`);\n } else {\n if (b !== undefined) out.push(`- ${b}`);\n if (a !== undefined) out.push(`+ ${a}`);\n }\n }\n return out.join('\\n');\n}\n\nexport function ensureOpencodeDirExists(path: string): void {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n throw new Error(\n `Parent directory does not exist: ${dir}. Create it first or pass a path under an existing dir.`\n );\n }\n logger.debug('opencode.json target directory exists', { dir });\n}\n\n/**\n * --validate flow for `init --opencode` (follow-up to #2504).\n *\n * After the merge step writes the file, optionally probe the gateway it\n * points at. Reuses the same opencode-bridge loader (#2503) that the\n * runtime uses, so what we validate is exactly what the server will see\n * at boot.\n *\n * Returns:\n * - `{ ok: true, models }` when the gateway is reachable and returns ≥1 model\n * - `{ ok: false, reason }` for every failure path (config missing,\n * probe failed, zero models)\n *\n * Caller (cli-commands-handlers) maps to exit codes + stderr / stdout.\n * The API key never reaches the returned object — only model IDs +\n * baseURL appear in the success payload.\n */\nexport interface OpencodeValidateResult {\n readonly ok: boolean;\n readonly baseURL?: string;\n readonly models?: readonly string[];\n readonly reason?: string;\n}\n\nexport async function runOpencodeValidate(opencodePath: string): Promise<OpencodeValidateResult> {\n const config = readOpencodeGateway(opencodePath);\n if (config === null) {\n return {\n ok: false,\n reason:\n 'opencode.json does not resolve a usable gateway. Check that providers.openai-compat.options.{baseURL, apiKey} are set and that any {env:VAR} interpolation references are exported.',\n };\n }\n const result = await discoverModels({ baseUrl: config.baseURL, apiKey: config.apiKey });\n if (!result.ok) {\n return { ok: false, baseURL: config.baseURL, reason: result.error.message };\n }\n if (result.value.length === 0) {\n return {\n ok: false,\n baseURL: config.baseURL,\n reason: 'gateway returned 0 models. Check upstream provider quotas / list filters.',\n };\n }\n return {\n ok: true,\n baseURL: config.baseURL,\n models: result.value.map((m) => m.id),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/init-opencode.ts"],"sourcesContent":["/**\n * `nexus-agents init --opencode <path>` setup helper (#2504, child 4 of #2500).\n *\n * Injects the nexus-agents MCP block + recommended environment into an\n * existing `opencode.json` without overwriting other operator-set keys.\n * Pairs with the existing `init --portable --mcp-config` (which targets\n * Claude Code's `.mcp.json`). Different harness, same merge-not-overwrite\n * pattern.\n *\n * Behaviour:\n * - File exists → merge `mcp.nexus-agents` into the existing JSON.\n * Preserve every other key the operator has set (provider config,\n * model lists, theme, …). Idempotent: re-running produces the same\n * final file.\n * - File missing → write a minimal template with the nexus-agents MCP\n * block + a stubbed `providers.openai-compat` shell the operator\n * fills in (placeholder baseURL + `{env:WORKSPACE_PROXY_KEY}`).\n * - `--dry-run` → print the diff (proposed vs existing) without writing.\n * - `--validate` → after merge (or alongside dry-run), probe\n * `providers.openai-compat.options.baseURL/v1/models` with the\n * resolved apiKey, exit non-zero if unreachable.\n *\n * @module cli/init-opencode\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\nimport { createLogger } from '../core/index.js';\nimport { readOpencodeGateway } from '../config/opencode-bridge.js';\nimport { discoverModels } from '../adapters/openai-compat-adapter.js';\n\nconst logger = createLogger({ component: 'init-opencode' });\n\nexport interface InitOpencodeOptions {\n /** Absolute or relative path to opencode.json. */\n readonly path: string;\n /** Path to the nexus-agents CLI binary that the MCP block will spawn. */\n readonly cliPath: string;\n /** Sandbox flavor written to NEXUS_SANDBOX in the MCP environment. */\n readonly sandboxFlavor?: string;\n /** Print the diff without writing. */\n readonly dryRun?: boolean;\n}\n\nexport interface InitOpencodeResult {\n readonly path: string;\n readonly action: 'created' | 'updated' | 'unchanged' | 'dry-run';\n readonly diff: string;\n}\n\ninterface OpencodeMcpBlock {\n type: 'local';\n command: string[];\n enabled: boolean;\n environment: Record<string, string>;\n}\n\ninterface OpencodeFile {\n $schema?: string;\n providers?: Record<string, unknown>;\n mcp?: Record<string, unknown>;\n permission?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Conservative default OpenCode `permission` block (#2658). OpenCode\n * evaluates a glob map with **last-matching-rule-winning**, so the broad\n * `\"*\"` rule is listed first and the hard `deny` patterns last.\n *\n * - `edit` — everything `ask`s; secrets, keys, and `.git/` are hard-denied\n * regardless of operator confirmation. The deny patterns come after\n * `\"*\"` so last-match-wins makes them stick.\n * - `bash` — `ask` unconditionally. Shell is the highest-risk surface.\n * - `skill` — `allow`. Skills are trusted, in-repo, CI-validated content.\n *\n * Emitted only when the operator has not already set their own\n * `permission` block — never overwrites operator config.\n */\nexport function buildDefaultPermissionBlock(): Record<string, unknown> {\n return {\n edit: {\n '*': 'ask',\n '**/.env': 'deny',\n '**/.env.*': 'deny',\n '**/*.pem': 'deny',\n '**/*.key': 'deny',\n '**/id_rsa*': 'deny',\n '**/secrets/**': 'deny',\n '**/.git/**': 'deny',\n },\n bash: 'ask',\n skill: 'allow',\n };\n}\n\n/**\n * Build the canonical nexus-agents MCP block. Mirrors what\n * `Dockerfile.sandbox` writes today plus the env vars from #2501 + #2503.\n */\nexport function buildNexusMcpBlock(opts: {\n readonly cliPath: string;\n readonly sandboxFlavor?: string;\n readonly opencodeConfigPath: string;\n}): OpencodeMcpBlock {\n const env: Record<string, string> = {\n NEXUS_DATA_DIR: '{env:NEXUS_DATA_DIR}',\n NEXUS_OPENCODE_CONFIG: opts.opencodeConfigPath,\n };\n if (opts.sandboxFlavor !== undefined && opts.sandboxFlavor !== '') {\n env['NEXUS_SANDBOX'] = opts.sandboxFlavor;\n }\n return {\n type: 'local',\n command: ['node', opts.cliPath, '--mode=server'],\n enabled: true,\n environment: env,\n };\n}\n\n/**\n * Execute the merge. Pure with respect to `opts.dryRun: true` — no fs\n * writes. Returns the final-or-proposed JSON + a diff string suitable\n * for printing.\n */\nexport function runInitOpencode(opts: InitOpencodeOptions): InitOpencodeResult {\n const existing = readExisting(opts.path);\n const merged = mergeNexusBlock(existing, opts);\n const before = existing === null ? '' : `${JSON.stringify(existing, null, 2)}\\n`;\n const after = `${JSON.stringify(merged, null, 2)}\\n`;\n const diff = simpleDiff(before, after);\n\n if (opts.dryRun === true) {\n return { path: opts.path, action: 'dry-run', diff };\n }\n\n if (existing !== null && before === after) {\n return { path: opts.path, action: 'unchanged', diff };\n }\n\n writeFileSync(opts.path, after, 'utf8');\n return { path: opts.path, action: existing === null ? 'created' : 'updated', diff };\n}\n\nfunction readExisting(path: string): OpencodeFile | null {\n if (!existsSync(path)) return null;\n try {\n const raw = readFileSync(path, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n if (typeof parsed !== 'object' || parsed === null) {\n throw new Error('opencode.json root must be an object');\n }\n return parsed as OpencodeFile;\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to parse opencode.json at ${path}: ${msg}`);\n }\n}\n\nfunction mergeNexusBlock(existing: OpencodeFile | null, opts: InitOpencodeOptions): OpencodeFile {\n const block = buildNexusMcpBlock({\n cliPath: opts.cliPath,\n ...(opts.sandboxFlavor !== undefined && { sandboxFlavor: opts.sandboxFlavor }),\n opencodeConfigPath: opts.path,\n });\n\n if (existing === null) {\n return {\n $schema: 'https://opencode.ai/config.json',\n providers: { 'openai-compat': stubOpenaiCompatProvider() },\n permission: buildDefaultPermissionBlock(),\n mcp: { 'nexus-agents': block },\n };\n }\n\n // Idempotent merge: preserve user-customised fields if they exist on the\n // current MCP block (e.g. `enabled: false`). Update anything else.\n const existingMcp: Record<string, unknown> = existing.mcp ?? {};\n const rawNexus = existingMcp['nexus-agents'];\n const existingNexus: Partial<OpencodeMcpBlock> =\n typeof rawNexus === 'object' && rawNexus !== null ? rawNexus : {};\n const mergedBlock: OpencodeMcpBlock = {\n type: 'local',\n command: block.command,\n enabled: existingNexus.enabled ?? block.enabled,\n environment: { ...block.environment, ...(existingNexus.environment ?? {}) },\n };\n\n // Add the default permission block only when the operator has not set\n // their own — never overwrite an existing `permission` key.\n const permission = existing.permission ?? buildDefaultPermissionBlock();\n\n return {\n ...existing,\n permission,\n mcp: { ...existingMcp, 'nexus-agents': mergedBlock },\n };\n}\n\n/**\n * Stub for `providers.openai-compat`. Operators replace the placeholder\n * baseURL + key with their workspace-proxy values. Empty by design — we\n * never overwrite an existing provider block (see `mergeNexusBlock`).\n */\nfunction stubOpenaiCompatProvider(): Record<string, unknown> {\n return {\n npm: '@ai-sdk/openai-compatible',\n options: {\n baseURL: '<replace with workspace proxy URL>',\n apiKey: '{env:WORKSPACE_PROXY_KEY}',\n },\n };\n}\n\n/**\n * Cheap line-based diff. Three-line context, +/- prefixes. Good enough\n * for an operator preview; not a unified-diff replacement.\n */\nfunction simpleDiff(before: string, after: string): string {\n if (before === after) return '(no changes)';\n const beforeLines = before.split('\\n');\n const afterLines = after.split('\\n');\n const out: string[] = [];\n const max = Math.max(beforeLines.length, afterLines.length);\n for (let i = 0; i < max; i += 1) {\n const b = beforeLines[i];\n const a = afterLines[i];\n if (b === a) {\n out.push(` ${b ?? ''}`);\n } else {\n if (b !== undefined) out.push(`- ${b}`);\n if (a !== undefined) out.push(`+ ${a}`);\n }\n }\n return out.join('\\n');\n}\n\nexport function ensureOpencodeDirExists(path: string): void {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n throw new Error(\n `Parent directory does not exist: ${dir}. Create it first or pass a path under an existing dir.`\n );\n }\n logger.debug('opencode.json target directory exists', { dir });\n}\n\n/**\n * --validate flow for `init --opencode` (follow-up to #2504).\n *\n * After the merge step writes the file, optionally probe the gateway it\n * points at. Reuses the same opencode-bridge loader (#2503) that the\n * runtime uses, so what we validate is exactly what the server will see\n * at boot.\n *\n * Returns:\n * - `{ ok: true, models }` when the gateway is reachable and returns ≥1 model\n * - `{ ok: false, reason }` for every failure path (config missing,\n * probe failed, zero models)\n *\n * Caller (cli-commands-handlers) maps to exit codes + stderr / stdout.\n * The API key never reaches the returned object — only model IDs +\n * baseURL appear in the success payload.\n */\nexport interface OpencodeValidateResult {\n readonly ok: boolean;\n readonly baseURL?: string;\n readonly models?: readonly string[];\n readonly reason?: string;\n}\n\nexport async function runOpencodeValidate(opencodePath: string): Promise<OpencodeValidateResult> {\n const config = readOpencodeGateway(opencodePath);\n if (config === null) {\n return {\n ok: false,\n reason:\n 'opencode.json does not resolve a usable gateway. Check that providers.openai-compat.options.{baseURL, apiKey} are set and that any {env:VAR} interpolation references are exported.',\n };\n }\n const result = await discoverModels({ baseUrl: config.baseURL, apiKey: config.apiKey });\n if (!result.ok) {\n return { ok: false, baseURL: config.baseURL, reason: result.error.message };\n }\n if (result.value.length === 0) {\n return {\n ok: false,\n baseURL: config.baseURL,\n reason: 'gateway returned 0 models. Check upstream provider quotas / list filters.',\n };\n }\n return {\n ok: true,\n baseURL: config.baseURL,\n models: result.value.map((m) => m.id),\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IssueTriage,
|
|
3
|
+
createIssueTriage,
|
|
4
|
+
formatTriageComment
|
|
5
|
+
} from "./chunk-6TFTVW77.js";
|
|
6
|
+
import "./chunk-SD76JZBG.js";
|
|
7
|
+
import "./chunk-WDYCIJWN.js";
|
|
8
|
+
import "./chunk-7BMOZJYS.js";
|
|
9
|
+
import "./chunk-UP2VWCW5.js";
|
|
10
|
+
export {
|
|
11
|
+
IssueTriage,
|
|
12
|
+
createIssueTriage,
|
|
13
|
+
formatTriageComment
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=issue-triage-RMXPDZ2K.js.map
|
|
@@ -4,8 +4,7 @@ import {
|
|
|
4
4
|
getOutcomesFile,
|
|
5
5
|
getRulesFile,
|
|
6
6
|
isPersistenceEnabled
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-GOT7OAL5.js";
|
|
7
|
+
} from "./chunk-7BMOZJYS.js";
|
|
9
8
|
import "./chunk-UP2VWCW5.js";
|
|
10
9
|
export {
|
|
11
10
|
ensureLearningDir,
|
|
@@ -14,4 +13,4 @@ export {
|
|
|
14
13
|
getRulesFile,
|
|
15
14
|
isPersistenceEnabled
|
|
16
15
|
};
|
|
17
|
-
//# sourceMappingURL=learning-persistence-
|
|
16
|
+
//# sourceMappingURL=learning-persistence-Q3HTOGTU.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import "./chunk-UP2VWCW5.js";
|
|
2
|
+
|
|
3
|
+
// src/orchestration/outcomes/outcome-store-adapter.ts
|
|
4
|
+
var OutcomeStoreAdapter = class {
|
|
5
|
+
domain = "outcomes";
|
|
6
|
+
store;
|
|
7
|
+
constructor(store) {
|
|
8
|
+
this.store = store;
|
|
9
|
+
}
|
|
10
|
+
read(_key) {
|
|
11
|
+
return Promise.resolve(void 0);
|
|
12
|
+
}
|
|
13
|
+
write(_key, _value, _meta) {
|
|
14
|
+
return Promise.reject(
|
|
15
|
+
new Error(
|
|
16
|
+
"nexus-memory: outcomes write should go through OutcomeStore.append() directly; the adapter is read-only for discovery + telemetry"
|
|
17
|
+
)
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
query(filter) {
|
|
21
|
+
const where = filter?.where ?? {};
|
|
22
|
+
const all = this.store.query({
|
|
23
|
+
...typeof where.cli === "string" && { cli: where.cli },
|
|
24
|
+
...typeof where.category === "string" && { category: where.category },
|
|
25
|
+
...typeof where.success === "boolean" && { success: where.success },
|
|
26
|
+
...typeof where.baselineId === "string" && { baselineId: where.baselineId }
|
|
27
|
+
});
|
|
28
|
+
const limit = filter?.limit;
|
|
29
|
+
return Promise.resolve(limit !== void 0 ? all.slice(0, limit) : all);
|
|
30
|
+
}
|
|
31
|
+
delete(_key) {
|
|
32
|
+
return Promise.resolve(false);
|
|
33
|
+
}
|
|
34
|
+
stats() {
|
|
35
|
+
const all = this.store.query({});
|
|
36
|
+
let oldest = null;
|
|
37
|
+
let newest = null;
|
|
38
|
+
for (const o of all) {
|
|
39
|
+
const t = new Date(o.timestamp).getTime();
|
|
40
|
+
if (oldest === null || t < oldest) oldest = t;
|
|
41
|
+
if (newest === null || t > newest) newest = t;
|
|
42
|
+
}
|
|
43
|
+
return Promise.resolve({
|
|
44
|
+
domain: this.domain,
|
|
45
|
+
count: this.store.size,
|
|
46
|
+
oldestTimestamp: oldest,
|
|
47
|
+
newestTimestamp: newest
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
close() {
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
export {
|
|
55
|
+
OutcomeStoreAdapter
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=outcome-store-adapter-QRFJJIKB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/orchestration/outcomes/outcome-store-adapter.ts"],"sourcesContent":["/**\n * Phase 6 of #2766 — IMemoryBackend adapter for OutcomeStore.\n *\n * Routes `getMemoryRegistry().get('outcomes')` reads through the existing\n * OutcomeStore so memory_stats and any other consumer can discover routing\n * outcomes via the unified contract. CRUD continues to flow through the\n * existing typed surface (`store.append`, `store.query`, etc.).\n *\n * Full JSONL→SQLite migration deferred to Phase 6.1.\n *\n * @module orchestration/outcomes/outcome-store-adapter\n */\n\nimport type { BackendStats, IMemoryBackend, QueryFilter, WriteMeta } from 'nexus-memory';\nimport type { OutcomeStore } from './outcome-store.js';\nimport type { TaskOutcome } from './outcome-types.js';\n\nexport class OutcomeStoreAdapter implements IMemoryBackend<string, TaskOutcome> {\n readonly domain = 'outcomes';\n private readonly store: OutcomeStore;\n\n constructor(store: OutcomeStore) {\n this.store = store;\n }\n\n read(_key: string): Promise<TaskOutcome | undefined> {\n // OutcomeStore is keyed by query filter, not primary key. Direct\n // key lookup isn't a meaningful operation — callers should `query`.\n return Promise.resolve(undefined);\n }\n\n write(_key: string, _value: TaskOutcome, _meta?: WriteMeta): Promise<void> {\n return Promise.reject(\n new Error(\n 'nexus-memory: outcomes write should go through OutcomeStore.append() directly; ' +\n 'the adapter is read-only for discovery + telemetry'\n )\n );\n }\n\n query(filter?: QueryFilter<TaskOutcome>): Promise<readonly TaskOutcome[]> {\n // Translate the IMemoryBackend filter into OutcomeStore.query's\n // narrower shape. `where` is shallow-matched, `limit` is honored.\n const where = filter?.where ?? {};\n const all = this.store.query({\n ...(typeof where.cli === 'string' && { cli: where.cli }),\n ...(typeof where.category === 'string' && { category: where.category }),\n ...(typeof where.success === 'boolean' && { success: where.success }),\n ...(typeof where.baselineId === 'string' && { baselineId: where.baselineId }),\n });\n const limit = filter?.limit;\n return Promise.resolve(limit !== undefined ? all.slice(0, limit) : all);\n }\n\n delete(_key: string): Promise<boolean> {\n // OutcomeStore has bulk-purge methods (`purgeSkippedWorkers`) but no\n // per-key delete. Treat as no-op for the contract.\n return Promise.resolve(false);\n }\n\n stats(): Promise<BackendStats> {\n const all = this.store.query({});\n let oldest: number | null = null;\n let newest: number | null = null;\n for (const o of all) {\n const t = new Date(o.timestamp).getTime();\n if (oldest === null || t < oldest) oldest = t;\n if (newest === null || t > newest) newest = t;\n }\n return Promise.resolve({\n domain: this.domain,\n count: this.store.size,\n oldestTimestamp: oldest,\n newestTimestamp: newest,\n });\n }\n\n close(): Promise<void> {\n // OutcomeStore has no close — singleton lives for the process.\n return Promise.resolve();\n }\n}\n"],"mappings":";;;AAiBO,IAAM,sBAAN,MAAyE;AAAA,EACrE,SAAS;AAAA,EACD;AAAA,EAEjB,YAAY,OAAqB;AAC/B,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,KAAK,MAAgD;AAGnD,WAAO,QAAQ,QAAQ,MAAS;AAAA,EAClC;AAAA,EAEA,MAAM,MAAc,QAAqB,OAAkC;AACzE,WAAO,QAAQ;AAAA,MACb,IAAI;AAAA,QACF;AAAA,MAEF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAoE;AAGxE,UAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,UAAM,MAAM,KAAK,MAAM,MAAM;AAAA,MAC3B,GAAI,OAAO,MAAM,QAAQ,YAAY,EAAE,KAAK,MAAM,IAAI;AAAA,MACtD,GAAI,OAAO,MAAM,aAAa,YAAY,EAAE,UAAU,MAAM,SAAS;AAAA,MACrE,GAAI,OAAO,MAAM,YAAY,aAAa,EAAE,SAAS,MAAM,QAAQ;AAAA,MACnE,GAAI,OAAO,MAAM,eAAe,YAAY,EAAE,YAAY,MAAM,WAAW;AAAA,IAC7E,CAAC;AACD,UAAM,QAAQ,QAAQ;AACtB,WAAO,QAAQ,QAAQ,UAAU,SAAY,IAAI,MAAM,GAAG,KAAK,IAAI,GAAG;AAAA,EACxE;AAAA,EAEA,OAAO,MAAgC;AAGrC,WAAO,QAAQ,QAAQ,KAAK;AAAA,EAC9B;AAAA,EAEA,QAA+B;AAC7B,UAAM,MAAM,KAAK,MAAM,MAAM,CAAC,CAAC;AAC/B,QAAI,SAAwB;AAC5B,QAAI,SAAwB;AAC5B,eAAW,KAAK,KAAK;AACnB,YAAM,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ;AACxC,UAAI,WAAW,QAAQ,IAAI,OAAQ,UAAS;AAC5C,UAAI,WAAW,QAAQ,IAAI,OAAQ,UAAS;AAAA,IAC9C;AACA,WAAO,QAAQ,QAAQ;AAAA,MACrB,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK,MAAM;AAAA,MAClB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEA,QAAuB;AAErB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;","names":[]}
|
|
@@ -2,11 +2,10 @@ import {
|
|
|
2
2
|
ModelCapabilitySchema,
|
|
3
3
|
createLogger,
|
|
4
4
|
getInTreeCapabilitiesMatrix
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-I7ORMAO7.js";
|
|
5
|
+
} from "./chunk-WDYCIJWN.js";
|
|
7
6
|
import {
|
|
8
7
|
nexusDataPath
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7BMOZJYS.js";
|
|
10
9
|
import "./chunk-UP2VWCW5.js";
|
|
11
10
|
|
|
12
11
|
// src/cli/registry-command.ts
|
|
@@ -576,4 +575,4 @@ export {
|
|
|
576
575
|
isValidRegistrySubcommand,
|
|
577
576
|
registryCommand
|
|
578
577
|
};
|
|
579
|
-
//# sourceMappingURL=registry-command-
|
|
578
|
+
//# sourceMappingURL=registry-command-6E4YKAMT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/registry-command.ts","../src/config/capability-discovery.ts","../src/config/capability-overlay.ts"],"sourcesContent":["/**\n * `nexus-agents registry` CLI subcommands (epic #2174 / issue #2179).\n *\n * Two subcommands:\n *\n * - `doctor` — inspect CapabilityDiscovery state: tier counts, overlay /\n * bundled paths and status, configured conservative default. Surfaces\n * whatever T3 overlay parse rejections occurred at load. Read-only.\n *\n * - `refresh` — download a signed `model-registry.generated.json` from a\n * URL, SHA256-verify against a `.sha256` sidecar, write to the user's\n * overlay location. Requires `--source=<url>` today; the GitHub-latest-\n * release automation is #2180's concern.\n *\n * No runtime hot path touches the network — refresh is a one-shot,\n * user-initiated operation.\n *\n * @module cli/registry-command\n */\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { nexusDataPath } from '../config/nexus-data-dir.js';\n\nimport {\n defaultGeneratedRegistryPath,\n getCapabilityDiscovery,\n loadBundledGeneratedRegistry,\n type ResolutionTier,\n} from '../config/capability-discovery.js';\nimport {\n OVERLAY_ENV_VAR,\n OVERLAY_MAX_BYTES,\n defaultOverlayPath,\n loadCapabilityOverlay,\n resolveOverlayPath,\n} from '../config/capability-overlay.js';\n\n// ---------------------------------------------------------------------------\n// Dispatch\n// ---------------------------------------------------------------------------\n\nexport type RegistrySubcommand = 'doctor' | 'refresh';\n\nconst VALID_SUBCOMMANDS: readonly RegistrySubcommand[] = ['doctor', 'refresh'];\n\nexport function isValidRegistrySubcommand(v: string | undefined): v is RegistrySubcommand {\n return v !== undefined && (VALID_SUBCOMMANDS as readonly string[]).includes(v);\n}\n\nexport interface RegistryCommandOptions {\n readonly json?: boolean;\n readonly source?: string;\n readonly dryRun?: boolean;\n readonly overlayPath?: string;\n /** For tests: a fetch function. Defaults to `globalThis.fetch`. */\n readonly fetchImpl?: typeof fetch;\n /** For tests: override the default destination path. */\n readonly destPath?: string;\n}\n\nexport interface RegistryCommandResult {\n readonly text: string;\n readonly exitCode: number;\n}\n\nexport async function registryCommand(\n subcommand: RegistrySubcommand,\n options: RegistryCommandOptions = {}\n): Promise<RegistryCommandResult> {\n if (subcommand === 'doctor') return doctorCommand(options);\n return refreshCommand(options);\n}\n\n// ---------------------------------------------------------------------------\n// doctor\n// ---------------------------------------------------------------------------\n\ninterface DoctorReport {\n readonly tierCounts: Record<ResolutionTier, number>;\n readonly bundled: {\n readonly path: string;\n readonly present: boolean;\n readonly entryCount: number | null;\n readonly generatedAt: string | null;\n };\n readonly overlay: {\n readonly path: string;\n readonly status: 'missing' | 'empty' | 'malformed' | 'too-large' | 'loaded';\n readonly entryCount: number;\n readonly rejections: readonly { index: number; id?: string; reason: string }[];\n readonly envOverride: string | undefined;\n };\n readonly conservativeDefault: {\n readonly contextWindow: number;\n readonly maxOutputTokens: number | null;\n };\n}\n\nfunction doctorCommand(options: RegistryCommandOptions): RegistryCommandResult {\n const report = buildDoctorReport(options);\n if (options.json === true) {\n return { text: JSON.stringify(report, null, 2), exitCode: 0 };\n }\n return { text: formatDoctorReport(report), exitCode: 0 };\n}\n\nfunction buildDoctorReport(options: RegistryCommandOptions): DoctorReport {\n const bundledPath = defaultGeneratedRegistryPath();\n const bundled = loadBundledGeneratedRegistry(bundledPath);\n const overlay = loadCapabilityOverlay(options.overlayPath ?? process.env);\n const discovery = getCapabilityDiscovery();\n const fallback = discovery.getConservativeDefault();\n\n return {\n tierCounts: discovery.getTierCounts(),\n bundled: {\n path: bundledPath,\n present: bundled !== null,\n entryCount: bundled !== null ? bundled.entryCount : null,\n generatedAt: bundled !== null ? bundled.generatedAt : null,\n },\n overlay: {\n path: overlay.path,\n status: overlay.status,\n entryCount: overlay.entries.length,\n rejections: overlay.rejections.map((r) => ({\n index: r.index,\n ...(r.id !== undefined ? { id: r.id } : {}),\n reason: r.reason,\n })),\n envOverride: process.env[OVERLAY_ENV_VAR],\n },\n conservativeDefault: {\n contextWindow: fallback.contextWindow,\n maxOutputTokens: fallback.maxOutputTokens ?? null,\n },\n };\n}\n\nfunction formatDoctorReport(r: DoctorReport): string {\n const lines: string[] = [];\n lines.push('nexus-agents registry doctor');\n lines.push('============================');\n lines.push('');\n lines.push('Tier counts (T3 overlay → T1 canonical → T2 bundled → T4 fallback):');\n lines.push(` T3 overlay : ${String(r.tierCounts.t3)}`);\n lines.push(` T1 canonical : ${String(r.tierCounts.t1)}`);\n lines.push(` T2 bundled : ${String(r.tierCounts.t2)}`);\n lines.push('');\n lines.push('T2 bundled registry:');\n lines.push(` path : ${r.bundled.path}`);\n lines.push(` present : ${r.bundled.present ? 'yes' : 'no (using T1 + T4 only)'}`);\n if (r.bundled.present) {\n lines.push(` entryCount : ${String(r.bundled.entryCount ?? '?')}`);\n lines.push(` generatedAt : ${r.bundled.generatedAt ?? '?'}`);\n }\n lines.push('');\n lines.push('T3 user overlay:');\n lines.push(` path : ${r.overlay.path}`);\n lines.push(` status : ${r.overlay.status}`);\n lines.push(` entryCount : ${String(r.overlay.entryCount)}`);\n lines.push(` env override: ${r.overlay.envOverride ?? '(not set)'}`);\n if (r.overlay.rejections.length > 0) {\n lines.push(' rejections :');\n for (const rej of r.overlay.rejections) {\n const idPart = rej.id !== undefined ? ` id=${rej.id}` : '';\n lines.push(` - [${String(rej.index)}]${idPart} ${rej.reason}`);\n }\n }\n lines.push('');\n lines.push('T4 conservative default (for unknown ids):');\n lines.push(` contextWindow : ${String(r.conservativeDefault.contextWindow)}`);\n if (r.conservativeDefault.maxOutputTokens !== null) {\n lines.push(` maxOutputTokens: ${String(r.conservativeDefault.maxOutputTokens)}`);\n }\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// refresh\n// ---------------------------------------------------------------------------\n\nconst MAX_REFRESH_BYTES = 5 * 1024 * 1024;\n\nfunction missingSourceResult(): RegistryCommandResult {\n return {\n text: [\n 'registry refresh requires --source=<url>.',\n '',\n 'The url should point at a model-registry.generated.json file with a',\n 'matching <url>.sha256 sidecar (single line containing the SHA256 hash).',\n '',\n 'A signed GitHub release artifact is a planned default but not wired yet;',\n `that is tracked in #2180. Use --source=<your-mirror-url> in the meantime.`,\n ].join('\\n'),\n exitCode: 2,\n };\n}\n\ninterface VerifiedArtifact {\n readonly body: string;\n readonly sha256: string;\n}\n\nasync function fetchAndVerify(\n source: string,\n fetchImpl: typeof fetch\n): Promise<VerifiedArtifact | RegistryCommandResult> {\n const body = await fetchWithCap(source, fetchImpl);\n if (!body.ok || body.body === undefined) {\n return { text: `Failed to fetch ${source}: ${body.error ?? 'unknown'}`, exitCode: 1 };\n }\n const sha = await fetchWithCap(`${source}.sha256`, fetchImpl);\n if (!sha.ok || sha.body === undefined) {\n return {\n text: `Failed to fetch ${source}.sha256 for integrity check: ${sha.error ?? 'unknown'}`,\n exitCode: 1,\n };\n }\n const expected = sha.body.trim().split(/\\s+/)[0] ?? '';\n if (expected === '') {\n return { text: `SHA256 sidecar at ${source}.sha256 is empty`, exitCode: 1 };\n }\n const actual = createHash('sha256').update(body.body, 'utf-8').digest('hex');\n if (actual.toLowerCase() !== expected.toLowerCase()) {\n return {\n text: `SHA256 mismatch: expected ${expected}, got ${actual}. Aborting write.`,\n exitCode: 1,\n };\n }\n return { body: body.body, sha256: actual };\n}\n\nfunction formatRefreshReport(\n verb: 'would write to' | 'wrote to',\n source: string,\n artifact: VerifiedArtifact,\n dest: string,\n extraTail: readonly string[] = []\n): string {\n return [\n `registry refresh${verb.startsWith('would') ? ' --dry-run' : ''}`,\n `source : ${source}`,\n `sha256 : ${artifact.sha256} (verified)`,\n `bytes : ${String(artifact.body.length)}`,\n `${verb}: ${dest}`,\n ...extraTail,\n ].join('\\n');\n}\n\nasync function refreshCommand(options: RegistryCommandOptions): Promise<RegistryCommandResult> {\n const source = options.source;\n if (source === undefined || source === '') return missingSourceResult();\n\n const artifact = await fetchAndVerify(source, options.fetchImpl ?? fetch);\n if ('text' in artifact) return artifact;\n\n const dest = options.destPath ?? nexusDataPath('model-registry.generated.json');\n if (options.dryRun === true) {\n return { text: formatRefreshReport('would write to', source, artifact, dest), exitCode: 0 };\n }\n\n mkdirSync(dirname(dest), { recursive: true });\n writeFileSync(dest, artifact.body, 'utf-8');\n return {\n text: formatRefreshReport('wrote to', source, artifact, dest, [\n '',\n 'The refreshed file takes precedence over the bundled registry on the next',\n 'run. Restart any running CLI / MCP server for the change to take effect.',\n ]),\n exitCode: 0,\n };\n}\n\ninterface FetchResult {\n readonly ok: boolean;\n readonly body?: string;\n readonly error?: string;\n}\n\nasync function fetchWithCap(url: string, fetchImpl: typeof fetch): Promise<FetchResult> {\n try {\n const response = await fetchImpl(url, { signal: AbortSignal.timeout(30_000) });\n if (!response.ok) {\n return { ok: false, error: `HTTP ${String(response.status)}` };\n }\n const body = await response.text();\n if (body.length > MAX_REFRESH_BYTES) {\n return {\n ok: false,\n error: `payload ${String(body.length)} bytes exceeds cap ${String(MAX_REFRESH_BYTES)}`,\n };\n }\n return { ok: true, body };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Usage\n// ---------------------------------------------------------------------------\n\nexport function formatRegistryUsage(): string {\n return [\n 'Usage:',\n ' nexus-agents registry doctor [--json]',\n ' Inspect the four-tier capability discovery state.',\n '',\n ' nexus-agents registry refresh --source=<url> [--dry-run]',\n ' Download a signed model-registry.generated.json from <url>,',\n ' SHA256-verify against <url>.sha256, and write to:',\n ` ${nexusDataPath('model-registry.generated.json')}`,\n '',\n `Overlay path (T3) is ${defaultOverlayPath()} by default,`,\n `or whatever ${OVERLAY_ENV_VAR} points to. Overlay max size is ${String(OVERLAY_MAX_BYTES)} bytes.`,\n ].join('\\n');\n}\n\n// Dummy references to satisfy unused-var lint when destructuring is conditional.\nvoid existsSync;\nvoid readFileSync;\nvoid resolveOverlayPath;\n","/**\n * CapabilityDiscovery — synchronous four-tier model capability resolution\n * for epic #2174 (child issue #2176).\n *\n * Lookup order: **T3 user YAML overlay → T1 hardcoded canonical → T2 bundled\n * generated → T4 conservative default**. User overlay wins so operators can\n * fix a broken bundled or canonical entry. No runtime network fetch — T2 is\n * loaded once from the bundled JSON (or skipped if the file is missing /\n * corrupt). Injection points exist for tests so no test ever touches the\n * real filesystem or network.\n *\n * This issue (#2176) only delivers the class + tests. Existing call sites\n * keep using the direct T1 helpers in `model-config-helpers.ts` (the\n * registry-backed surface that replaced the legacy `model-capabilities.ts`\n * after #2546 slice E) — those get migrated when #2177 flips the\n * conservative default from the legacy 200 K fall-through to fail-closed\n * 8 K, and when #2178 wires the T3 YAML loader in.\n *\n * @module config/capability-discovery\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { z } from 'zod';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { getInTreeCapabilitiesMatrix } from './model-config-helpers.js';\nimport type {\n ModelCapabilitiesMatrix,\n ModelCapability,\n Pricing,\n} from './model-capabilities-types.js';\nimport { loadCapabilityOverlay } from './capability-overlay.js';\n\n// ---------------------------------------------------------------------------\n// Generated (T2) shape — mirrors scripts/build-model-registry-types.ts\n// ---------------------------------------------------------------------------\n\nconst GeneratedProvenanceSchema = z.object({\n source: z.enum(['models.dev', 'litellm']),\n fetchedAt: z.string(),\n upstreamUrl: z.string(),\n});\n\nexport type GeneratedProvenance = z.infer<typeof GeneratedProvenanceSchema>;\n\nconst GeneratedModelEntrySchema = z.object({\n id: z.string().min(1),\n displayName: z.string().min(1),\n provider: z.string().min(1),\n contextWindow: z.number().int().positive(),\n pricing: z\n .object({\n inputPer1M: z.number().nonnegative(),\n outputPer1M: z.number().nonnegative(),\n })\n .optional(),\n maxOutputTokens: z.number().int().positive().optional(),\n deprecated: z.boolean().optional(),\n provenance: GeneratedProvenanceSchema,\n});\n\nexport type GeneratedModelEntry = z.infer<typeof GeneratedModelEntrySchema>;\n\nconst GeneratedRegistrySchema = z.object({\n version: z.literal(1),\n generatedAt: z.string(),\n entryCount: z.number().int().nonnegative(),\n entries: z.array(GeneratedModelEntrySchema),\n});\n\nexport type GeneratedRegistry = z.infer<typeof GeneratedRegistrySchema>;\n\n// ---------------------------------------------------------------------------\n// T4 conservative-default toggles\n// ---------------------------------------------------------------------------\n\n/** Conservative default returned when no tier resolves a model id. */\nexport interface ConservativeDefault {\n readonly contextWindow: number;\n readonly maxOutputTokens?: number;\n}\n\n/**\n * Legacy default matching today's `getModelContextWindow` 200 K fall-through.\n * Preserved so this issue (#2176) is a pure addition. Issue #2177 will\n * switch the default to `FAIL_CLOSED_DEFAULT` and update the routing paths\n * to skip models resolved at T4.\n */\nexport const LEGACY_200K_DEFAULT: ConservativeDefault = { contextWindow: 200_000 };\n\n/** Fail-closed default that #2177 will flip on. */\nexport const FAIL_CLOSED_DEFAULT: ConservativeDefault = { contextWindow: 8_192 };\n\n// ---------------------------------------------------------------------------\n// ResolvedCapability — unified shape returned by resolve()\n// ---------------------------------------------------------------------------\n\nexport type ResolutionTier = 't1' | 't2' | 't3' | 't4';\n\nexport interface ResolvedCapability {\n readonly tier: ResolutionTier;\n readonly id: string;\n readonly displayName: string;\n readonly provider: string;\n readonly contextWindow: number;\n readonly pricing?: Pricing;\n readonly maxOutputTokens?: number;\n readonly deprecated?: boolean;\n /** Full T1/T3 entry when resolved from the canonical-shaped tiers. */\n readonly canonical?: ModelCapability;\n /** Provenance when resolved from T2. */\n readonly provenance?: GeneratedProvenance;\n}\n\n// ---------------------------------------------------------------------------\n// Config + construction\n// ---------------------------------------------------------------------------\n\nexport interface CapabilityDiscoveryConfig {\n /** T1 canonical registry. Defaults to the in-tree matrix from the ModelRegistry. */\n readonly canonical?: ModelCapabilitiesMatrix;\n /** T2 bundled generated registry. Pass `null` to force-skip T2. */\n readonly generated?: GeneratedRegistry | null;\n /** T3 user overlay entries. Defaults to empty. Loader is #2178. */\n readonly overlay?: readonly ModelCapability[];\n /** T4 fallback. Defaults to `LEGACY_200K_DEFAULT` until #2177 flips it. */\n readonly conservativeDefault?: ConservativeDefault;\n /** Logger; defaults to a named logger. Inject a mock in tests. */\n readonly logger?: ILogger;\n}\n\nexport class CapabilityDiscovery {\n private readonly canonical: ModelCapabilitiesMatrix;\n private readonly generated: GeneratedRegistry | null;\n private readonly overlay: readonly ModelCapability[];\n private readonly fallback: ConservativeDefault;\n private readonly logger: ILogger;\n private readonly generatedById: Map<string, GeneratedModelEntry>;\n\n constructor(config: CapabilityDiscoveryConfig = {}) {\n // The helper returns a readonly view; loosen here because\n // `ModelCapabilitiesMatrix` predates the registry and uses mutable\n // arrays. Callers in this class only read.\n this.canonical = config.canonical ?? (getInTreeCapabilitiesMatrix() as ModelCapabilitiesMatrix);\n this.generated = config.generated ?? null;\n this.overlay = config.overlay ?? [];\n this.fallback = config.conservativeDefault ?? LEGACY_200K_DEFAULT;\n this.logger = config.logger ?? createLogger({ component: 'capability-discovery' });\n\n this.generatedById = new Map();\n if (this.generated !== null) {\n for (const entry of this.generated.entries) {\n this.generatedById.set(entry.id, entry);\n }\n }\n }\n\n /** Synchronously resolve a model id through the four-tier chain. */\n resolve(modelId: string): ResolvedCapability {\n const t3 = this.lookupOverlay(modelId);\n if (t3 !== undefined) return this.fromCanonical('t3', t3);\n\n const t1 = this.lookupCanonical(modelId);\n if (t1 !== undefined) return this.fromCanonical('t1', t1);\n\n const t2 = this.lookupGenerated(modelId);\n if (t2 !== undefined) return this.fromGenerated('t2', t2);\n\n return this.fromFallback(modelId);\n }\n\n /** Exposes the configured fallback for testing / doctor command. */\n getConservativeDefault(): ConservativeDefault {\n return this.fallback;\n }\n\n /** Count of entries per tier — used by `registry doctor` (#2179). */\n getTierCounts(): Record<ResolutionTier, number> {\n return {\n t3: this.overlay.length,\n t1: this.canonical.models.length,\n t2: this.generatedById.size,\n t4: 0,\n };\n }\n\n // -------------------------------------------------------------------------\n // Tier lookups\n // -------------------------------------------------------------------------\n\n private lookupOverlay(modelId: string): ModelCapability | undefined {\n return this.overlay.find((m) => m.id === modelId);\n }\n\n private lookupCanonical(modelId: string): ModelCapability | undefined {\n return this.canonical.models.find((m) => m.id === modelId);\n }\n\n private lookupGenerated(modelId: string): GeneratedModelEntry | undefined {\n const direct = this.generatedById.get(modelId);\n if (direct !== undefined) return direct;\n for (const candidate of buildAliasCandidates(modelId)) {\n const hit = this.generatedById.get(candidate);\n if (hit !== undefined) return hit;\n }\n return undefined;\n }\n\n // -------------------------------------------------------------------------\n // Result shaping\n // -------------------------------------------------------------------------\n\n private fromCanonical(tier: 't1' | 't3', entry: ModelCapability): ResolvedCapability {\n const base: ResolvedCapability = {\n tier,\n id: entry.id,\n displayName: entry.displayName,\n provider: entry.provider,\n contextWindow: entry.contextWindow,\n canonical: entry,\n ...(entry.pricing !== undefined ? { pricing: entry.pricing } : {}),\n ...(entry.maxOutputTokens !== undefined ? { maxOutputTokens: entry.maxOutputTokens } : {}),\n ...(entry.deprecated !== undefined ? { deprecated: entry.deprecated } : {}),\n };\n return base;\n }\n\n private fromGenerated(tier: 't2', entry: GeneratedModelEntry): ResolvedCapability {\n return {\n tier,\n id: entry.id,\n displayName: entry.displayName,\n provider: entry.provider,\n contextWindow: entry.contextWindow,\n provenance: entry.provenance,\n ...(entry.pricing !== undefined ? { pricing: entry.pricing } : {}),\n ...(entry.maxOutputTokens !== undefined ? { maxOutputTokens: entry.maxOutputTokens } : {}),\n ...(entry.deprecated !== undefined ? { deprecated: entry.deprecated } : {}),\n };\n }\n\n private fromFallback(modelId: string): ResolvedCapability {\n this.logger.warn('Model resolved at T4 conservative default', {\n modelId,\n contextWindow: this.fallback.contextWindow,\n });\n return {\n tier: 't4',\n id: modelId,\n displayName: modelId,\n provider: 'unknown',\n contextWindow: this.fallback.contextWindow,\n ...(this.fallback.maxOutputTokens !== undefined\n ? { maxOutputTokens: this.fallback.maxOutputTokens }\n : {}),\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Alias resolution helpers\n// ---------------------------------------------------------------------------\n\nconst KNOWN_PROVIDER_PREFIXES: readonly string[] = [\n 'amazon-bedrock',\n 'google-vertex',\n 'azure-openai',\n 'openrouter',\n 'anthropic',\n 'openai',\n 'google',\n 'deepseek',\n];\n\n/**\n * Generate candidate alias forms so versioned / prefix-stripped ids still\n * resolve to their T2 entry. Example inputs:\n * anthropic.claude-3-5-sonnet-20241022-v2:0\n * openrouter/anthropic/claude-3-5-sonnet\n * gpt-5-codex\n */\nexport function buildAliasCandidates(modelId: string): readonly string[] {\n const seen = new Set<string>([modelId]);\n for (const prefix of KNOWN_PROVIDER_PREFIXES) {\n seen.add(`${prefix}/${modelId}`);\n }\n const slash = modelId.indexOf('/');\n if (slash !== -1) {\n const tail = modelId.slice(slash + 1);\n for (const prefix of KNOWN_PROVIDER_PREFIXES) {\n seen.add(`${prefix}/${tail}`);\n }\n }\n seen.delete(modelId);\n return [...seen];\n}\n\n// ---------------------------------------------------------------------------\n// Bundled T2 loader — used by the global singleton only, injectable for tests\n// ---------------------------------------------------------------------------\n\n/** Path to the bundled generated registry. Test-only export. */\nexport function defaultGeneratedRegistryPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return join(here, 'model-registry.generated.json');\n}\n\n/**\n * Loads the bundled T2 registry synchronously. Returns `null` if the file\n * is missing or fails Zod validation — callers should treat null as \"T2\n * unavailable\" and fall through to T1 + T4. Logs but never throws.\n */\nexport function loadBundledGeneratedRegistry(\n path: string = defaultGeneratedRegistryPath(),\n logger?: ILogger\n): GeneratedRegistry | null {\n const log = logger ?? createLogger({ component: 'capability-discovery' });\n if (!existsSync(path)) {\n log.warn('T2 generated registry file missing; falling back to T1 + T4', { path });\n return null;\n }\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n log.warn('T2 generated registry JSON parse failed; falling back to T1 + T4', {\n path,\n errorMessage: error.message,\n });\n return null;\n }\n const parsed = GeneratedRegistrySchema.safeParse(raw);\n if (!parsed.success) {\n log.warn('T2 generated registry schema validation failed; falling back to T1 + T4', {\n path,\n errorMessage: parsed.error.message,\n });\n return null;\n }\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Global singleton\n// ---------------------------------------------------------------------------\n\nlet globalDiscovery: CapabilityDiscovery | undefined;\n\n/**\n * Global singleton. Lazily constructed on first access using the bundled T2\n * registry + canonical T1. Tests MUST call `setCapabilityDiscovery` with an\n * injected instance to avoid touching the real file.\n */\nexport function getCapabilityDiscovery(): CapabilityDiscovery {\n globalDiscovery ??= new CapabilityDiscovery({\n generated: loadBundledGeneratedRegistry(),\n overlay: loadCapabilityOverlay().entries,\n // Fail-closed default (#2177): unknown models get 8 K context and a\n // structured warn instead of the silent 200 K fall-through the legacy\n // getModelContextWindow used to return.\n conservativeDefault: FAIL_CLOSED_DEFAULT,\n });\n return globalDiscovery;\n}\n\n/** Test-only: inject a discovery instance. */\nexport function setCapabilityDiscovery(discovery: CapabilityDiscovery | undefined): void {\n globalDiscovery = discovery;\n}\n","/**\n * User YAML overlay loader for CapabilityDiscovery's T3 tier (#2178).\n *\n * Reads user-supplied model capability overrides from a YAML file. Fully\n * optional — missing file, empty file, malformed YAML, and schema-invalid\n * entries all return the empty overlay with structured warnings instead of\n * throwing. Operators use this to fix broken bundled / canonical entries\n * without needing an npm release, or to declare models the curated T1 /\n * generated T2 tiers don't cover.\n *\n * Precedent: LiteLLM's `register_model({...})` + aider's\n * `aider/resources/model-settings.yml`.\n *\n * @module config/capability-overlay\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { nexusDataPath } from './nexus-data-dir.js';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { ModelCapabilitySchema } from './model-capabilities-types.js';\nimport type { ModelCapability } from './model-capabilities-types.js';\n\n/** Environment variable an operator can set to override the default path. */\nexport const OVERLAY_ENV_VAR = 'NEXUS_MODEL_REGISTRY_OVERLAY';\n\n/** Max file size accepted for the overlay (1 MB — far larger than expected). */\nexport const OVERLAY_MAX_BYTES = 1 * 1024 * 1024;\n\n/**\n * Default overlay location: `<NEXUS_DATA_DIR>/models.yaml`. Returns the\n * absolute path without checking if it exists.\n */\nexport function defaultOverlayPath(): string {\n return nexusDataPath('models.yaml');\n}\n\n/**\n * Resolves the overlay path: `$NEXUS_MODEL_REGISTRY_OVERLAY` wins if set,\n * otherwise the default `~/.nexus-agents/models.yaml`.\n */\nexport function resolveOverlayPath(env: NodeJS.ProcessEnv = process.env): string {\n const override = env[OVERLAY_ENV_VAR];\n if (override !== undefined && override !== '') return override;\n return defaultOverlayPath();\n}\n\n// ---------------------------------------------------------------------------\n// Result shape\n// ---------------------------------------------------------------------------\n\n/** Structured reason for a rejected or skipped entry. */\nexport interface OverlayRejection {\n readonly index: number;\n readonly id?: string;\n readonly reason: string;\n}\n\nexport interface OverlayLoadResult {\n readonly entries: readonly ModelCapability[];\n readonly rejections: readonly OverlayRejection[];\n readonly path: string;\n readonly status: 'missing' | 'empty' | 'malformed' | 'too-large' | 'loaded';\n}\n\n// ---------------------------------------------------------------------------\n// Loader\n// ---------------------------------------------------------------------------\n\n/**\n * Expected YAML root shape:\n *\n * version: 1\n * models:\n * - id: claude-opus\n * displayName: \"Claude Opus (overridden)\"\n * provider: anthropic\n * contextWindow: 1000000\n * ...\n * - ...\n *\n * or simply:\n *\n * - id: ...\n * ...\n *\n * Both a top-level array and an object with `models:` are accepted for\n * ergonomics; everything else is rejected with a structured reason.\n */\nexport function loadCapabilityOverlay(\n pathOrEnv?: string | NodeJS.ProcessEnv,\n logger?: ILogger\n): OverlayLoadResult {\n const log = logger ?? createLogger({ component: 'capability-overlay' });\n const path = resolvePath(pathOrEnv);\n\n if (!existsSync(path)) {\n return { entries: [], rejections: [], path, status: 'missing' };\n }\n\n const sizeStatus = checkSize(path, log);\n if (sizeStatus !== undefined) return sizeStatus;\n\n const bodyResult = readBody(path, log);\n if ('result' in bodyResult) return bodyResult.result;\n const body = bodyResult.body;\n if (body === '') {\n log.info('Model registry overlay file is empty', { path });\n return { entries: [], rejections: [], path, status: 'empty' };\n }\n\n const parseResult = parseBody(body, path, log);\n if ('result' in parseResult) return parseResult.result;\n const parsed = parseResult.parsed;\n\n const rawEntries = extractEntries(parsed);\n if (rawEntries === undefined) {\n log.warn('Model registry overlay has unrecognized shape; treated as empty', {\n path,\n });\n return {\n entries: [],\n rejections: [{ index: -1, reason: 'Expected array or { models: [...] }' }],\n path,\n status: 'malformed',\n };\n }\n\n const { entries, rejections } = validateEntries(rawEntries, log, path);\n return { entries, rejections, path, status: 'loaded' };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction resolvePath(pathOrEnv: string | NodeJS.ProcessEnv | undefined): string {\n if (typeof pathOrEnv === 'string') return pathOrEnv;\n if (pathOrEnv !== undefined) return resolveOverlayPath(pathOrEnv);\n return resolveOverlayPath();\n}\n\ntype ReadBodyResult = { body: string } | { result: OverlayLoadResult };\nfunction readBody(path: string, log: ILogger): ReadBodyResult {\n try {\n return { body: readFileSync(path, 'utf-8').trim() };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay file read failed; treated as empty', {\n path,\n errorMessage: message,\n });\n return {\n result: {\n entries: [],\n rejections: [{ index: -1, reason: `file read error: ${message}` }],\n path,\n status: 'malformed',\n },\n };\n }\n}\n\ntype ParseBodyResult = { parsed: unknown } | { result: OverlayLoadResult };\nfunction parseBody(body: string, path: string, log: ILogger): ParseBodyResult {\n try {\n return { parsed: parseYaml(body) };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay YAML parse failed; treated as empty', {\n path,\n errorMessage: message,\n });\n return {\n result: {\n entries: [],\n rejections: [{ index: -1, reason: `YAML parse error: ${message}` }],\n path,\n status: 'malformed',\n },\n };\n }\n}\n\nfunction checkSize(path: string, log: ILogger): OverlayLoadResult | undefined {\n let size: number;\n try {\n size = statSync(path).size;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay statSync failed; treated as missing', {\n path,\n errorMessage: message,\n });\n return { entries: [], rejections: [], path, status: 'missing' };\n }\n if (size <= OVERLAY_MAX_BYTES) return undefined;\n log.warn('Model registry overlay exceeds size cap; refusing to load', {\n path,\n size,\n maxBytes: OVERLAY_MAX_BYTES,\n });\n return {\n entries: [],\n rejections: [\n {\n index: -1,\n reason: `file size ${String(size)} exceeds cap ${String(OVERLAY_MAX_BYTES)}`,\n },\n ],\n path,\n status: 'too-large',\n };\n}\n\nfunction extractIdForError(raw: unknown): string | undefined {\n if (raw === null || typeof raw !== 'object' || !('id' in raw)) return undefined;\n const idValue = raw.id;\n if (typeof idValue === 'string' && idValue !== '') return idValue;\n return undefined;\n}\n\nfunction extractEntries(parsed: unknown): unknown[] | undefined {\n if (Array.isArray(parsed)) return parsed as unknown[];\n if (parsed !== null && typeof parsed === 'object') {\n const obj = parsed as { models?: unknown };\n if (Array.isArray(obj.models)) return obj.models as unknown[];\n }\n return undefined;\n}\n\ninterface ValidatedEntries {\n readonly entries: readonly ModelCapability[];\n readonly rejections: readonly OverlayRejection[];\n}\n\nfunction validateEntries(\n rawEntries: readonly unknown[],\n log: ILogger,\n path: string\n): ValidatedEntries {\n const entries: ModelCapability[] = [];\n const rejections: OverlayRejection[] = [];\n for (let i = 0; i < rawEntries.length; i++) {\n const raw = rawEntries[i];\n const idCandidate = extractIdForError(raw);\n const parsed = ModelCapabilitySchema.safeParse(raw);\n if (!parsed.success) {\n const rejection: OverlayRejection = {\n index: i,\n ...(idCandidate !== undefined && idCandidate !== '' ? { id: idCandidate } : {}),\n reason: parsed.error.message,\n };\n rejections.push(rejection);\n log.warn('Model registry overlay entry rejected by schema', {\n path,\n index: i,\n id: idCandidate,\n errorMessage: parsed.error.message,\n });\n continue;\n }\n entries.push(parsed.data);\n }\n return { entries, rejections };\n}\n"],"mappings":"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","names":["existsSync","readFileSync","dirname","readFileSync","existsSync","existsSync","readFileSync","dirname"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/registry-command.ts","../src/config/capability-discovery.ts","../src/config/capability-overlay.ts"],"sourcesContent":["/**\n * `nexus-agents registry` CLI subcommands (epic #2174 / issue #2179).\n *\n * Two subcommands:\n *\n * - `doctor` — inspect CapabilityDiscovery state: tier counts, overlay /\n * bundled paths and status, configured conservative default. Surfaces\n * whatever T3 overlay parse rejections occurred at load. Read-only.\n *\n * - `refresh` — download a signed `model-registry.generated.json` from a\n * URL, SHA256-verify against a `.sha256` sidecar, write to the user's\n * overlay location. Requires `--source=<url>` today; the GitHub-latest-\n * release automation is #2180's concern.\n *\n * No runtime hot path touches the network — refresh is a one-shot,\n * user-initiated operation.\n *\n * @module cli/registry-command\n */\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { nexusDataPath } from '../config/nexus-data-dir.js';\n\nimport {\n defaultGeneratedRegistryPath,\n getCapabilityDiscovery,\n loadBundledGeneratedRegistry,\n type ResolutionTier,\n} from '../config/capability-discovery.js';\nimport {\n OVERLAY_ENV_VAR,\n OVERLAY_MAX_BYTES,\n defaultOverlayPath,\n loadCapabilityOverlay,\n resolveOverlayPath,\n} from '../config/capability-overlay.js';\n\n// ---------------------------------------------------------------------------\n// Dispatch\n// ---------------------------------------------------------------------------\n\nexport type RegistrySubcommand = 'doctor' | 'refresh';\n\nconst VALID_SUBCOMMANDS: readonly RegistrySubcommand[] = ['doctor', 'refresh'];\n\nexport function isValidRegistrySubcommand(v: string | undefined): v is RegistrySubcommand {\n return v !== undefined && (VALID_SUBCOMMANDS as readonly string[]).includes(v);\n}\n\nexport interface RegistryCommandOptions {\n readonly json?: boolean;\n readonly source?: string;\n readonly dryRun?: boolean;\n readonly overlayPath?: string;\n /** For tests: a fetch function. Defaults to `globalThis.fetch`. */\n readonly fetchImpl?: typeof fetch;\n /** For tests: override the default destination path. */\n readonly destPath?: string;\n}\n\nexport interface RegistryCommandResult {\n readonly text: string;\n readonly exitCode: number;\n}\n\nexport async function registryCommand(\n subcommand: RegistrySubcommand,\n options: RegistryCommandOptions = {}\n): Promise<RegistryCommandResult> {\n if (subcommand === 'doctor') return doctorCommand(options);\n return refreshCommand(options);\n}\n\n// ---------------------------------------------------------------------------\n// doctor\n// ---------------------------------------------------------------------------\n\ninterface DoctorReport {\n readonly tierCounts: Record<ResolutionTier, number>;\n readonly bundled: {\n readonly path: string;\n readonly present: boolean;\n readonly entryCount: number | null;\n readonly generatedAt: string | null;\n };\n readonly overlay: {\n readonly path: string;\n readonly status: 'missing' | 'empty' | 'malformed' | 'too-large' | 'loaded';\n readonly entryCount: number;\n readonly rejections: readonly { index: number; id?: string; reason: string }[];\n readonly envOverride: string | undefined;\n };\n readonly conservativeDefault: {\n readonly contextWindow: number;\n readonly maxOutputTokens: number | null;\n };\n}\n\nfunction doctorCommand(options: RegistryCommandOptions): RegistryCommandResult {\n const report = buildDoctorReport(options);\n if (options.json === true) {\n return { text: JSON.stringify(report, null, 2), exitCode: 0 };\n }\n return { text: formatDoctorReport(report), exitCode: 0 };\n}\n\nfunction buildDoctorReport(options: RegistryCommandOptions): DoctorReport {\n const bundledPath = defaultGeneratedRegistryPath();\n const bundled = loadBundledGeneratedRegistry(bundledPath);\n const overlay = loadCapabilityOverlay(options.overlayPath ?? process.env);\n const discovery = getCapabilityDiscovery();\n const fallback = discovery.getConservativeDefault();\n\n return {\n tierCounts: discovery.getTierCounts(),\n bundled: {\n path: bundledPath,\n present: bundled !== null,\n entryCount: bundled !== null ? bundled.entryCount : null,\n generatedAt: bundled !== null ? bundled.generatedAt : null,\n },\n overlay: {\n path: overlay.path,\n status: overlay.status,\n entryCount: overlay.entries.length,\n rejections: overlay.rejections.map((r) => ({\n index: r.index,\n ...(r.id !== undefined ? { id: r.id } : {}),\n reason: r.reason,\n })),\n envOverride: process.env[OVERLAY_ENV_VAR],\n },\n conservativeDefault: {\n contextWindow: fallback.contextWindow,\n maxOutputTokens: fallback.maxOutputTokens ?? null,\n },\n };\n}\n\nfunction formatDoctorReport(r: DoctorReport): string {\n const lines: string[] = [];\n lines.push('nexus-agents registry doctor');\n lines.push('============================');\n lines.push('');\n lines.push('Tier counts (T3 overlay → T1 canonical → T2 bundled → T4 fallback):');\n lines.push(` T3 overlay : ${String(r.tierCounts.t3)}`);\n lines.push(` T1 canonical : ${String(r.tierCounts.t1)}`);\n lines.push(` T2 bundled : ${String(r.tierCounts.t2)}`);\n lines.push('');\n lines.push('T2 bundled registry:');\n lines.push(` path : ${r.bundled.path}`);\n lines.push(` present : ${r.bundled.present ? 'yes' : 'no (using T1 + T4 only)'}`);\n if (r.bundled.present) {\n lines.push(` entryCount : ${String(r.bundled.entryCount ?? '?')}`);\n lines.push(` generatedAt : ${r.bundled.generatedAt ?? '?'}`);\n }\n lines.push('');\n lines.push('T3 user overlay:');\n lines.push(` path : ${r.overlay.path}`);\n lines.push(` status : ${r.overlay.status}`);\n lines.push(` entryCount : ${String(r.overlay.entryCount)}`);\n lines.push(` env override: ${r.overlay.envOverride ?? '(not set)'}`);\n if (r.overlay.rejections.length > 0) {\n lines.push(' rejections :');\n for (const rej of r.overlay.rejections) {\n const idPart = rej.id !== undefined ? ` id=${rej.id}` : '';\n lines.push(` - [${String(rej.index)}]${idPart} ${rej.reason}`);\n }\n }\n lines.push('');\n lines.push('T4 conservative default (for unknown ids):');\n lines.push(` contextWindow : ${String(r.conservativeDefault.contextWindow)}`);\n if (r.conservativeDefault.maxOutputTokens !== null) {\n lines.push(` maxOutputTokens: ${String(r.conservativeDefault.maxOutputTokens)}`);\n }\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// refresh\n// ---------------------------------------------------------------------------\n\nconst MAX_REFRESH_BYTES = 5 * 1024 * 1024;\n\nfunction missingSourceResult(): RegistryCommandResult {\n return {\n text: [\n 'registry refresh requires --source=<url>.',\n '',\n 'The url should point at a model-registry.generated.json file with a',\n 'matching <url>.sha256 sidecar (single line containing the SHA256 hash).',\n '',\n 'A signed GitHub release artifact is a planned default but not wired yet;',\n `that is tracked in #2180. Use --source=<your-mirror-url> in the meantime.`,\n ].join('\\n'),\n exitCode: 2,\n };\n}\n\ninterface VerifiedArtifact {\n readonly body: string;\n readonly sha256: string;\n}\n\nasync function fetchAndVerify(\n source: string,\n fetchImpl: typeof fetch\n): Promise<VerifiedArtifact | RegistryCommandResult> {\n const body = await fetchWithCap(source, fetchImpl);\n if (!body.ok || body.body === undefined) {\n return { text: `Failed to fetch ${source}: ${body.error ?? 'unknown'}`, exitCode: 1 };\n }\n const sha = await fetchWithCap(`${source}.sha256`, fetchImpl);\n if (!sha.ok || sha.body === undefined) {\n return {\n text: `Failed to fetch ${source}.sha256 for integrity check: ${sha.error ?? 'unknown'}`,\n exitCode: 1,\n };\n }\n const expected = sha.body.trim().split(/\\s+/)[0] ?? '';\n if (expected === '') {\n return { text: `SHA256 sidecar at ${source}.sha256 is empty`, exitCode: 1 };\n }\n const actual = createHash('sha256').update(body.body, 'utf-8').digest('hex');\n if (actual.toLowerCase() !== expected.toLowerCase()) {\n return {\n text: `SHA256 mismatch: expected ${expected}, got ${actual}. Aborting write.`,\n exitCode: 1,\n };\n }\n return { body: body.body, sha256: actual };\n}\n\nfunction formatRefreshReport(\n verb: 'would write to' | 'wrote to',\n source: string,\n artifact: VerifiedArtifact,\n dest: string,\n extraTail: readonly string[] = []\n): string {\n return [\n `registry refresh${verb.startsWith('would') ? ' --dry-run' : ''}`,\n `source : ${source}`,\n `sha256 : ${artifact.sha256} (verified)`,\n `bytes : ${String(artifact.body.length)}`,\n `${verb}: ${dest}`,\n ...extraTail,\n ].join('\\n');\n}\n\nasync function refreshCommand(options: RegistryCommandOptions): Promise<RegistryCommandResult> {\n const source = options.source;\n if (source === undefined || source === '') return missingSourceResult();\n\n const artifact = await fetchAndVerify(source, options.fetchImpl ?? fetch);\n if ('text' in artifact) return artifact;\n\n const dest = options.destPath ?? nexusDataPath('model-registry.generated.json');\n if (options.dryRun === true) {\n return { text: formatRefreshReport('would write to', source, artifact, dest), exitCode: 0 };\n }\n\n mkdirSync(dirname(dest), { recursive: true });\n writeFileSync(dest, artifact.body, 'utf-8');\n return {\n text: formatRefreshReport('wrote to', source, artifact, dest, [\n '',\n 'The refreshed file takes precedence over the bundled registry on the next',\n 'run. Restart any running CLI / MCP server for the change to take effect.',\n ]),\n exitCode: 0,\n };\n}\n\ninterface FetchResult {\n readonly ok: boolean;\n readonly body?: string;\n readonly error?: string;\n}\n\nasync function fetchWithCap(url: string, fetchImpl: typeof fetch): Promise<FetchResult> {\n try {\n const response = await fetchImpl(url, { signal: AbortSignal.timeout(30_000) });\n if (!response.ok) {\n return { ok: false, error: `HTTP ${String(response.status)}` };\n }\n const body = await response.text();\n if (body.length > MAX_REFRESH_BYTES) {\n return {\n ok: false,\n error: `payload ${String(body.length)} bytes exceeds cap ${String(MAX_REFRESH_BYTES)}`,\n };\n }\n return { ok: true, body };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Usage\n// ---------------------------------------------------------------------------\n\nexport function formatRegistryUsage(): string {\n return [\n 'Usage:',\n ' nexus-agents registry doctor [--json]',\n ' Inspect the four-tier capability discovery state.',\n '',\n ' nexus-agents registry refresh --source=<url> [--dry-run]',\n ' Download a signed model-registry.generated.json from <url>,',\n ' SHA256-verify against <url>.sha256, and write to:',\n ` ${nexusDataPath('model-registry.generated.json')}`,\n '',\n `Overlay path (T3) is ${defaultOverlayPath()} by default,`,\n `or whatever ${OVERLAY_ENV_VAR} points to. Overlay max size is ${String(OVERLAY_MAX_BYTES)} bytes.`,\n ].join('\\n');\n}\n\n// Dummy references to satisfy unused-var lint when destructuring is conditional.\nvoid existsSync;\nvoid readFileSync;\nvoid resolveOverlayPath;\n","/**\n * CapabilityDiscovery — synchronous four-tier model capability resolution\n * for epic #2174 (child issue #2176).\n *\n * Lookup order: **T3 user YAML overlay → T1 hardcoded canonical → T2 bundled\n * generated → T4 conservative default**. User overlay wins so operators can\n * fix a broken bundled or canonical entry. No runtime network fetch — T2 is\n * loaded once from the bundled JSON (or skipped if the file is missing /\n * corrupt). Injection points exist for tests so no test ever touches the\n * real filesystem or network.\n *\n * This issue (#2176) only delivers the class + tests. Existing call sites\n * keep using the direct T1 helpers in `model-config-helpers.ts` (the\n * registry-backed surface that replaced the legacy `model-capabilities.ts`\n * after #2546 slice E) — those get migrated when #2177 flips the\n * conservative default from the legacy 200 K fall-through to fail-closed\n * 8 K, and when #2178 wires the T3 YAML loader in.\n *\n * @module config/capability-discovery\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { z } from 'zod';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { getInTreeCapabilitiesMatrix } from './model-config-helpers.js';\nimport type {\n ModelCapabilitiesMatrix,\n ModelCapability,\n Pricing,\n} from './model-capabilities-types.js';\nimport { loadCapabilityOverlay } from './capability-overlay.js';\n\n// ---------------------------------------------------------------------------\n// Generated (T2) shape — mirrors scripts/build-model-registry-types.ts\n// ---------------------------------------------------------------------------\n\nconst GeneratedProvenanceSchema = z.object({\n source: z.enum(['models.dev', 'litellm']),\n fetchedAt: z.string(),\n upstreamUrl: z.string(),\n});\n\nexport type GeneratedProvenance = z.infer<typeof GeneratedProvenanceSchema>;\n\nconst GeneratedModelEntrySchema = z.object({\n id: z.string().min(1),\n displayName: z.string().min(1),\n provider: z.string().min(1),\n contextWindow: z.number().int().positive(),\n pricing: z\n .object({\n inputPer1M: z.number().nonnegative(),\n outputPer1M: z.number().nonnegative(),\n })\n .optional(),\n maxOutputTokens: z.number().int().positive().optional(),\n deprecated: z.boolean().optional(),\n provenance: GeneratedProvenanceSchema,\n});\n\nexport type GeneratedModelEntry = z.infer<typeof GeneratedModelEntrySchema>;\n\nconst GeneratedRegistrySchema = z.object({\n version: z.literal(1),\n generatedAt: z.string(),\n entryCount: z.number().int().nonnegative(),\n entries: z.array(GeneratedModelEntrySchema),\n});\n\nexport type GeneratedRegistry = z.infer<typeof GeneratedRegistrySchema>;\n\n// ---------------------------------------------------------------------------\n// T4 conservative-default toggles\n// ---------------------------------------------------------------------------\n\n/** Conservative default returned when no tier resolves a model id. */\nexport interface ConservativeDefault {\n readonly contextWindow: number;\n readonly maxOutputTokens?: number;\n}\n\n/**\n * Legacy default matching today's `getModelContextWindow` 200 K fall-through.\n * Preserved so this issue (#2176) is a pure addition. Issue #2177 will\n * switch the default to `FAIL_CLOSED_DEFAULT` and update the routing paths\n * to skip models resolved at T4.\n */\nexport const LEGACY_200K_DEFAULT: ConservativeDefault = { contextWindow: 200_000 };\n\n/** Fail-closed default that #2177 will flip on. */\nexport const FAIL_CLOSED_DEFAULT: ConservativeDefault = { contextWindow: 8_192 };\n\n// ---------------------------------------------------------------------------\n// ResolvedCapability — unified shape returned by resolve()\n// ---------------------------------------------------------------------------\n\nexport type ResolutionTier = 't1' | 't2' | 't3' | 't4';\n\nexport interface ResolvedCapability {\n readonly tier: ResolutionTier;\n readonly id: string;\n readonly displayName: string;\n readonly provider: string;\n readonly contextWindow: number;\n readonly pricing?: Pricing;\n readonly maxOutputTokens?: number;\n readonly deprecated?: boolean;\n /** Full T1/T3 entry when resolved from the canonical-shaped tiers. */\n readonly canonical?: ModelCapability;\n /** Provenance when resolved from T2. */\n readonly provenance?: GeneratedProvenance;\n}\n\n// ---------------------------------------------------------------------------\n// Config + construction\n// ---------------------------------------------------------------------------\n\nexport interface CapabilityDiscoveryConfig {\n /** T1 canonical registry. Defaults to the in-tree matrix from the ModelRegistry. */\n readonly canonical?: ModelCapabilitiesMatrix;\n /** T2 bundled generated registry. Pass `null` to force-skip T2. */\n readonly generated?: GeneratedRegistry | null;\n /** T3 user overlay entries. Defaults to empty. Loader is #2178. */\n readonly overlay?: readonly ModelCapability[];\n /** T4 fallback. Defaults to `LEGACY_200K_DEFAULT` until #2177 flips it. */\n readonly conservativeDefault?: ConservativeDefault;\n /** Logger; defaults to a named logger. Inject a mock in tests. */\n readonly logger?: ILogger;\n}\n\nexport class CapabilityDiscovery {\n private readonly canonical: ModelCapabilitiesMatrix;\n private readonly generated: GeneratedRegistry | null;\n private readonly overlay: readonly ModelCapability[];\n private readonly fallback: ConservativeDefault;\n private readonly logger: ILogger;\n private readonly generatedById: Map<string, GeneratedModelEntry>;\n\n constructor(config: CapabilityDiscoveryConfig = {}) {\n // The helper returns a readonly view; loosen here because\n // `ModelCapabilitiesMatrix` predates the registry and uses mutable\n // arrays. Callers in this class only read.\n this.canonical = config.canonical ?? (getInTreeCapabilitiesMatrix() as ModelCapabilitiesMatrix);\n this.generated = config.generated ?? null;\n this.overlay = config.overlay ?? [];\n this.fallback = config.conservativeDefault ?? LEGACY_200K_DEFAULT;\n this.logger = config.logger ?? createLogger({ component: 'capability-discovery' });\n\n this.generatedById = new Map();\n if (this.generated !== null) {\n for (const entry of this.generated.entries) {\n this.generatedById.set(entry.id, entry);\n }\n }\n }\n\n /** Synchronously resolve a model id through the four-tier chain. */\n resolve(modelId: string): ResolvedCapability {\n const t3 = this.lookupOverlay(modelId);\n if (t3 !== undefined) return this.fromCanonical('t3', t3);\n\n const t1 = this.lookupCanonical(modelId);\n if (t1 !== undefined) return this.fromCanonical('t1', t1);\n\n const t2 = this.lookupGenerated(modelId);\n if (t2 !== undefined) return this.fromGenerated('t2', t2);\n\n return this.fromFallback(modelId);\n }\n\n /** Exposes the configured fallback for testing / doctor command. */\n getConservativeDefault(): ConservativeDefault {\n return this.fallback;\n }\n\n /** Count of entries per tier — used by `registry doctor` (#2179). */\n getTierCounts(): Record<ResolutionTier, number> {\n return {\n t3: this.overlay.length,\n t1: this.canonical.models.length,\n t2: this.generatedById.size,\n t4: 0,\n };\n }\n\n // -------------------------------------------------------------------------\n // Tier lookups\n // -------------------------------------------------------------------------\n\n private lookupOverlay(modelId: string): ModelCapability | undefined {\n return this.overlay.find((m) => m.id === modelId);\n }\n\n private lookupCanonical(modelId: string): ModelCapability | undefined {\n return this.canonical.models.find((m) => m.id === modelId);\n }\n\n private lookupGenerated(modelId: string): GeneratedModelEntry | undefined {\n const direct = this.generatedById.get(modelId);\n if (direct !== undefined) return direct;\n for (const candidate of buildAliasCandidates(modelId)) {\n const hit = this.generatedById.get(candidate);\n if (hit !== undefined) return hit;\n }\n return undefined;\n }\n\n // -------------------------------------------------------------------------\n // Result shaping\n // -------------------------------------------------------------------------\n\n private fromCanonical(tier: 't1' | 't3', entry: ModelCapability): ResolvedCapability {\n const base: ResolvedCapability = {\n tier,\n id: entry.id,\n displayName: entry.displayName,\n provider: entry.provider,\n contextWindow: entry.contextWindow,\n canonical: entry,\n ...(entry.pricing !== undefined ? { pricing: entry.pricing } : {}),\n ...(entry.maxOutputTokens !== undefined ? { maxOutputTokens: entry.maxOutputTokens } : {}),\n ...(entry.deprecated !== undefined ? { deprecated: entry.deprecated } : {}),\n };\n return base;\n }\n\n private fromGenerated(tier: 't2', entry: GeneratedModelEntry): ResolvedCapability {\n return {\n tier,\n id: entry.id,\n displayName: entry.displayName,\n provider: entry.provider,\n contextWindow: entry.contextWindow,\n provenance: entry.provenance,\n ...(entry.pricing !== undefined ? { pricing: entry.pricing } : {}),\n ...(entry.maxOutputTokens !== undefined ? { maxOutputTokens: entry.maxOutputTokens } : {}),\n ...(entry.deprecated !== undefined ? { deprecated: entry.deprecated } : {}),\n };\n }\n\n private fromFallback(modelId: string): ResolvedCapability {\n this.logger.warn('Model resolved at T4 conservative default', {\n modelId,\n contextWindow: this.fallback.contextWindow,\n });\n return {\n tier: 't4',\n id: modelId,\n displayName: modelId,\n provider: 'unknown',\n contextWindow: this.fallback.contextWindow,\n ...(this.fallback.maxOutputTokens !== undefined\n ? { maxOutputTokens: this.fallback.maxOutputTokens }\n : {}),\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Alias resolution helpers\n// ---------------------------------------------------------------------------\n\nconst KNOWN_PROVIDER_PREFIXES: readonly string[] = [\n 'amazon-bedrock',\n 'google-vertex',\n 'azure-openai',\n 'openrouter',\n 'anthropic',\n 'openai',\n 'google',\n 'deepseek',\n];\n\n/**\n * Generate candidate alias forms so versioned / prefix-stripped ids still\n * resolve to their T2 entry. Example inputs:\n * anthropic.claude-3-5-sonnet-20241022-v2:0\n * openrouter/anthropic/claude-3-5-sonnet\n * gpt-5-codex\n */\nexport function buildAliasCandidates(modelId: string): readonly string[] {\n const seen = new Set<string>([modelId]);\n for (const prefix of KNOWN_PROVIDER_PREFIXES) {\n seen.add(`${prefix}/${modelId}`);\n }\n const slash = modelId.indexOf('/');\n if (slash !== -1) {\n const tail = modelId.slice(slash + 1);\n for (const prefix of KNOWN_PROVIDER_PREFIXES) {\n seen.add(`${prefix}/${tail}`);\n }\n }\n seen.delete(modelId);\n return [...seen];\n}\n\n// ---------------------------------------------------------------------------\n// Bundled T2 loader — used by the global singleton only, injectable for tests\n// ---------------------------------------------------------------------------\n\n/** Path to the bundled generated registry. Test-only export. */\nexport function defaultGeneratedRegistryPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return join(here, 'model-registry.generated.json');\n}\n\n/**\n * Loads the bundled T2 registry synchronously. Returns `null` if the file\n * is missing or fails Zod validation — callers should treat null as \"T2\n * unavailable\" and fall through to T1 + T4. Logs but never throws.\n */\nexport function loadBundledGeneratedRegistry(\n path: string = defaultGeneratedRegistryPath(),\n logger?: ILogger\n): GeneratedRegistry | null {\n const log = logger ?? createLogger({ component: 'capability-discovery' });\n if (!existsSync(path)) {\n log.warn('T2 generated registry file missing; falling back to T1 + T4', { path });\n return null;\n }\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n log.warn('T2 generated registry JSON parse failed; falling back to T1 + T4', {\n path,\n errorMessage: error.message,\n });\n return null;\n }\n const parsed = GeneratedRegistrySchema.safeParse(raw);\n if (!parsed.success) {\n log.warn('T2 generated registry schema validation failed; falling back to T1 + T4', {\n path,\n errorMessage: parsed.error.message,\n });\n return null;\n }\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Global singleton\n// ---------------------------------------------------------------------------\n\nlet globalDiscovery: CapabilityDiscovery | undefined;\n\n/**\n * Global singleton. Lazily constructed on first access using the bundled T2\n * registry + canonical T1. Tests MUST call `setCapabilityDiscovery` with an\n * injected instance to avoid touching the real file.\n */\nexport function getCapabilityDiscovery(): CapabilityDiscovery {\n globalDiscovery ??= new CapabilityDiscovery({\n generated: loadBundledGeneratedRegistry(),\n overlay: loadCapabilityOverlay().entries,\n // Fail-closed default (#2177): unknown models get 8 K context and a\n // structured warn instead of the silent 200 K fall-through the legacy\n // getModelContextWindow used to return.\n conservativeDefault: FAIL_CLOSED_DEFAULT,\n });\n return globalDiscovery;\n}\n\n/** Test-only: inject a discovery instance. */\nexport function setCapabilityDiscovery(discovery: CapabilityDiscovery | undefined): void {\n globalDiscovery = discovery;\n}\n","/**\n * User YAML overlay loader for CapabilityDiscovery's T3 tier (#2178).\n *\n * Reads user-supplied model capability overrides from a YAML file. Fully\n * optional — missing file, empty file, malformed YAML, and schema-invalid\n * entries all return the empty overlay with structured warnings instead of\n * throwing. Operators use this to fix broken bundled / canonical entries\n * without needing an npm release, or to declare models the curated T1 /\n * generated T2 tiers don't cover.\n *\n * Precedent: LiteLLM's `register_model({...})` + aider's\n * `aider/resources/model-settings.yml`.\n *\n * @module config/capability-overlay\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { nexusDataPath } from './nexus-data-dir.js';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { ModelCapabilitySchema } from './model-capabilities-types.js';\nimport type { ModelCapability } from './model-capabilities-types.js';\n\n/** Environment variable an operator can set to override the default path. */\nexport const OVERLAY_ENV_VAR = 'NEXUS_MODEL_REGISTRY_OVERLAY';\n\n/** Max file size accepted for the overlay (1 MB — far larger than expected). */\nexport const OVERLAY_MAX_BYTES = 1 * 1024 * 1024;\n\n/**\n * Default overlay location: `<NEXUS_DATA_DIR>/models.yaml`. Returns the\n * absolute path without checking if it exists.\n */\nexport function defaultOverlayPath(): string {\n return nexusDataPath('models.yaml');\n}\n\n/**\n * Resolves the overlay path: `$NEXUS_MODEL_REGISTRY_OVERLAY` wins if set,\n * otherwise the default `~/.nexus-agents/models.yaml`.\n */\nexport function resolveOverlayPath(env: NodeJS.ProcessEnv = process.env): string {\n const override = env[OVERLAY_ENV_VAR];\n if (override !== undefined && override !== '') return override;\n return defaultOverlayPath();\n}\n\n// ---------------------------------------------------------------------------\n// Result shape\n// ---------------------------------------------------------------------------\n\n/** Structured reason for a rejected or skipped entry. */\nexport interface OverlayRejection {\n readonly index: number;\n readonly id?: string;\n readonly reason: string;\n}\n\nexport interface OverlayLoadResult {\n readonly entries: readonly ModelCapability[];\n readonly rejections: readonly OverlayRejection[];\n readonly path: string;\n readonly status: 'missing' | 'empty' | 'malformed' | 'too-large' | 'loaded';\n}\n\n// ---------------------------------------------------------------------------\n// Loader\n// ---------------------------------------------------------------------------\n\n/**\n * Expected YAML root shape:\n *\n * version: 1\n * models:\n * - id: claude-opus\n * displayName: \"Claude Opus (overridden)\"\n * provider: anthropic\n * contextWindow: 1000000\n * ...\n * - ...\n *\n * or simply:\n *\n * - id: ...\n * ...\n *\n * Both a top-level array and an object with `models:` are accepted for\n * ergonomics; everything else is rejected with a structured reason.\n */\nexport function loadCapabilityOverlay(\n pathOrEnv?: string | NodeJS.ProcessEnv,\n logger?: ILogger\n): OverlayLoadResult {\n const log = logger ?? createLogger({ component: 'capability-overlay' });\n const path = resolvePath(pathOrEnv);\n\n if (!existsSync(path)) {\n return { entries: [], rejections: [], path, status: 'missing' };\n }\n\n const sizeStatus = checkSize(path, log);\n if (sizeStatus !== undefined) return sizeStatus;\n\n const bodyResult = readBody(path, log);\n if ('result' in bodyResult) return bodyResult.result;\n const body = bodyResult.body;\n if (body === '') {\n log.info('Model registry overlay file is empty', { path });\n return { entries: [], rejections: [], path, status: 'empty' };\n }\n\n const parseResult = parseBody(body, path, log);\n if ('result' in parseResult) return parseResult.result;\n const parsed = parseResult.parsed;\n\n const rawEntries = extractEntries(parsed);\n if (rawEntries === undefined) {\n log.warn('Model registry overlay has unrecognized shape; treated as empty', {\n path,\n });\n return {\n entries: [],\n rejections: [{ index: -1, reason: 'Expected array or { models: [...] }' }],\n path,\n status: 'malformed',\n };\n }\n\n const { entries, rejections } = validateEntries(rawEntries, log, path);\n return { entries, rejections, path, status: 'loaded' };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction resolvePath(pathOrEnv: string | NodeJS.ProcessEnv | undefined): string {\n if (typeof pathOrEnv === 'string') return pathOrEnv;\n if (pathOrEnv !== undefined) return resolveOverlayPath(pathOrEnv);\n return resolveOverlayPath();\n}\n\ntype ReadBodyResult = { body: string } | { result: OverlayLoadResult };\nfunction readBody(path: string, log: ILogger): ReadBodyResult {\n try {\n return { body: readFileSync(path, 'utf-8').trim() };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay file read failed; treated as empty', {\n path,\n errorMessage: message,\n });\n return {\n result: {\n entries: [],\n rejections: [{ index: -1, reason: `file read error: ${message}` }],\n path,\n status: 'malformed',\n },\n };\n }\n}\n\ntype ParseBodyResult = { parsed: unknown } | { result: OverlayLoadResult };\nfunction parseBody(body: string, path: string, log: ILogger): ParseBodyResult {\n try {\n return { parsed: parseYaml(body) };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay YAML parse failed; treated as empty', {\n path,\n errorMessage: message,\n });\n return {\n result: {\n entries: [],\n rejections: [{ index: -1, reason: `YAML parse error: ${message}` }],\n path,\n status: 'malformed',\n },\n };\n }\n}\n\nfunction checkSize(path: string, log: ILogger): OverlayLoadResult | undefined {\n let size: number;\n try {\n size = statSync(path).size;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay statSync failed; treated as missing', {\n path,\n errorMessage: message,\n });\n return { entries: [], rejections: [], path, status: 'missing' };\n }\n if (size <= OVERLAY_MAX_BYTES) return undefined;\n log.warn('Model registry overlay exceeds size cap; refusing to load', {\n path,\n size,\n maxBytes: OVERLAY_MAX_BYTES,\n });\n return {\n entries: [],\n rejections: [\n {\n index: -1,\n reason: `file size ${String(size)} exceeds cap ${String(OVERLAY_MAX_BYTES)}`,\n },\n ],\n path,\n status: 'too-large',\n };\n}\n\nfunction extractIdForError(raw: unknown): string | undefined {\n if (raw === null || typeof raw !== 'object' || !('id' in raw)) return undefined;\n const idValue = raw.id;\n if (typeof idValue === 'string' && idValue !== '') return idValue;\n return undefined;\n}\n\nfunction extractEntries(parsed: unknown): unknown[] | undefined {\n if (Array.isArray(parsed)) return parsed as unknown[];\n if (parsed !== null && typeof parsed === 'object') {\n const obj = parsed as { models?: unknown };\n if (Array.isArray(obj.models)) return obj.models as unknown[];\n }\n return undefined;\n}\n\ninterface ValidatedEntries {\n readonly entries: readonly ModelCapability[];\n readonly rejections: readonly OverlayRejection[];\n}\n\nfunction validateEntries(\n rawEntries: readonly unknown[],\n log: ILogger,\n path: string\n): ValidatedEntries {\n const entries: ModelCapability[] = [];\n const rejections: OverlayRejection[] = [];\n for (let i = 0; i < rawEntries.length; i++) {\n const raw = rawEntries[i];\n const idCandidate = extractIdForError(raw);\n const parsed = ModelCapabilitySchema.safeParse(raw);\n if (!parsed.success) {\n const rejection: OverlayRejection = {\n index: i,\n ...(idCandidate !== undefined && idCandidate !== '' ? { id: idCandidate } : {}),\n reason: parsed.error.message,\n };\n rejections.push(rejection);\n log.warn('Model registry overlay entry rejected by schema', {\n path,\n index: i,\n id: idCandidate,\n errorMessage: parsed.error.message,\n });\n continue;\n }\n entries.push(parsed.data);\n }\n return { entries, rejections };\n}\n"],"mappings":"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","names":["existsSync","readFileSync","dirname","readFileSync","existsSync","existsSync","readFileSync","dirname"]}
|
|
@@ -3,11 +3,10 @@ import {
|
|
|
3
3
|
buildPlanFromAnalysis,
|
|
4
4
|
generateSecurityPlan,
|
|
5
5
|
resolveScannerData
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-FJWWSVWB.js";
|
|
7
7
|
import "./chunk-7J7PNOJQ.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-GOT7OAL5.js";
|
|
8
|
+
import "./chunk-WDYCIJWN.js";
|
|
9
|
+
import "./chunk-7BMOZJYS.js";
|
|
11
10
|
import "./chunk-UP2VWCW5.js";
|
|
12
11
|
export {
|
|
13
12
|
FALLBACK_SCANNER_DATA,
|
|
@@ -15,4 +14,4 @@ export {
|
|
|
15
14
|
generateSecurityPlan,
|
|
16
15
|
resolveScannerData
|
|
17
16
|
};
|
|
18
|
-
//# sourceMappingURL=repo-security-plan-
|
|
17
|
+
//# sourceMappingURL=repo-security-plan-AGRU72DL.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AttributedInsightSchema,
|
|
3
|
+
synthesizeResearch
|
|
4
|
+
} from "./chunk-5O6XLBPP.js";
|
|
5
|
+
import "./chunk-NUBSJGQZ.js";
|
|
6
|
+
import "./chunk-WDYCIJWN.js";
|
|
7
|
+
import "./chunk-7BMOZJYS.js";
|
|
8
|
+
import "./chunk-UP2VWCW5.js";
|
|
9
|
+
export {
|
|
10
|
+
AttributedInsightSchema,
|
|
11
|
+
synthesizeResearch
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=research-helpers-synthesize-K2UCJQQG.js.map
|
|
@@ -2,13 +2,12 @@ import {
|
|
|
2
2
|
DEFAULT_ROUTING_MEMORY_CONFIG,
|
|
3
3
|
RoutingMemory,
|
|
4
4
|
createRoutingMemory
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-GOT7OAL5.js";
|
|
5
|
+
} from "./chunk-WDYCIJWN.js";
|
|
6
|
+
import "./chunk-7BMOZJYS.js";
|
|
8
7
|
import "./chunk-UP2VWCW5.js";
|
|
9
8
|
export {
|
|
10
9
|
DEFAULT_ROUTING_MEMORY_CONFIG,
|
|
11
10
|
RoutingMemory,
|
|
12
11
|
createRoutingMemory
|
|
13
12
|
};
|
|
14
|
-
//# sourceMappingURL=routing-memory-
|
|
13
|
+
//# sourceMappingURL=routing-memory-3B6DDZ76.js.map
|
|
@@ -6,10 +6,9 @@ import {
|
|
|
6
6
|
SessionMemory,
|
|
7
7
|
SessionMemoryError,
|
|
8
8
|
createSessionMemory
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-GOT7OAL5.js";
|
|
9
|
+
} from "./chunk-3NIPH6UP.js";
|
|
10
|
+
import "./chunk-WDYCIJWN.js";
|
|
11
|
+
import "./chunk-7BMOZJYS.js";
|
|
13
12
|
import "./chunk-UP2VWCW5.js";
|
|
14
13
|
export {
|
|
15
14
|
CompletedTaskSchema,
|
|
@@ -20,4 +19,4 @@ export {
|
|
|
20
19
|
SessionMemoryError,
|
|
21
20
|
createSessionMemory
|
|
22
21
|
};
|
|
23
|
-
//# sourceMappingURL=session-memory-
|
|
22
|
+
//# sourceMappingURL=session-memory-L7EQIY2O.js.map
|
|
@@ -7,19 +7,18 @@ import {
|
|
|
7
7
|
runWizard,
|
|
8
8
|
setupCommand,
|
|
9
9
|
setupCommandAsync
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-GTGDVBLW.js";
|
|
11
|
+
import "./chunk-YXWGEIQR.js";
|
|
12
|
+
import "./chunk-4N33QZLH.js";
|
|
13
|
+
import "./chunk-KT5FIBWS.js";
|
|
14
|
+
import "./chunk-HYU4GZY6.js";
|
|
15
15
|
import "./chunk-NUBSJGQZ.js";
|
|
16
|
-
import "./chunk-TDV5ALHY.js";
|
|
17
|
-
import "./chunk-ZM4O442V.js";
|
|
18
16
|
import "./chunk-633WH2ML.js";
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-D6TM2VHX.js";
|
|
18
|
+
import "./chunk-DLXT23AC.js";
|
|
19
|
+
import "./chunk-ZM4O442V.js";
|
|
20
|
+
import "./chunk-WDYCIJWN.js";
|
|
21
|
+
import "./chunk-7BMOZJYS.js";
|
|
23
22
|
import "./chunk-UP2VWCW5.js";
|
|
24
23
|
export {
|
|
25
24
|
detectEnvironment,
|
|
@@ -31,4 +30,4 @@ export {
|
|
|
31
30
|
setupCommand,
|
|
32
31
|
setupCommandAsync
|
|
33
32
|
};
|
|
34
|
-
//# sourceMappingURL=setup-command-
|
|
33
|
+
//# sourceMappingURL=setup-command-VYV4RFWW.js.map
|
|
@@ -2,16 +2,15 @@ import {
|
|
|
2
2
|
CUSTOM_API_ALLOW_PRIVATE_ENV,
|
|
3
3
|
CUSTOM_API_BASE_URL_ENV,
|
|
4
4
|
validateCustomApiBaseUrl
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZVCED4Z4.js";
|
|
6
6
|
import {
|
|
7
7
|
CUSTOM_API_DEFAULT_MODEL
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HYU4GZY6.js";
|
|
9
9
|
import {
|
|
10
10
|
err,
|
|
11
11
|
ok
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-GOT7OAL5.js";
|
|
12
|
+
} from "./chunk-WDYCIJWN.js";
|
|
13
|
+
import "./chunk-7BMOZJYS.js";
|
|
15
14
|
import "./chunk-UP2VWCW5.js";
|
|
16
15
|
|
|
17
16
|
// src/cli/setup-custom-api.ts
|
|
@@ -107,4 +106,4 @@ function buildShellFragment(params) {
|
|
|
107
106
|
export {
|
|
108
107
|
configureCustomApi
|
|
109
108
|
};
|
|
110
|
-
//# sourceMappingURL=setup-custom-api-
|
|
109
|
+
//# sourceMappingURL=setup-custom-api-IBDV654K.js.map
|