nexus-agents 2.99.0 → 2.100.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{chunk-VPH2M5H7.js → chunk-GEXFJOLK.js} +4 -4
  2. package/dist/{chunk-VPH2M5H7.js.map → chunk-GEXFJOLK.js.map} +1 -1
  3. package/dist/{chunk-6IHEDRKI.js → chunk-H4LBBFCO.js} +2 -2
  4. package/dist/{chunk-WHFCVKAV.js → chunk-NZC5NLUD.js} +3 -3
  5. package/dist/{chunk-EM7NUGMG.js → chunk-P453545L.js} +21 -2
  6. package/dist/chunk-P453545L.js.map +1 -0
  7. package/dist/{chunk-AN3IGMJT.js → chunk-TYELRYRO.js} +9 -4
  8. package/dist/chunk-TYELRYRO.js.map +1 -0
  9. package/dist/{chunk-O6EXYWHP.js → chunk-VXNN3JKU.js} +144 -82
  10. package/dist/{chunk-O6EXYWHP.js.map → chunk-VXNN3JKU.js.map} +1 -1
  11. package/dist/cli.js +14 -9
  12. package/dist/cli.js.map +1 -1
  13. package/dist/{consensus-vote-5D7FNWYM.js → consensus-vote-PGOS5AA6.js} +3 -3
  14. package/dist/{dist-75MXB4R3.js → dist-NGFMLKZR.js} +2232 -1558
  15. package/dist/dist-NGFMLKZR.js.map +1 -0
  16. package/dist/{expert-bridge-EOVHUCJ4.js → expert-bridge-L25WFHQF.js} +2 -2
  17. package/dist/{factory-NJRJAZKK.js → factory-PVN7DDNZ.js} +2 -2
  18. package/dist/index.d.ts +27 -0
  19. package/dist/index.js +6 -6
  20. package/dist/{registry-command-AX7Z4K4W.js → registry-command-5L7I44JA.js} +31 -8
  21. package/dist/registry-command-5L7I44JA.js.map +1 -0
  22. package/dist/{setup-command-PHTP43V7.js → setup-command-COISAIOH.js} +4 -4
  23. package/package.json +10 -10
  24. package/dist/chunk-AN3IGMJT.js.map +0 -1
  25. package/dist/chunk-EM7NUGMG.js.map +0 -1
  26. package/dist/dist-75MXB4R3.js.map +0 -1
  27. package/dist/registry-command-AX7Z4K4W.js.map +0 -1
  28. /package/dist/{chunk-6IHEDRKI.js.map → chunk-H4LBBFCO.js.map} +0 -0
  29. /package/dist/{chunk-WHFCVKAV.js.map → chunk-NZC5NLUD.js.map} +0 -0
  30. /package/dist/{consensus-vote-5D7FNWYM.js.map → consensus-vote-PGOS5AA6.js.map} +0 -0
  31. /package/dist/{expert-bridge-EOVHUCJ4.js.map → expert-bridge-L25WFHQF.js.map} +0 -0
  32. /package/dist/{factory-NJRJAZKK.js.map → factory-PVN7DDNZ.js.map} +0 -0
  33. /package/dist/{setup-command-PHTP43V7.js.map → setup-command-COISAIOH.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeExpert,
3
3
  shutdownExpertBridge
4
- } from "./chunk-6IHEDRKI.js";
4
+ } from "./chunk-H4LBBFCO.js";
5
5
  import "./chunk-HBZUXO4Q.js";
6
6
  import "./chunk-M774MKHE.js";
7
7
  import "./chunk-CH7QIDHQ.js";
@@ -10,4 +10,4 @@ export {
10
10
  executeExpert,
11
11
  shutdownExpertBridge
12
12
  };
13
- //# sourceMappingURL=expert-bridge-EOVHUCJ4.js.map
13
+ //# sourceMappingURL=expert-bridge-L25WFHQF.js.map
@@ -3,7 +3,7 @@ import {
3
3
  createCliAdapter,
4
4
  getAvailableClis,
5
5
  isCliAvailable
6
- } from "./chunk-EM7NUGMG.js";
6
+ } from "./chunk-P453545L.js";
7
7
  import "./chunk-A7XUXJWL.js";
8
8
  import "./chunk-AH67WRET.js";
9
9
  import "./chunk-M774MKHE.js";
@@ -15,4 +15,4 @@ export {
15
15
  getAvailableClis,
16
16
  isCliAvailable
17
17
  };
18
- //# sourceMappingURL=factory-NJRJAZKK.js.map
18
+ //# sourceMappingURL=factory-PVN7DDNZ.js.map
package/dist/index.d.ts CHANGED
@@ -31692,6 +31692,17 @@ interface DevPipelineStages {
31692
31692
  implement(task: PipelineTask): Promise<string>;
31693
31693
  /** QA expert reviews implementation. */
31694
31694
  qaReview(task: PipelineTask, implementation: string): Promise<QaReviewResult>;
31695
+ /**
31696
+ * Local QA quality gate (typecheck/lint/tests/build) run before ship (#3356).
31697
+ * Optional: pipelines that don't supply it simply skip the gate. Returns
31698
+ * `passed` plus actionable `feedback` from the underlying `runQualityGate`
31699
+ * engine. Whether a red gate fails the phase is governed by the
31700
+ * `qualityGate` mode in {@link DevPipelineOptions}, not this method.
31701
+ */
31702
+ qualityGate?(): Promise<{
31703
+ passed: boolean;
31704
+ feedback: string;
31705
+ }>;
31695
31706
  /** Security scan. Returns true if passed. */
31696
31707
  securityScan(): Promise<{
31697
31708
  passed: boolean;
@@ -31700,6 +31711,15 @@ interface DevPipelineStages {
31700
31711
  }
31701
31712
  /** Pipeline execution mode. */
31702
31713
  type PipelineMode = 'autonomous' | 'harness';
31714
+ /**
31715
+ * Local quality-gate mode (#3356). Controls the pre-ship typecheck/lint/tests/build gate:
31716
+ * - 'off' (default): the gate is never run. Safe for repos lacking standard scripts.
31717
+ * - 'advisory': the gate runs and its feedback is recorded, but a red gate does
31718
+ * NOT fail the pipeline.
31719
+ * - 'blocking': a red gate fails the phase, the same way a blocking security
31720
+ * scan does.
31721
+ */
31722
+ type QualityGateMode = 'off' | 'advisory' | 'blocking';
31703
31723
  /** Options for pipeline execution. */
31704
31724
  interface DevPipelineOptions {
31705
31725
  /** Session ID for checkpoint/resume. Omit for no persistence. */
@@ -31712,6 +31732,13 @@ interface DevPipelineOptions {
31712
31732
  * - 'harness': stops after decompose, returns tasks for external implementation
31713
31733
  */
31714
31734
  readonly mode?: PipelineMode | undefined;
31735
+ /**
31736
+ * Local pre-ship quality-gate mode (#3356). Default 'off' so the pipeline
31737
+ * never wedges repos that lack standard build/test scripts. See
31738
+ * {@link QualityGateMode}. Requires `stages.qualityGate` to be supplied;
31739
+ * if the stage is absent the gate is skipped regardless of mode.
31740
+ */
31741
+ readonly qualityGate?: QualityGateMode | undefined;
31715
31742
  /** Optional BeliefMemory for hindsight updates after plan outcomes (#1720). */
31716
31743
  readonly beliefMemory?: IHindsightBeliefMemory | undefined;
31717
31744
  }
package/dist/index.js CHANGED
@@ -509,7 +509,7 @@ import {
509
509
  validateWorkflow,
510
510
  validateWorkflowDependencies,
511
511
  withLogging
512
- } from "./chunk-O6EXYWHP.js";
512
+ } from "./chunk-VXNN3JKU.js";
513
513
  import "./chunk-3ACDP4E6.js";
514
514
  import {
515
515
  getTokenEnvVars,
@@ -529,7 +529,7 @@ import {
529
529
  } from "./chunk-V2C2MC6H.js";
530
530
  import {
531
531
  executeExpert
532
- } from "./chunk-6IHEDRKI.js";
532
+ } from "./chunk-H4LBBFCO.js";
533
533
  import {
534
534
  AgentFindingSchema,
535
535
  AgentPerformanceSchema,
@@ -601,7 +601,7 @@ import {
601
601
  registerConsensusVoteTool,
602
602
  withModelNotFoundFallback,
603
603
  wrapResilientWithFallback
604
- } from "./chunk-AN3IGMJT.js";
604
+ } from "./chunk-TYELRYRO.js";
605
605
  import {
606
606
  AdapterModelError,
607
607
  BaseAdapter,
@@ -744,7 +744,7 @@ import {
744
744
  getKnownNexusVarNames,
745
745
  startStdioServer,
746
746
  validateNexusEnv
747
- } from "./chunk-VPH2M5H7.js";
747
+ } from "./chunk-GEXFJOLK.js";
748
748
  import {
749
749
  AvailabilityCache,
750
750
  filterAvailableModels,
@@ -792,7 +792,7 @@ import {
792
792
  isCliAvailable,
793
793
  isRetryableError,
794
794
  sleep
795
- } from "./chunk-EM7NUGMG.js";
795
+ } from "./chunk-P453545L.js";
796
796
  import "./chunk-A7XUXJWL.js";
797
797
  import "./chunk-AH67WRET.js";
798
798
  import {
@@ -6134,7 +6134,7 @@ function buildVotingInput(plan, config) {
6134
6134
  }
6135
6135
  async function executeSingleVote(plan, config, log) {
6136
6136
  try {
6137
- const { executeVoting } = await import("./consensus-vote-5D7FNWYM.js");
6137
+ const { executeVoting } = await import("./consensus-vote-PGOS5AA6.js");
6138
6138
  const input = buildVotingInput(plan, config);
6139
6139
  const result = await executeVoting(input, log);
6140
6140
  return parseVotingResult(result);
@@ -338,25 +338,48 @@ async function refreshCommand(options) {
338
338
  exitCode: 0
339
339
  };
340
340
  }
341
+ var overCapError = (bytes) => ({
342
+ ok: false,
343
+ error: bytes === null ? `payload exceeds cap ${String(MAX_REFRESH_BYTES)} bytes (stream aborted)` : `payload ${String(bytes)} bytes exceeds cap ${String(MAX_REFRESH_BYTES)}`
344
+ });
341
345
  async function fetchWithCap(url, fetchImpl) {
342
346
  try {
343
347
  const response = await fetchImpl(url, { signal: AbortSignal.timeout(3e4) });
344
348
  if (!response.ok) {
345
349
  return { ok: false, error: `HTTP ${String(response.status)}` };
346
350
  }
347
- const body = await response.text();
348
- if (body.length > MAX_REFRESH_BYTES) {
349
- return {
350
- ok: false,
351
- error: `payload ${String(body.length)} bytes exceeds cap ${String(MAX_REFRESH_BYTES)}`
352
- };
351
+ const declared = Number(response.headers.get("content-length"));
352
+ if (Number.isFinite(declared) && declared > MAX_REFRESH_BYTES) {
353
+ return overCapError(declared);
354
+ }
355
+ if (response.body === null) {
356
+ const body = await response.text();
357
+ return body.length > MAX_REFRESH_BYTES ? overCapError(body.length) : { ok: true, body };
353
358
  }
354
- return { ok: true, body };
359
+ return await readStreamWithCap(response.body);
355
360
  } catch (err) {
356
361
  const message = err instanceof Error ? err.message : String(err);
357
362
  return { ok: false, error: message };
358
363
  }
359
364
  }
365
+ async function readStreamWithCap(stream) {
366
+ const reader = stream.getReader();
367
+ const decoder = new TextDecoder();
368
+ let total = 0;
369
+ let body = "";
370
+ for (; ; ) {
371
+ const { done, value } = await reader.read();
372
+ if (done) break;
373
+ total += value.byteLength;
374
+ if (total > MAX_REFRESH_BYTES) {
375
+ await reader.cancel();
376
+ return overCapError(null);
377
+ }
378
+ body += decoder.decode(value, { stream: true });
379
+ }
380
+ body += decoder.decode();
381
+ return { ok: true, body };
382
+ }
360
383
  function formatRegistryUsage() {
361
384
  return [
362
385
  "Usage:",
@@ -379,4 +402,4 @@ export {
379
402
  isValidRegistrySubcommand,
380
403
  registryCommand
381
404
  };
382
- //# sourceMappingURL=registry-command-AX7Z4K4W.js.map
405
+ //# sourceMappingURL=registry-command-5L7I44JA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/registry-command.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 the ModelRegistry: effective per-source entry counts,\n * the bundled generated registry path/status, the user overlay (reported for\n * inspection), and the unknown-id fallback contextWindow. Surfaces whatever\n * overlay parse rejections occurred at load. Read-only. (#3293 migrated this\n * off the deleted CapabilityDiscovery four-tier chain.)\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 { getDefaultRegistry, type EntrySource } from '../config/model-registry.js';\nimport { loadGeneratedRegistryEntries } from '../config/models-generated-loader.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\n/**\n * ContextWindow returned for an id no registry source resolves. This is the\n * old `FAIL_CLOSED_DEFAULT.contextWindow` value (#2177), preserved here after\n * the CapabilityDiscovery four-tier chain was deleted in #3293.\n */\nconst UNKNOWN_MODEL_CONTEXT_WINDOW = 8192;\n\n/** Every registry source, in report order. */\nconst ENTRY_SOURCES: readonly EntrySource[] = [\n 'in-tree',\n 'models-dev',\n 'manifest',\n 'derived',\n 'generated',\n];\n\ninterface DoctorReport {\n /** Effective per-source counts over `getDefaultRegistry().allEntries()`. */\n readonly sourceCounts: Record<EntrySource, number>;\n readonly totalEntries: number;\n readonly bundled: {\n readonly path: string;\n readonly status: 'loaded' | 'missing' | 'malformed';\n readonly entryCount: number;\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 unknownIdFallback: {\n readonly contextWindow: number;\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 // Effective per-source counts over the fully-merged registry: dedup/override\n // across tiers has already happened, so `allEntries()` reflects what actually\n // wins, grouped by the surviving entry's `source`.\n const entries = getDefaultRegistry().allEntries();\n const sourceCounts: Record<EntrySource, number> = {\n 'in-tree': 0,\n 'models-dev': 0,\n manifest: 0,\n derived: 0,\n generated: 0,\n };\n for (const entry of entries) {\n sourceCounts[entry.source] += 1;\n }\n\n // The bundled generated catalog (long-tail breadth tier) — reported from the\n // same loader the registry ingests, so the path/status here matches reality.\n const generated = loadGeneratedRegistryEntries();\n\n // User overlay is reported for inspection only; the registry consumes the\n // operator manifest, not this YAML overlay (kept by manifest-overlay.ts).\n const overlay = loadCapabilityOverlay(options.overlayPath ?? process.env);\n\n return {\n sourceCounts,\n totalEntries: entries.length,\n bundled: {\n path: generated.path,\n status: generated.status,\n entryCount: generated.entries.length,\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 unknownIdFallback: {\n contextWindow: UNKNOWN_MODEL_CONTEXT_WINDOW,\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(`Registry entries by source (total ${String(r.totalEntries)}):`);\n for (const source of ENTRY_SOURCES) {\n lines.push(` ${source.padEnd(11)}: ${String(r.sourceCounts[source])}`);\n }\n lines.push('');\n lines.push('Bundled generated registry (long-tail breadth tier):');\n lines.push(` path : ${r.bundled.path}`);\n lines.push(` status : ${r.bundled.status}`);\n lines.push(` entryCount : ${String(r.bundled.entryCount)}`);\n lines.push('');\n // User overlay reported for inspection; not consumed by the merged registry.\n lines.push('T3 user overlay (reported for inspection):');\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('Unknown-id fallback (id resolves in no source):');\n lines.push(` contextWindow : ${String(r.unknownIdFallback.contextWindow)}`);\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\nconst overCapError = (bytes: number | null): FetchResult => ({\n ok: false,\n error:\n bytes === null\n ? `payload exceeds cap ${String(MAX_REFRESH_BYTES)} bytes (stream aborted)`\n : `payload ${String(bytes)} bytes exceeds cap ${String(MAX_REFRESH_BYTES)}`,\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\n // Reject on the declared size before reading a single byte (#3354). A\n // compromised/typo'd mirror could otherwise stream gigabytes; the old\n // `response.text()` buffered the whole body before checking the cap and\n // could exhaust memory first.\n const declared = Number(response.headers.get('content-length'));\n if (Number.isFinite(declared) && declared > MAX_REFRESH_BYTES) {\n return overCapError(declared);\n }\n\n // No declared length we can trust: stream with a running cap and abort\n // the moment the accumulated bytes exceed it, so an undeclared or lying\n // Content-Length can't OOM the process.\n if (response.body === null) {\n const body = await response.text();\n return body.length > MAX_REFRESH_BYTES ? overCapError(body.length) : { ok: true, body };\n }\n return await readStreamWithCap(response.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 * Read a response body stream, aborting the moment the accumulated bytes\n * exceed {@link MAX_REFRESH_BYTES} (#3354). Keeps a hostile mirror with an\n * undeclared/lying Content-Length from buffering unbounded data into memory.\n */\nasync function readStreamWithCap(stream: ReadableStream<Uint8Array>): Promise<FetchResult> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let total = 0;\n let body = '';\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > MAX_REFRESH_BYTES) {\n await reader.cancel();\n return overCapError(null);\n }\n body += decoder.decode(value, { stream: true });\n }\n body += decoder.decode();\n return { ok: true, body };\n}\n\n// ---------------------------------------------------------------------------\n// Usage\n// ---------------------------------------------------------------------------\n\nexport function formatRegistryUsage(): string {\n return [\n 'Usage:',\n ' nexus-agents registry doctor [--json]',\n ' Inspect the merged ModelRegistry: per-source entry counts, the',\n ' bundled generated registry, the user overlay, and the unknown-id',\n ' fallback contextWindow.',\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 * User YAML overlay loader for user model overrides (#2178).\n *\n * NOTE (#3293): the legacy CapabilityDiscovery resolver that consumed this\n * overlay was removed. This loader is retained — `registry doctor` reports\n * the overlay file for inspection, and `manifest-overlay.ts` reuses its\n * parsing helpers — but the overlay is NOT yet wired into the live\n * ModelRegistry. Wiring it in (so `models.yaml` actually affects resolution)\n * is tracked in #3351.\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"]}
@@ -8,15 +8,15 @@ import {
8
8
  runWizard,
9
9
  setupCommand,
10
10
  setupCommandAsync
11
- } from "./chunk-WHFCVKAV.js";
11
+ } from "./chunk-NZC5NLUD.js";
12
12
  import "./chunk-HFNHJZOK.js";
13
- import "./chunk-VPH2M5H7.js";
13
+ import "./chunk-GEXFJOLK.js";
14
14
  import "./chunk-HBZUXO4Q.js";
15
15
  import "./chunk-CJODZY4U.js";
16
16
  import "./chunk-XO25FS24.js";
17
17
  import "./chunk-NUBSJGQZ.js";
18
18
  import "./chunk-6T3EPABN.js";
19
- import "./chunk-EM7NUGMG.js";
19
+ import "./chunk-P453545L.js";
20
20
  import "./chunk-A7XUXJWL.js";
21
21
  import "./chunk-AH67WRET.js";
22
22
  import "./chunk-ZM4O442V.js";
@@ -34,4 +34,4 @@ export {
34
34
  setupCommand,
35
35
  setupCommandAsync
36
36
  };
37
- //# sourceMappingURL=setup-command-PHTP43V7.js.map
37
+ //# sourceMappingURL=setup-command-COISAIOH.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexus-agents",
3
- "version": "2.99.0",
3
+ "version": "2.100.1",
4
4
  "description": "Governance substrate for AI coding agents — adversarial PR review, drift-detected rules, immutable audit, and closed-loop outcome routing for Claude, Codex, Gemini, and OpenCode",
5
5
  "mcpName": "io.github.nexus-substrate/nexus-agents",
6
6
  "license": "MIT",
@@ -59,16 +59,16 @@
59
59
  "node": ">=22.0.0"
60
60
  },
61
61
  "optionalDependencies": {
62
- "@atproto/api": "^0.20.5"
62
+ "@atproto/api": "^0.20.8"
63
63
  },
64
64
  "dependencies": {
65
- "@anthropic-ai/sdk": "^0.98.0",
65
+ "@anthropic-ai/sdk": "^0.100.1",
66
66
  "@google/genai": "^1.52.0",
67
67
  "@modelcontextprotocol/sdk": "^1.29.0",
68
68
  "better-sqlite3": "^12.10.0",
69
69
  "jsonc-parser": "^3.3.1",
70
70
  "ollama": "^0.6.3",
71
- "openai": "^6.39.0",
71
+ "openai": "^6.41.0",
72
72
  "semver": "^7.8.1",
73
73
  "tiktoken": "^1.0.22",
74
74
  "ts-morph": "^27.0.2",
@@ -77,17 +77,17 @@
77
77
  "zod": "^4.4.3"
78
78
  },
79
79
  "devDependencies": {
80
- "@ai-sdk/anthropic": "^3.0.79",
81
- "@ai-sdk/google": "^3.0.79",
82
- "@ai-sdk/openai": "^3.0.65",
80
+ "@ai-sdk/anthropic": "^3.0.81",
81
+ "@ai-sdk/google": "^3.0.80",
82
+ "@ai-sdk/openai": "^3.0.67",
83
83
  "@types/better-sqlite3": "^7.6.13",
84
84
  "@types/semver": "^7.7.1",
85
- "@vitest/coverage-v8": "4.1.7",
86
- "ai": "^6.0.191",
85
+ "@vitest/coverage-v8": "4.1.8",
86
+ "ai": "^6.0.195",
87
87
  "fast-check": "^4.8.0",
88
88
  "tsup": "^8.5.1",
89
89
  "typedoc": "0.28.19",
90
- "vitest": "4.1.7",
90
+ "vitest": "4.1.8",
91
91
  "nexus-memory": "0.1.2"
92
92
  },
93
93
  "peerDependencies": {