nexus-agents 2.79.4 → 2.80.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 (119) hide show
  1. package/dist/{child-mcp-config-DFRYTRBK.js → child-mcp-config-Q6UMCPGZ.js} +3 -3
  2. package/dist/{chunk-UWDVEMYZ.js → chunk-23XU4LE2.js} +4 -4
  3. package/dist/chunk-2JQXC3CK.js +317 -0
  4. package/dist/chunk-2JQXC3CK.js.map +1 -0
  5. package/dist/{chunk-DOI7RE3X.js → chunk-33LDLZCC.js} +2 -2
  6. package/dist/{chunk-UNRTM43V.js → chunk-54UT2JUQ.js} +2 -2
  7. package/dist/{chunk-OGV7J5WG.js → chunk-5WN3WGXG.js} +3 -3
  8. package/dist/{chunk-NJPFN75N.js → chunk-7UM5XRGG.js} +2 -2
  9. package/dist/{chunk-JMRCMMZ5.js → chunk-7ZKZ7K7J.js} +2 -2
  10. package/dist/{chunk-45NUO4FE.js → chunk-ALDKPBOZ.js} +2 -2
  11. package/dist/{chunk-DW3UTO43.js → chunk-D3MQ4U2R.js} +51 -21
  12. package/dist/chunk-D3MQ4U2R.js.map +1 -0
  13. package/dist/{chunk-NVSJXN4S.js → chunk-D4NEYNBO.js} +8 -5
  14. package/dist/chunk-D4NEYNBO.js.map +1 -0
  15. package/dist/{chunk-42MM7GKW.js → chunk-D5C5N5Q4.js} +2 -2
  16. package/dist/{chunk-BIH2CBC5.js → chunk-EPZMFIAX.js} +105 -10
  17. package/dist/chunk-EPZMFIAX.js.map +1 -0
  18. package/dist/{chunk-ACP4YARI.js → chunk-GODRGVF4.js} +3 -3
  19. package/dist/{chunk-IPDUZJPH.js → chunk-HR7C4DSA.js} +4 -4
  20. package/dist/{chunk-PAKVXGS2.js → chunk-I5KYDT23.js} +2 -2
  21. package/dist/{chunk-PDCLBWH5.js → chunk-L7433REX.js} +4 -4
  22. package/dist/{chunk-3ENBGGYA.js → chunk-LDD272PW.js} +959 -885
  23. package/dist/chunk-LDD272PW.js.map +1 -0
  24. package/dist/{chunk-OFRDE7MK.js → chunk-MUIA32LU.js} +2 -2
  25. package/dist/{chunk-TN5ZKSGC.js → chunk-MVIYQMQM.js} +2 -2
  26. package/dist/{chunk-NXNNT5XW.js → chunk-NALIFUBD.js} +4 -4
  27. package/dist/{chunk-LFTK5ZQG.js → chunk-NCBWA6RU.js} +2 -2
  28. package/dist/{chunk-BXI6DKBU.js → chunk-O2ECPTFH.js} +3 -3
  29. package/dist/{chunk-UNFS6YBY.js → chunk-Q4DXTNGR.js} +2 -2
  30. package/dist/{chunk-BSQ4KTY4.js → chunk-SX3P2PD2.js} +2 -2
  31. package/dist/{chunk-UQOSVOEU.js → chunk-T4E6UFFC.js} +16 -14
  32. package/dist/chunk-T4E6UFFC.js.map +1 -0
  33. package/dist/{chunk-UOR2JWFH.js → chunk-TFTP7EUQ.js} +82 -57
  34. package/dist/chunk-TFTP7EUQ.js.map +1 -0
  35. package/dist/{chunk-PHBRELUK.js → chunk-UEKTTIDA.js} +7 -7
  36. package/dist/{chunk-SU3Y6LU2.js → chunk-WZ2T4T7N.js} +32 -6
  37. package/dist/chunk-WZ2T4T7N.js.map +1 -0
  38. package/dist/{cli-circuit-breaker-T75HOLZK.js → cli-circuit-breaker-EUERR2HK.js} +5 -5
  39. package/dist/cli.d.ts +1 -1
  40. package/dist/cli.js +618 -567
  41. package/dist/cli.js.map +1 -1
  42. package/dist/{composite-router-OPSK5FCQ.js → composite-router-ZP72LQFH.js} +3 -3
  43. package/dist/{consensus-vote-CYUPIJXR.js → consensus-vote-TU3TQ4VH.js} +12 -12
  44. package/dist/{context-retriever-6AWHCHRP.js → context-retriever-OTLV46DF.js} +6 -6
  45. package/dist/{doctor-deep-XBPRQ6ZP.js → doctor-deep-ZMBSG2DF.js} +4 -4
  46. package/dist/expert-bridge-IK4TY7HA.js +11 -0
  47. package/dist/{factory-Y3TMP4OQ.js → factory-45NHZFLK.js} +5 -5
  48. package/dist/factory-QDHYIYVE.js +14 -0
  49. package/dist/index.d.ts +40 -5
  50. package/dist/index.js +25 -25
  51. package/dist/{init-opencode-RV6IQEMS.js → init-opencode-WFL4OXMB.js} +6 -6
  52. package/dist/issue-triage-UHFCGTEJ.js +15 -0
  53. package/dist/{learning-persistence-Q3HTOGTU.js → learning-persistence-TGOBRUUU.js} +2 -2
  54. package/dist/{registry-command-6KJWW3W7.js → registry-command-YMZPSW7S.js} +3 -3
  55. package/dist/{repo-security-plan-HNLMF7J7.js → repo-security-plan-TGDXTSHS.js} +4 -4
  56. package/dist/{research-helpers-synthesize-77TLYSW4.js → research-helpers-synthesize-5BAN353Y.js} +4 -4
  57. package/dist/{routing-memory-6DV6ZPAH.js → routing-memory-RG3U2MC2.js} +3 -3
  58. package/dist/{session-memory-XZ3NJIR4.js → session-memory-C5GC2JAX.js} +4 -4
  59. package/dist/{setup-command-QOXG36UV.js → setup-command-OXJ32UAI.js} +13 -11
  60. package/dist/setup-config-KNMVMGDD.js +10 -0
  61. package/dist/{setup-custom-api-PJ6TGHJH.js → setup-custom-api-4EYRKCHB.js} +5 -5
  62. package/dist/{tool-memory-K2QPTPKV.js → tool-memory-LUXUOE6Q.js} +5 -5
  63. package/dist/{weather-report-ZB4AKOIA.js → weather-report-3KSDTC7T.js} +3 -3
  64. package/package.json +1 -1
  65. package/dist/chunk-3ENBGGYA.js.map +0 -1
  66. package/dist/chunk-7BMOZJYS.js +0 -83
  67. package/dist/chunk-7BMOZJYS.js.map +0 -1
  68. package/dist/chunk-BIH2CBC5.js.map +0 -1
  69. package/dist/chunk-DW3UTO43.js.map +0 -1
  70. package/dist/chunk-NVSJXN4S.js.map +0 -1
  71. package/dist/chunk-SU3Y6LU2.js.map +0 -1
  72. package/dist/chunk-UOR2JWFH.js.map +0 -1
  73. package/dist/chunk-UQOSVOEU.js.map +0 -1
  74. package/dist/expert-bridge-5YOPK5IT.js +0 -11
  75. package/dist/factory-DN7SJZ5Z.js +0 -14
  76. package/dist/issue-triage-UTWKXLKC.js +0 -15
  77. package/dist/setup-config-B4V4QHDP.js +0 -10
  78. /package/dist/{child-mcp-config-DFRYTRBK.js.map → child-mcp-config-Q6UMCPGZ.js.map} +0 -0
  79. /package/dist/{chunk-UWDVEMYZ.js.map → chunk-23XU4LE2.js.map} +0 -0
  80. /package/dist/{chunk-DOI7RE3X.js.map → chunk-33LDLZCC.js.map} +0 -0
  81. /package/dist/{chunk-UNRTM43V.js.map → chunk-54UT2JUQ.js.map} +0 -0
  82. /package/dist/{chunk-OGV7J5WG.js.map → chunk-5WN3WGXG.js.map} +0 -0
  83. /package/dist/{chunk-NJPFN75N.js.map → chunk-7UM5XRGG.js.map} +0 -0
  84. /package/dist/{chunk-JMRCMMZ5.js.map → chunk-7ZKZ7K7J.js.map} +0 -0
  85. /package/dist/{chunk-45NUO4FE.js.map → chunk-ALDKPBOZ.js.map} +0 -0
  86. /package/dist/{chunk-42MM7GKW.js.map → chunk-D5C5N5Q4.js.map} +0 -0
  87. /package/dist/{chunk-ACP4YARI.js.map → chunk-GODRGVF4.js.map} +0 -0
  88. /package/dist/{chunk-IPDUZJPH.js.map → chunk-HR7C4DSA.js.map} +0 -0
  89. /package/dist/{chunk-PAKVXGS2.js.map → chunk-I5KYDT23.js.map} +0 -0
  90. /package/dist/{chunk-PDCLBWH5.js.map → chunk-L7433REX.js.map} +0 -0
  91. /package/dist/{chunk-OFRDE7MK.js.map → chunk-MUIA32LU.js.map} +0 -0
  92. /package/dist/{chunk-TN5ZKSGC.js.map → chunk-MVIYQMQM.js.map} +0 -0
  93. /package/dist/{chunk-NXNNT5XW.js.map → chunk-NALIFUBD.js.map} +0 -0
  94. /package/dist/{chunk-LFTK5ZQG.js.map → chunk-NCBWA6RU.js.map} +0 -0
  95. /package/dist/{chunk-BXI6DKBU.js.map → chunk-O2ECPTFH.js.map} +0 -0
  96. /package/dist/{chunk-UNFS6YBY.js.map → chunk-Q4DXTNGR.js.map} +0 -0
  97. /package/dist/{chunk-BSQ4KTY4.js.map → chunk-SX3P2PD2.js.map} +0 -0
  98. /package/dist/{chunk-PHBRELUK.js.map → chunk-UEKTTIDA.js.map} +0 -0
  99. /package/dist/{cli-circuit-breaker-T75HOLZK.js.map → cli-circuit-breaker-EUERR2HK.js.map} +0 -0
  100. /package/dist/{composite-router-OPSK5FCQ.js.map → composite-router-ZP72LQFH.js.map} +0 -0
  101. /package/dist/{consensus-vote-CYUPIJXR.js.map → consensus-vote-TU3TQ4VH.js.map} +0 -0
  102. /package/dist/{context-retriever-6AWHCHRP.js.map → context-retriever-OTLV46DF.js.map} +0 -0
  103. /package/dist/{doctor-deep-XBPRQ6ZP.js.map → doctor-deep-ZMBSG2DF.js.map} +0 -0
  104. /package/dist/{expert-bridge-5YOPK5IT.js.map → expert-bridge-IK4TY7HA.js.map} +0 -0
  105. /package/dist/{factory-DN7SJZ5Z.js.map → factory-45NHZFLK.js.map} +0 -0
  106. /package/dist/{factory-Y3TMP4OQ.js.map → factory-QDHYIYVE.js.map} +0 -0
  107. /package/dist/{init-opencode-RV6IQEMS.js.map → init-opencode-WFL4OXMB.js.map} +0 -0
  108. /package/dist/{issue-triage-UTWKXLKC.js.map → issue-triage-UHFCGTEJ.js.map} +0 -0
  109. /package/dist/{learning-persistence-Q3HTOGTU.js.map → learning-persistence-TGOBRUUU.js.map} +0 -0
  110. /package/dist/{registry-command-6KJWW3W7.js.map → registry-command-YMZPSW7S.js.map} +0 -0
  111. /package/dist/{repo-security-plan-HNLMF7J7.js.map → repo-security-plan-TGDXTSHS.js.map} +0 -0
  112. /package/dist/{research-helpers-synthesize-77TLYSW4.js.map → research-helpers-synthesize-5BAN353Y.js.map} +0 -0
  113. /package/dist/{routing-memory-6DV6ZPAH.js.map → routing-memory-RG3U2MC2.js.map} +0 -0
  114. /package/dist/{session-memory-XZ3NJIR4.js.map → session-memory-C5GC2JAX.js.map} +0 -0
  115. /package/dist/{setup-command-QOXG36UV.js.map → setup-command-OXJ32UAI.js.map} +0 -0
  116. /package/dist/{setup-config-B4V4QHDP.js.map → setup-config-KNMVMGDD.js.map} +0 -0
  117. /package/dist/{setup-custom-api-PJ6TGHJH.js.map → setup-custom-api-4EYRKCHB.js.map} +0 -0
  118. /package/dist/{tool-memory-K2QPTPKV.js.map → tool-memory-LUXUOE6Q.js.map} +0 -0
  119. /package/dist/{weather-report-ZB4AKOIA.js.map → weather-report-3KSDTC7T.js.map} +0 -0
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  getErrorMessage
3
- } from "./chunk-UQOSVOEU.js";
3
+ } from "./chunk-T4E6UFFC.js";
4
4
 
5
5
  // src/cli/setup-config.ts
6
- import { copyFileSync, existsSync, writeFileSync } from "fs";
7
- import { resolve } from "path";
6
+ import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
7
+ import { dirname, resolve } from "path";
8
8
  var DEFAULT_CONFIG_FILE = "nexus-agents.yaml";
9
+ var DEFAULT_CONFIG_REL_PATH = `.nexus-agents/${DEFAULT_CONFIG_FILE}`;
9
10
  var SETUP_CONFIG_TEMPLATE = `# Nexus Agents Configuration
10
11
  # Generated by: nexus-agents setup
11
12
  # Full template: nexus-agents config init
@@ -21,7 +22,8 @@ logging:
21
22
  format: json
22
23
  `;
23
24
  function runConfigInitSync(projectRoot, force, dryRun) {
24
- const outputPath = resolve(projectRoot, DEFAULT_CONFIG_FILE);
25
+ const legacyPath = resolve(projectRoot, DEFAULT_CONFIG_FILE);
26
+ const outputPath = existsSync(legacyPath) ? legacyPath : resolve(projectRoot, DEFAULT_CONFIG_REL_PATH);
25
27
  if (existsSync(outputPath) && !force) {
26
28
  return {
27
29
  success: true,
@@ -41,6 +43,7 @@ function runConfigInitSync(projectRoot, force, dryRun) {
41
43
  const backup = ensureBackup(outputPath);
42
44
  if ("error" in backup) return backup.error;
43
45
  try {
46
+ mkdirSync(dirname(outputPath), { recursive: true });
44
47
  writeFileSync(outputPath, SETUP_CONFIG_TEMPLATE, "utf-8");
45
48
  const message = backup.path !== void 0 ? `Created: ${outputPath} (backup saved at ${backup.path})` : `Created: ${outputPath}`;
46
49
  return { success: true, path: outputPath, created: true, message };
@@ -74,4 +77,4 @@ function ensureBackup(outputPath) {
74
77
  export {
75
78
  runConfigInitSync
76
79
  };
77
- //# sourceMappingURL=chunk-NVSJXN4S.js.map
80
+ //# sourceMappingURL=chunk-D4NEYNBO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/setup-config.ts"],"sourcesContent":["/**\n * Synchronous config file generation for setup command.\n *\n * Reuses the CONFIG_TEMPLATE from config-init.ts pattern but provides\n * a synchronous API suitable for the setup command flow.\n *\n * @module cli/setup-config\n * (Source: Issue #1252 - Setup auto-generates nexus-agents.yaml)\n */\n\nimport { copyFileSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { getErrorMessage } from '../core/index.js';\n\n/** Default configuration file name. */\nconst DEFAULT_CONFIG_FILE = 'nexus-agents.yaml';\n\n/**\n * Path setup writes new configs to (epic #2872). The config loader checks\n * `.nexus-agents/nexus-agents.yaml` ahead of the legacy root-level location,\n * so writing here is forward-compatible. Existing root-level configs keep\n * working without action (loader still falls back to them).\n */\nconst DEFAULT_CONFIG_REL_PATH = `.nexus-agents/${DEFAULT_CONFIG_FILE}`;\n\n/** Result of the config generation step. */\nexport interface ConfigStepResult {\n readonly success: boolean;\n readonly path: string;\n readonly created: boolean;\n readonly message: string;\n}\n\n/**\n * Minimal YAML config template for setup command.\n * Intentionally brief — just enough to get started.\n * Users can run `nexus-agents config init` for the full template.\n */\nconst SETUP_CONFIG_TEMPLATE = `# Nexus Agents Configuration\n# Generated by: nexus-agents setup\n# Full template: nexus-agents config init\n\nmodels:\n default: claude-sonnet-4\n\nexperts:\n builtin: true\n\nlogging:\n level: info\n format: json\n`;\n\n/**\n * Generates a nexus-agents.yaml config file synchronously.\n *\n * @param projectRoot - Directory to create config in.\n * @param force - Overwrite existing config.\n * @param dryRun - Report what would happen without writing.\n */\nexport function runConfigInitSync(\n projectRoot: string,\n force: boolean,\n dryRun: boolean\n): ConfigStepResult {\n // Prefer the dotdir location for new configs. Per #2877: if a legacy\n // root-level nexus-agents.yaml already exists, keep editing it in place\n // rather than silently moving the user's config — the migrate command\n // (#2879) is the explicit way to relocate. New installs land in the dotdir.\n const legacyPath = resolve(projectRoot, DEFAULT_CONFIG_FILE);\n const outputPath = existsSync(legacyPath)\n ? legacyPath\n : resolve(projectRoot, DEFAULT_CONFIG_REL_PATH);\n\n if (existsSync(outputPath) && !force) {\n return {\n success: true,\n path: outputPath,\n created: false,\n message: 'Config already exists (use --force to overwrite)',\n };\n }\n\n if (dryRun) {\n return {\n success: true,\n path: outputPath,\n created: true,\n message: `Would create: ${outputPath}`,\n };\n }\n\n const backup = ensureBackup(outputPath);\n if ('error' in backup) return backup.error;\n\n try {\n // Ensure parent dir exists — needed for the new dotdir location since\n // .nexus-agents/ may not yet exist on a fresh repo.\n mkdirSync(dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, SETUP_CONFIG_TEMPLATE, 'utf-8');\n const message =\n backup.path !== undefined\n ? `Created: ${outputPath} (backup saved at ${backup.path})`\n : `Created: ${outputPath}`;\n return { success: true, path: outputPath, created: true, message };\n } catch (error: unknown) {\n return {\n success: false,\n path: outputPath,\n created: false,\n message: `Failed: ${getErrorMessage(error)}`,\n };\n }\n}\n\n/**\n * Saves a timestamped backup of an existing config file before overwrite (#2183).\n *\n * Returns `{ path }` with the backup path (or undefined if no existing file)\n * on success, or `{ error }` with a populated `ConfigStepResult` on failure.\n * Failure to write the backup aborts the overwrite — better to keep the\n * user's customizations intact than to lose them silently.\n */\nfunction ensureBackup(\n outputPath: string\n): { path: string | undefined } | { error: ConfigStepResult } {\n if (!existsSync(outputPath)) return { path: undefined };\n const backupPath = `${outputPath}.bak.${String(Date.now())}`;\n try {\n copyFileSync(outputPath, backupPath);\n return { path: backupPath };\n } catch (err: unknown) {\n return {\n error: {\n success: false,\n path: outputPath,\n created: false,\n message: `Failed to back up existing config: ${getErrorMessage(err)}`,\n },\n };\n }\n}\n"],"mappings":";;;;;AAUA,SAAS,cAAc,YAAY,WAAW,qBAAqB;AACnE,SAAS,SAAS,eAAe;AAIjC,IAAM,sBAAsB;AAQ5B,IAAM,0BAA0B,iBAAiB,mBAAmB;AAepE,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBvB,SAAS,kBACd,aACA,OACA,QACkB;AAKlB,QAAM,aAAa,QAAQ,aAAa,mBAAmB;AAC3D,QAAM,aAAa,WAAW,UAAU,IACpC,aACA,QAAQ,aAAa,uBAAuB;AAEhD,MAAI,WAAW,UAAU,KAAK,CAAC,OAAO;AACpC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,QAAQ;AACV,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,iBAAiB,UAAU;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,SAAS,aAAa,UAAU;AACtC,MAAI,WAAW,OAAQ,QAAO,OAAO;AAErC,MAAI;AAGF,cAAU,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,kBAAc,YAAY,uBAAuB,OAAO;AACxD,UAAM,UACJ,OAAO,SAAS,SACZ,YAAY,UAAU,qBAAqB,OAAO,IAAI,MACtD,YAAY,UAAU;AAC5B,WAAO,EAAE,SAAS,MAAM,MAAM,YAAY,SAAS,MAAM,QAAQ;AAAA,EACnE,SAAS,OAAgB;AACvB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,WAAW,gBAAgB,KAAK,CAAC;AAAA,IAC5C;AAAA,EACF;AACF;AAUA,SAAS,aACP,YAC4D;AAC5D,MAAI,CAAC,WAAW,UAAU,EAAG,QAAO,EAAE,MAAM,OAAU;AACtD,QAAM,aAAa,GAAG,UAAU,QAAQ,OAAO,KAAK,IAAI,CAAC,CAAC;AAC1D,MAAI;AACF,iBAAa,YAAY,UAAU;AACnC,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B,SAAS,KAAc;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS,sCAAsC,gBAAgB,GAAG,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createLogger
3
- } from "./chunk-UQOSVOEU.js";
3
+ } from "./chunk-T4E6UFFC.js";
4
4
 
5
5
  // src/config/available-models-cache.ts
6
6
  var logger = createLogger({ component: "available-models-cache" });
@@ -150,4 +150,4 @@ export {
150
150
  getDefaultAvailableModelsCache,
151
151
  setDefaultAvailableModelsCache
152
152
  };
153
- //# sourceMappingURL=chunk-42MM7GKW.js.map
153
+ //# sourceMappingURL=chunk-D5C5N5Q4.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CliCircuitBreaker,
3
3
  DEFAULT_CIRCUIT_BREAKER_CONFIG
4
- } from "./chunk-NJPFN75N.js";
4
+ } from "./chunk-7UM5XRGG.js";
5
5
  import {
6
6
  CLI_SUBPROCESS_TIMEOUTS,
7
7
  CLI_TIMEOUTS,
@@ -24,7 +24,7 @@ import {
24
24
  getTimeProvider,
25
25
  isRateLimitText,
26
26
  ok
27
- } from "./chunk-UQOSVOEU.js";
27
+ } from "./chunk-T4E6UFFC.js";
28
28
 
29
29
  // src/cli-adapters/subprocess-adapter.ts
30
30
  import { spawn } from "child_process";
@@ -400,13 +400,23 @@ var BaseCliAdapter = class {
400
400
  if (task.timeoutMs !== void 0) return task.timeoutMs;
401
401
  return getTimeoutForTaskAuto(this.name, task.content);
402
402
  }
403
+ /**
404
+ * Whether the shared outer retry loop ({@link executeCliRetryLoop}) is
405
+ * allowed to retry this adapter's failures. The base adapter honors the
406
+ * caller's `allowRetry`. Subprocess adapters override this to suppress
407
+ * the outer loop when their own transient-retry layer is active, so the
408
+ * two layers do not nest into multiplied spawns (#2824).
409
+ */
410
+ shouldOuterRetry(opts) {
411
+ return opts.allowRetry;
412
+ }
403
413
  /**
404
414
  * Executes task with retry logic via shared retry loop.
405
415
  */
406
416
  async executeWithRetry(task, opts) {
407
417
  const result = await executeCliRetryLoop(() => this.executeTask(task, opts), {
408
418
  maxRetries: opts.maxRetries,
409
- allowRetry: opts.allowRetry,
419
+ allowRetry: this.shouldOuterRetry(opts),
410
420
  baseDelayMs: 1e3,
411
421
  maxDelayMs: 16e3,
412
422
  cli: this.name,
@@ -576,6 +586,78 @@ var BaseCliAdapter = class {
576
586
  }
577
587
  };
578
588
 
589
+ // src/cli-adapters/subprocess-env.ts
590
+ var BASE_ENV_EXACT = [
591
+ "PATH",
592
+ "HOME",
593
+ "USER",
594
+ "LOGNAME",
595
+ "SHELL",
596
+ "LANG",
597
+ "TERM",
598
+ "TZ",
599
+ "TMPDIR",
600
+ "TEMP",
601
+ "TMP",
602
+ "HTTP_PROXY",
603
+ "HTTPS_PROXY",
604
+ "NO_PROXY",
605
+ "ALL_PROXY",
606
+ "http_proxy",
607
+ "https_proxy",
608
+ "no_proxy",
609
+ "all_proxy",
610
+ "NODE_OPTIONS",
611
+ "NODE_PATH",
612
+ "NODE_ENV",
613
+ "NODE_EXTRA_CA_CERTS",
614
+ "SSL_CERT_FILE",
615
+ "SSL_CERT_DIR"
616
+ ];
617
+ var BASE_ENV_PREFIXES = [
618
+ "LC_",
619
+ // locale: LC_ALL, LC_CTYPE, …
620
+ "NEXUS_",
621
+ // nexus-agents config + nested-run credentials (a child may be a nested nexus-agents)
622
+ "npm_config_"
623
+ // npm/node resolution config: registry, proxy, …
624
+ ];
625
+ var CLI_VENDOR_KEYS = {
626
+ claude: ["ANTHROPIC_API_KEY"],
627
+ gemini: ["GOOGLE_AI_API_KEY", "GEMINI_API_KEY", "GOOGLE_API_KEY"],
628
+ codex: ["OPENAI_API_KEY"],
629
+ opencode: [
630
+ "ANTHROPIC_API_KEY",
631
+ "OPENAI_API_KEY",
632
+ "GOOGLE_AI_API_KEY",
633
+ "GEMINI_API_KEY",
634
+ "GOOGLE_API_KEY",
635
+ "OPENROUTER_API_KEY"
636
+ ]
637
+ };
638
+ function isAllowed(key, vendorKeys) {
639
+ if (BASE_ENV_EXACT.includes(key)) return true;
640
+ if (vendorKeys.includes(key)) return true;
641
+ return BASE_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
642
+ }
643
+ function buildChildEnv(cliName) {
644
+ const source = process.env;
645
+ const childEnv = {};
646
+ if (source["NEXUS_SUBPROCESS_ENV_ALLOWLIST"] === "0") {
647
+ for (const [key, value] of Object.entries(source)) {
648
+ if (value !== void 0 && key !== "CLAUDECODE") childEnv[key] = value;
649
+ }
650
+ return childEnv;
651
+ }
652
+ const vendorKeys = CLI_VENDOR_KEYS[cliName];
653
+ for (const [key, value] of Object.entries(source)) {
654
+ if (value === void 0) continue;
655
+ if (key === "CLAUDECODE") continue;
656
+ if (isAllowed(key, vendorKeys)) childEnv[key] = value;
657
+ }
658
+ return childEnv;
659
+ }
660
+
579
661
  // src/security/output-sanitizer.ts
580
662
  var REDACTED_KEY_PLACEHOLDER = "[REDACTED_KEY]";
581
663
  var KEY_PATTERNS = [
@@ -791,6 +873,18 @@ var SubprocessCliAdapter = class extends BaseCliAdapter {
791
873
  transport = "subprocess";
792
874
  /** Transient-error retry config. Override in subclass to enable. */
793
875
  transientRetry = { enabled: true };
876
+ /**
877
+ * The inner {@link retryTransient} layer is the single retry authority
878
+ * for subprocess CLIs. When it is enabled (the default), the shared
879
+ * outer retry loop must not also retry: nesting both meant up to 6
880
+ * subprocess spawns and ~10-minute hangs on a persistent TIMEOUT, since
881
+ * the inner layer's timeout extension compounds on every outer attempt
882
+ * (#2824). The outer loop still runs once, so circuit-breaker failure
883
+ * recording is unaffected.
884
+ */
885
+ shouldOuterRetry(opts) {
886
+ return opts.allowRetry && !this.transientRetry.enabled;
887
+ }
794
888
  /**
795
889
  * Executes a task via subprocess, with optional transient-error retry.
796
890
  * When `transientRetry.enabled` is true, transient errors (timeout,
@@ -850,8 +944,7 @@ var SubprocessCliAdapter = class extends BaseCliAdapter {
850
944
  runCleanup();
851
945
  resolveOuter(result);
852
946
  };
853
- const childEnv = { ...process.env };
854
- delete childEnv["CLAUDECODE"];
947
+ const childEnv = buildChildEnv(this.name);
855
948
  const child = spawn(cmdConfig.command, cmdConfig.args, {
856
949
  stdio: ["pipe", "pipe", "pipe"],
857
950
  env: childEnv
@@ -1698,7 +1791,7 @@ var GeminiCliAdapter = class extends SubprocessCliAdapter {
1698
1791
  async executeWithRetryTracking(task, options) {
1699
1792
  return executeCliRetryLoop(() => this.executeTask(task, options), {
1700
1793
  maxRetries: options.maxRetries,
1701
- allowRetry: options.allowRetry,
1794
+ allowRetry: this.shouldOuterRetry(options),
1702
1795
  baseDelayMs: this.baseDelayMs,
1703
1796
  maxDelayMs: this.maxDelayMs,
1704
1797
  circuitBreaker: this.circuitBreaker,
@@ -2626,9 +2719,10 @@ ${task.content}` : task.content;
2626
2719
  }
2627
2720
  /**
2628
2721
  * (#2540) Lists models the local OpenCode installation can route to.
2629
- * Wraps the existing `probeAvailableModels()` (already 5-min cached)
2630
- * and reshapes the result into the CliModelInfo schema. Splits
2631
- * `provider/model` ids when present.
2722
+ * Wraps the existing `probeAvailableModels()` (cached for the process
2723
+ * lifetime see `cachedModels` at the top of this file) and reshapes
2724
+ * the result into the CliModelInfo schema. Splits `provider/model` ids
2725
+ * when present.
2632
2726
  */
2633
2727
  async listModels() {
2634
2728
  const ids = await probeAvailableModels();
@@ -3063,6 +3157,7 @@ export {
3063
3157
  categorizeError,
3064
3158
  executeCliRetryLoop,
3065
3159
  BaseCliAdapter,
3160
+ sanitizeOutput,
3066
3161
  SubprocessCliAdapter,
3067
3162
  asRecord,
3068
3163
  isRecord,
@@ -3085,4 +3180,4 @@ export {
3085
3180
  isCliAvailable,
3086
3181
  getAvailableClis
3087
3182
  };
3088
- //# sourceMappingURL=chunk-BIH2CBC5.js.map
3183
+ //# sourceMappingURL=chunk-EPZMFIAX.js.map