nexus-agents 2.160.0 → 2.161.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.
Files changed (125) hide show
  1. package/dist/{child-mcp-config-XEXFG3LA.js → child-mcp-config-CR5HFAFF.js} +2 -2
  2. package/dist/{chunk-SNKSSSAR.js → chunk-2XOUYCGO.js} +4 -4
  3. package/dist/{chunk-AMY4S4VD.js → chunk-3B2WRRTU.js} +2 -2
  4. package/dist/{chunk-I2DK3KSH.js → chunk-3CPGHAZN.js} +2 -2
  5. package/dist/{chunk-7XISTLQP.js → chunk-5VYWG6N4.js} +8 -8
  6. package/dist/{chunk-RNCBSF6I.js → chunk-6QOMNQAM.js} +2 -2
  7. package/dist/{chunk-WRISLYLK.js → chunk-7ABXSM2X.js} +2 -2
  8. package/dist/{chunk-OQUELE4L.js → chunk-AYTV4P26.js} +38 -35
  9. package/dist/{chunk-OQUELE4L.js.map → chunk-AYTV4P26.js.map} +1 -1
  10. package/dist/{chunk-B23GFISN.js → chunk-B3FRHPJW.js} +3 -3
  11. package/dist/{chunk-SN4Q7TZT.js → chunk-B4DIA6YS.js} +2 -2
  12. package/dist/{chunk-ED6B55WK.js → chunk-B6CLLXZB.js} +3 -3
  13. package/dist/{chunk-HBLVOFLL.js → chunk-CWVPSHEP.js} +2 -2
  14. package/dist/{chunk-IG2SIC2E.js → chunk-DMFDSHOQ.js} +2 -2
  15. package/dist/{chunk-HT3B6ZWV.js → chunk-DTBU4J67.js} +2 -2
  16. package/dist/{chunk-E7LG7L4O.js → chunk-E5XTAHAS.js} +91 -11
  17. package/dist/chunk-E5XTAHAS.js.map +1 -0
  18. package/dist/{chunk-MXNIOTDY.js → chunk-E7SVEDLI.js} +3 -3
  19. package/dist/{chunk-ZO54JW4V.js → chunk-FE4TTIW7.js} +3 -3
  20. package/dist/{chunk-SHFCJJTY.js → chunk-FKXR4ELM.js} +6 -6
  21. package/dist/{chunk-SHFCJJTY.js.map → chunk-FKXR4ELM.js.map} +1 -1
  22. package/dist/{chunk-I6NTUVGW.js → chunk-HUXMIDNV.js} +2 -2
  23. package/dist/chunk-HUXMIDNV.js.map +1 -0
  24. package/dist/{chunk-QVIQAIOK.js → chunk-I3RJEXY2.js} +2 -2
  25. package/dist/{chunk-JYV5MZC6.js → chunk-KFWCF32D.js} +4 -4
  26. package/dist/{chunk-QD653D5O.js → chunk-LEMQDF4W.js} +7 -7
  27. package/dist/{chunk-Q6EGZKLE.js → chunk-MMPZLMSH.js} +2 -2
  28. package/dist/{chunk-WP6UBBNJ.js → chunk-MONR3CEL.js} +4 -4
  29. package/dist/{chunk-VKUP2PG5.js → chunk-OB4N36EY.js} +14 -10
  30. package/dist/chunk-OB4N36EY.js.map +1 -0
  31. package/dist/{chunk-VWX75FKD.js → chunk-PLEB6SON.js} +5 -5
  32. package/dist/{chunk-3QIXGEY7.js → chunk-POHORI2I.js} +2 -2
  33. package/dist/{chunk-5NVU25BA.js → chunk-QWZOEVR6.js} +4 -4
  34. package/dist/{chunk-ZBEJITR6.js → chunk-RV6S6OZJ.js} +5 -5
  35. package/dist/{chunk-XLEZBTQG.js → chunk-SDJQ2H7V.js} +2 -2
  36. package/dist/{chunk-O27ZG7BL.js → chunk-THE4NODE.js} +3 -3
  37. package/dist/{chunk-ICYEG7T4.js → chunk-TVPLAB4X.js} +7 -7
  38. package/dist/{chunk-FYQSTNG6.js → chunk-VV45XQVW.js} +5 -5
  39. package/dist/{chunk-4AXOISAP.js → chunk-VWOMHATO.js} +3 -3
  40. package/dist/{chunk-RU336IEH.js → chunk-WVKEKRZZ.js} +2 -2
  41. package/dist/{cli-circuit-breaker-SAHRY3BI.js → cli-circuit-breaker-ISW6F7DI.js} +4 -4
  42. package/dist/cli.d.ts +1 -1
  43. package/dist/cli.js +41 -41
  44. package/dist/{composite-router-MFJNLR3O.js → composite-router-PB4ZVWUH.js} +2 -2
  45. package/dist/{consensus-vote-Z55357CP.js → consensus-vote-FVKOLIPS.js} +15 -15
  46. package/dist/{consensus-vote-types-DB3SmULO.d.ts → consensus-vote-types-BlbNhK1n.d.ts} +1 -1
  47. package/dist/{context-retriever-Z474PNZ4.js → context-retriever-TGIQ6FNS.js} +8 -8
  48. package/dist/{doctor-deep-IESAJDVW.js → doctor-deep-VEFTQZMR.js} +3 -3
  49. package/dist/{expert-bridge-JW4DJPH3.js → expert-bridge-SFBHTNIB.js} +4 -4
  50. package/dist/{factory-6JIXPGRH.js → factory-DEO5DAXZ.js} +8 -8
  51. package/dist/{factory-Z7GGTUK2.js → factory-NF7WS67L.js} +5 -5
  52. package/dist/{improvement-review-5DRIOL5K.js → improvement-review-AFDZO6PL.js} +5 -5
  53. package/dist/index.d.ts +9 -2
  54. package/dist/index.js +30 -30
  55. package/dist/{init-opencode-T2F5WSLT.js → init-opencode-ELTBZAIN.js} +6 -6
  56. package/dist/{issue-triage-RC5VVUAV.js → issue-triage-3WL7PW26.js} +6 -6
  57. package/dist/{pr-reviewer-helpers-G35TGA7R.js → pr-reviewer-helpers-7ES4HWFC.js} +4 -4
  58. package/dist/{registry-command-47UO65SV.js → registry-command-3AXI4JXN.js} +2 -2
  59. package/dist/{repo-security-plan-CGXT5CIP.js → repo-security-plan-CTK2K2K7.js} +3 -3
  60. package/dist/{research-helpers-synthesize-37WHCE5I.js → research-helpers-synthesize-ICHGZ3TE.js} +4 -4
  61. package/dist/{routing-memory-YWPM45FH.js → routing-memory-CSIJCK3H.js} +2 -2
  62. package/dist/{session-memory-ENUULCNK.js → session-memory-EYZALDQ2.js} +3 -3
  63. package/dist/{setup-command-T6I5TRFR.js → setup-command-YFY4HEOU.js} +11 -11
  64. package/dist/{setup-config-AMGGWQHX.js → setup-config-3IJFI55J.js} +3 -3
  65. package/dist/{setup-custom-api-UNAPYLEX.js → setup-custom-api-MS2SBFTP.js} +3 -3
  66. package/dist/{tool-memory-QH3DN2SU.js → tool-memory-WD3LOBUM.js} +5 -5
  67. package/dist/{unified-registry-YXQGTU3P.js → unified-registry-D7EF252L.js} +9 -9
  68. package/dist/{weather-report-BUKQ7YPV.js → weather-report-V2GTV5MW.js} +2 -2
  69. package/package.json +1 -1
  70. package/dist/chunk-E7LG7L4O.js.map +0 -1
  71. package/dist/chunk-I6NTUVGW.js.map +0 -1
  72. package/dist/chunk-VKUP2PG5.js.map +0 -1
  73. /package/dist/{child-mcp-config-XEXFG3LA.js.map → child-mcp-config-CR5HFAFF.js.map} +0 -0
  74. /package/dist/{chunk-SNKSSSAR.js.map → chunk-2XOUYCGO.js.map} +0 -0
  75. /package/dist/{chunk-AMY4S4VD.js.map → chunk-3B2WRRTU.js.map} +0 -0
  76. /package/dist/{chunk-I2DK3KSH.js.map → chunk-3CPGHAZN.js.map} +0 -0
  77. /package/dist/{chunk-7XISTLQP.js.map → chunk-5VYWG6N4.js.map} +0 -0
  78. /package/dist/{chunk-RNCBSF6I.js.map → chunk-6QOMNQAM.js.map} +0 -0
  79. /package/dist/{chunk-WRISLYLK.js.map → chunk-7ABXSM2X.js.map} +0 -0
  80. /package/dist/{chunk-B23GFISN.js.map → chunk-B3FRHPJW.js.map} +0 -0
  81. /package/dist/{chunk-SN4Q7TZT.js.map → chunk-B4DIA6YS.js.map} +0 -0
  82. /package/dist/{chunk-ED6B55WK.js.map → chunk-B6CLLXZB.js.map} +0 -0
  83. /package/dist/{chunk-HBLVOFLL.js.map → chunk-CWVPSHEP.js.map} +0 -0
  84. /package/dist/{chunk-IG2SIC2E.js.map → chunk-DMFDSHOQ.js.map} +0 -0
  85. /package/dist/{chunk-HT3B6ZWV.js.map → chunk-DTBU4J67.js.map} +0 -0
  86. /package/dist/{chunk-MXNIOTDY.js.map → chunk-E7SVEDLI.js.map} +0 -0
  87. /package/dist/{chunk-ZO54JW4V.js.map → chunk-FE4TTIW7.js.map} +0 -0
  88. /package/dist/{chunk-QVIQAIOK.js.map → chunk-I3RJEXY2.js.map} +0 -0
  89. /package/dist/{chunk-JYV5MZC6.js.map → chunk-KFWCF32D.js.map} +0 -0
  90. /package/dist/{chunk-QD653D5O.js.map → chunk-LEMQDF4W.js.map} +0 -0
  91. /package/dist/{chunk-Q6EGZKLE.js.map → chunk-MMPZLMSH.js.map} +0 -0
  92. /package/dist/{chunk-WP6UBBNJ.js.map → chunk-MONR3CEL.js.map} +0 -0
  93. /package/dist/{chunk-VWX75FKD.js.map → chunk-PLEB6SON.js.map} +0 -0
  94. /package/dist/{chunk-3QIXGEY7.js.map → chunk-POHORI2I.js.map} +0 -0
  95. /package/dist/{chunk-5NVU25BA.js.map → chunk-QWZOEVR6.js.map} +0 -0
  96. /package/dist/{chunk-ZBEJITR6.js.map → chunk-RV6S6OZJ.js.map} +0 -0
  97. /package/dist/{chunk-XLEZBTQG.js.map → chunk-SDJQ2H7V.js.map} +0 -0
  98. /package/dist/{chunk-O27ZG7BL.js.map → chunk-THE4NODE.js.map} +0 -0
  99. /package/dist/{chunk-ICYEG7T4.js.map → chunk-TVPLAB4X.js.map} +0 -0
  100. /package/dist/{chunk-FYQSTNG6.js.map → chunk-VV45XQVW.js.map} +0 -0
  101. /package/dist/{chunk-4AXOISAP.js.map → chunk-VWOMHATO.js.map} +0 -0
  102. /package/dist/{chunk-RU336IEH.js.map → chunk-WVKEKRZZ.js.map} +0 -0
  103. /package/dist/{cli-circuit-breaker-SAHRY3BI.js.map → cli-circuit-breaker-ISW6F7DI.js.map} +0 -0
  104. /package/dist/{composite-router-MFJNLR3O.js.map → composite-router-PB4ZVWUH.js.map} +0 -0
  105. /package/dist/{consensus-vote-Z55357CP.js.map → consensus-vote-FVKOLIPS.js.map} +0 -0
  106. /package/dist/{context-retriever-Z474PNZ4.js.map → context-retriever-TGIQ6FNS.js.map} +0 -0
  107. /package/dist/{doctor-deep-IESAJDVW.js.map → doctor-deep-VEFTQZMR.js.map} +0 -0
  108. /package/dist/{expert-bridge-JW4DJPH3.js.map → expert-bridge-SFBHTNIB.js.map} +0 -0
  109. /package/dist/{factory-6JIXPGRH.js.map → factory-DEO5DAXZ.js.map} +0 -0
  110. /package/dist/{factory-Z7GGTUK2.js.map → factory-NF7WS67L.js.map} +0 -0
  111. /package/dist/{improvement-review-5DRIOL5K.js.map → improvement-review-AFDZO6PL.js.map} +0 -0
  112. /package/dist/{init-opencode-T2F5WSLT.js.map → init-opencode-ELTBZAIN.js.map} +0 -0
  113. /package/dist/{issue-triage-RC5VVUAV.js.map → issue-triage-3WL7PW26.js.map} +0 -0
  114. /package/dist/{pr-reviewer-helpers-G35TGA7R.js.map → pr-reviewer-helpers-7ES4HWFC.js.map} +0 -0
  115. /package/dist/{registry-command-47UO65SV.js.map → registry-command-3AXI4JXN.js.map} +0 -0
  116. /package/dist/{repo-security-plan-CGXT5CIP.js.map → repo-security-plan-CTK2K2K7.js.map} +0 -0
  117. /package/dist/{research-helpers-synthesize-37WHCE5I.js.map → research-helpers-synthesize-ICHGZ3TE.js.map} +0 -0
  118. /package/dist/{routing-memory-YWPM45FH.js.map → routing-memory-CSIJCK3H.js.map} +0 -0
  119. /package/dist/{session-memory-ENUULCNK.js.map → session-memory-EYZALDQ2.js.map} +0 -0
  120. /package/dist/{setup-command-T6I5TRFR.js.map → setup-command-YFY4HEOU.js.map} +0 -0
  121. /package/dist/{setup-config-AMGGWQHX.js.map → setup-config-3IJFI55J.js.map} +0 -0
  122. /package/dist/{setup-custom-api-UNAPYLEX.js.map → setup-custom-api-MS2SBFTP.js.map} +0 -0
  123. /package/dist/{tool-memory-QH3DN2SU.js.map → tool-memory-WD3LOBUM.js.map} +0 -0
  124. /package/dist/{unified-registry-YXQGTU3P.js.map → unified-registry-D7EF252L.js.map} +0 -0
  125. /package/dist/{weather-report-BUKQ7YPV.js.map → weather-report-V2GTV5MW.js.map} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  toolStructuredError,
8
8
  toolSuccessStructured,
9
9
  wrapToolWithTimeout
10
- } from "./chunk-4AXOISAP.js";
10
+ } from "./chunk-VWOMHATO.js";
11
11
  import {
12
12
  JsonlStore,
13
13
  SECURITY_KEYWORDS,
@@ -19,7 +19,7 @@ import {
19
19
  getPipelineEventBus,
20
20
  getTimeProvider,
21
21
  isDeclaredNeverDeprecate
22
- } from "./chunk-E7LG7L4O.js";
22
+ } from "./chunk-E5XTAHAS.js";
23
23
  import {
24
24
  getNexusDataDir,
25
25
  nexusDataPath
@@ -2132,4 +2132,4 @@ export {
2132
2132
  runImprovementReview,
2133
2133
  registerImprovementReviewTool
2134
2134
  };
2135
- //# sourceMappingURL=chunk-MXNIOTDY.js.map
2135
+ //# sourceMappingURL=chunk-E7SVEDLI.js.map
@@ -2,14 +2,14 @@ import {
2
2
  CircuitBreakerRegistry,
3
3
  CircuitError,
4
4
  mapCliErrorToCategory
5
- } from "./chunk-3QIXGEY7.js";
5
+ } from "./chunk-POHORI2I.js";
6
6
  import {
7
7
  createLogger,
8
8
  err,
9
9
  getFallbackChainForCategory,
10
10
  getTimeProvider,
11
11
  ok
12
- } from "./chunk-E7LG7L4O.js";
12
+ } from "./chunk-E5XTAHAS.js";
13
13
 
14
14
  // src/cli-adapters/cli-circuit-breaker.ts
15
15
  var CATEGORY_TO_FALLBACK = {
@@ -152,4 +152,4 @@ export {
152
152
  CliCircuitBreakerIntegration,
153
153
  createCliCircuitBreakerIntegration
154
154
  };
155
- //# sourceMappingURL=chunk-ZO54JW4V.js.map
155
+ //# sourceMappingURL=chunk-FE4TTIW7.js.map
@@ -15,7 +15,7 @@ import {
15
15
  createLogger,
16
16
  err,
17
17
  ok
18
- } from "./chunk-E7LG7L4O.js";
18
+ } from "./chunk-E5XTAHAS.js";
19
19
 
20
20
  // src/adapters/sdk/types.ts
21
21
  var PROVIDER_ENV_KEYS = {
@@ -184,10 +184,10 @@ var DEFAULTS = {
184
184
  TIMEOUT_DEFAULTS: {
185
185
  /** CLI tool execution timeout in milliseconds. */
186
186
  cliMs: CLI_TIMEOUTS.default.standard,
187
- /** Simple CLI task timeout (single function, quick query). */
188
- cliSimpleMs: CLI_TIMEOUTS.default.simple,
189
- /** Complex CLI task timeout (codebase-wide, deep analysis). */
190
- cliComplexMs: CLI_TIMEOUTS.default.complex,
187
+ // cliSimpleMs / cliComplexMs removed in #4180 never read by any production
188
+ // code (the matching NEXUS_TIMEOUT_CLISIMPLE/CLICOMPLEX env vars were silent
189
+ // no-ops, #2977 class). Per-complexity CLI timeouts come from
190
+ // getTimeoutForCli/TIMEOUT_PROFILES (CLI_TIMEOUTS in config/timeouts.ts).
191
191
  /** API request timeout in milliseconds. */
192
192
  apiMs: API_TIMEOUTS.defaultMs,
193
193
  /** Maximum API timeout in milliseconds. */
@@ -396,4 +396,4 @@ export {
396
396
  CUSTOM_API_DEFAULT_MODEL,
397
397
  DEFAULTS
398
398
  };
399
- //# sourceMappingURL=chunk-SHFCJJTY.js.map
399
+ //# sourceMappingURL=chunk-FKXR4ELM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/sdk/types.ts","../src/adapters/sdk/custom-api-validation.ts","../src/config/defaults.ts"],"sourcesContent":["/**\n * nexus-agents/adapters/sdk - Shared Types\n *\n * Type definitions for AI SDK adapter layer.\n *\n * @module adapters/sdk/types\n * (Source: Issue #1123 — AI SDK provider layer)\n */\n\n/**\n * Supported AI SDK provider identifiers.\n *\n * `custom-openai` is for OpenAI-compatible gateways (multi-vendor proxies,\n * self-hosted LLM servers, corporate model gateways) — uses the same\n * @ai-sdk/openai package but with a configurable `baseURL`.\n */\nexport type SdkProviderId = 'anthropic' | 'openai' | 'google' | 'custom-openai';\n\n/**\n * Configuration for creating an AI SDK adapter.\n */\nexport interface SdkAdapterConfig {\n /** Provider identifier */\n providerId: SdkProviderId;\n /** Model to use (e.g., 'claude-sonnet-4-6', 'gpt-4o') */\n modelId: string;\n /** API key (falls back to environment variable) */\n apiKey?: string;\n /**\n * Base URL for OpenAI-compatible gateways. Required when\n * `providerId === 'custom-openai'`, ignored otherwise. Falls back to\n * the `NEXUS_CUSTOM_API_BASE_URL` environment variable.\n */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Maximum retries on transient failures */\n maxRetries?: number;\n}\n\n/**\n * Maps provider IDs to their environment variable names.\n */\nexport const PROVIDER_ENV_KEYS: Record<SdkProviderId, string> = {\n anthropic: 'ANTHROPIC_API_KEY',\n openai: 'OPENAI_API_KEY',\n google: 'GOOGLE_AI_API_KEY',\n 'custom-openai': 'NEXUS_CUSTOM_API_KEY',\n};\n\n/**\n * Environment variable name for the custom gateway base URL.\n * Keep in sync with `SdkAdapterConfig.baseUrl`.\n */\nexport const CUSTOM_API_BASE_URL_ENV = 'NEXUS_CUSTOM_API_BASE_URL';\n\n/**\n * Escape hatch: set to `1`/`true` to allow the custom gateway base URL to\n * resolve to a loopback or RFC 1918 private address. Default is DENY —\n * SSRF defense. Only disable this when you know the gateway runs on a\n * trusted internal host and you accept the risk.\n */\nexport const CUSTOM_API_ALLOW_PRIVATE_ENV = 'NEXUS_CUSTOM_API_ALLOW_PRIVATE';\n","/**\n * Validation for the `custom-openai` SDK adapter's gateway URL.\n *\n * The base URL is user-provided, so without validation the adapter becomes\n * an SSRF vector: a malicious prompt that reshaped env vars, or a typo in\n * the config, could point nexus-agents at `http://169.254.169.254/` (AWS\n * metadata) or `http://localhost:5432/` (internal services). This module\n * rejects such URLs unless the user explicitly opts in via\n * `NEXUS_CUSTOM_API_ALLOW_PRIVATE=1`.\n *\n * Called out in the #2119 consensus vote by the Security Engineer role.\n *\n * @module adapters/sdk/custom-api-validation\n */\n\nimport { isIPv4, isIPv6 } from 'node:net';\nimport { lookup as dnsLookup } from 'node:dns/promises';\nimport { ConfigError, ok, err, createLogger, type Result } from '../../core/index.js';\nimport { CUSTOM_API_ALLOW_PRIVATE_ENV } from './types.js';\n\nconst logger = createLogger({ module: 'custom-api-validation' });\n\n/**\n * Why a given URL was rejected. Machine-readable so error messages can\n * distinguish root causes in downstream tooling.\n */\nexport type BaseUrlRejectionReason =\n | 'empty'\n | 'not_a_url'\n | 'not_http_https'\n | 'loopback'\n | 'link_local'\n | 'private_range'\n | 'reserved';\n\ninterface RejectionDetail {\n readonly reason: BaseUrlRejectionReason;\n readonly message: string;\n}\n\n/**\n * Validates a user-provided custom-gateway base URL. Returns the URL as an\n * `ok` Result if it passes, or a `ConfigError` with a machine-readable\n * reason if it fails.\n *\n * Pass `{ allowPrivate: true }` (or set the env var) to bypass the SSRF\n * checks — use this only when the gateway is on a trusted internal host\n * and you accept the risk.\n */\nexport function validateCustomApiBaseUrl(\n raw: string | undefined,\n opts: { readonly allowPrivate?: boolean } = {}\n): Result<URL, ConfigError> {\n if (raw === undefined || raw.trim() === '') {\n return err(\n new ConfigError(\n 'Custom API base URL is required but missing. Set NEXUS_CUSTOM_API_BASE_URL or pass `baseUrl` in config.'\n )\n );\n }\n\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n return err(new ConfigError(`Custom API base URL is not a valid URL: ${raw}`));\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return err(\n new ConfigError(`Custom API base URL must use http or https, got \"${url.protocol}\" in ${raw}`)\n );\n }\n\n const allowPrivate = opts.allowPrivate === true || resolveAllowPrivateFromEnv();\n if (!allowPrivate) {\n const rejection = classifyPrivateHost(url.hostname);\n if (rejection !== null) {\n return err(\n new ConfigError(\n `Custom API base URL rejected (SSRF guard, reason=\"${rejection.reason}\"): ${rejection.message}. ` +\n `Set ${CUSTOM_API_ALLOW_PRIVATE_ENV}=1 to bypass if the gateway runs on a trusted internal host.`\n )\n );\n }\n }\n\n return ok(url);\n}\n\nfunction resolveAllowPrivateFromEnv(): boolean {\n // Deliberately strict (case-sensitive, not parseBoolEnv): this disables an\n // SSRF guard, so we don't want extra case variants (e.g. `TRUE`) to loosen\n // the control. Fail-closed on anything but exact `1`/`true` (#3297).\n const v = process.env[CUSTOM_API_ALLOW_PRIVATE_ENV];\n return v === '1' || v === 'true';\n}\n\n/**\n * Returns a rejection reason if the hostname resolves (by string form) to\n * a loopback, link-local, or RFC 1918 private address; `null` otherwise.\n *\n * Note: this is a string-level check. It does NOT perform DNS resolution,\n * so a public DNS name that secretly resolves to a private IP will pass.\n * For that level of defense, callers should additionally run\n * {@link assertCustomApiHostResolvesPublic}, which performs a DNS lookup\n * and classifies each resolved address with the same range tables below.\n */\nfunction classifyPrivateHost(hostname: string): RejectionDetail | null {\n const normalized = normalizeHost(hostname);\n\n // Literal IP addresses — classify directly against the range tables.\n const literal = classifyIpAddress(normalized);\n if (literal !== 'not_an_ip') {\n return literal;\n }\n\n // Hostname literals that resolve to loopback without needing DNS\n if (\n normalized === 'localhost' ||\n normalized.endsWith('.localhost') ||\n normalized.endsWith('.local') // mDNS\n ) {\n return {\n reason: 'loopback',\n message: `hostname \"${hostname}\" resolves to loopback/mDNS`,\n };\n }\n\n return null;\n}\n\n/**\n * Strips IPv6 bracket wrapping (URL.hostname yields \"[::1]\") and lowercases,\n * giving the bare form the `node:net` checks expect. Shared by the sync and\n * async guards so the normalization rule lives in one place.\n */\nfunction normalizeHost(hostname: string): string {\n const stripped =\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n return stripped.toLowerCase();\n}\n\n/**\n * Classifies a single (already normalized, bracket-stripped) address string.\n * Returns:\n * - a {@link RejectionDetail} if it is a private/loopback/link-local/reserved IP,\n * - `null` if it is a public IP literal (safe),\n * - the sentinel `'not_an_ip'` if the string is not an IP literal at all.\n *\n * This is the shared per-address classifier reused by both the sync\n * string-level guard ({@link classifyPrivateHost}) and the async\n * DNS-resolve-time guard ({@link assertCustomApiHostResolvesPublic}), so the\n * IPv4/IPv6 range tables live in exactly one place.\n */\nfunction classifyIpAddress(normalized: string): RejectionDetail | null | 'not_an_ip' {\n if (isIPv4(normalized)) {\n return classifyIPv4(normalized);\n }\n if (isIPv6(normalized)) {\n return classifyIPv6(normalized);\n }\n return 'not_an_ip';\n}\n\n/**\n * DNS-resolve-time SSRF guard for the custom-openai gateway.\n *\n * The sync {@link validateCustomApiBaseUrl} only inspects the hostname as a\n * string, so a PUBLIC DNS name that resolves to a PRIVATE/loopback/link-local\n * IP (e.g. an attacker-controlled `gateway.evil.test` pointing at\n * `169.254.169.254`) slips past it. This function closes that gap: it resolves\n * the hostname and runs the EXISTING IP classification against every returned\n * address, failing closed if ANY of them is private.\n *\n * Behaviour:\n * - `allowPrivate` (opt or env) → bypass, returns `ok` (matches the sync guard).\n * - hostname is already an IP literal → no DNS needed; the sync guard already\n * classified literals at construction, so return `ok`.\n * - otherwise `dns.lookup(hostname, { all: true })` and classify each address.\n * If ANY resolves private → `err(ConfigError)`.\n * - on a `dns.lookup` THROW (transient/NXDOMAIN/network error) → log debug and\n * return `ok`. Failing closed here is too aggressive: it would break legit\n * gateways on a flaky resolver, and this is additive defense-in-depth layered\n * on top of the sync string guard that already ran at construction. We only\n * REJECT on a SUCCESSFUL resolution to a private address.\n *\n * Residual risk (TOCTOU): this is RESOLVE-time, not socket-connect-time. A name\n * that passes here could rebind to a private IP before the actual connect\n * (DNS rebinding). A full fix needs a custom `fetch` `lookup` hook validating\n * the peer address at the socket layer — out of scope for this LOW\n * defense-in-depth pass (#3426).\n */\nexport async function assertCustomApiHostResolvesPublic(\n hostname: string,\n opts: { readonly allowPrivate?: boolean } = {}\n): Promise<Result<void, ConfigError>> {\n const allowPrivate = opts.allowPrivate === true || resolveAllowPrivateFromEnv();\n if (allowPrivate) {\n return ok(undefined);\n }\n\n const normalized = normalizeHost(hostname);\n\n // IP literals are already handled by the sync guard at construction; no DNS.\n if (isIPv4(normalized) || isIPv6(normalized)) {\n return ok(undefined);\n }\n\n // Only `address` is read; the resolver's `family` is intentionally NOT\n // trusted — `classifyIpAddress` re-derives v4/v6 from the address string, so\n // a mislabeled family in the lookup result cannot let a private IP slip past.\n let addresses: ReadonlyArray<{ readonly address: string }>;\n try {\n addresses = await dnsLookup(hostname, { all: true });\n } catch (error) {\n // Fail OPEN: transient/NXDOMAIN/network errors must not break legit\n // gateways. The sync string guard already ran; this is additive only.\n logger.debug('custom-api SSRF resolve check: DNS lookup failed, skipping (fail-open)', {\n hostname,\n error: error instanceof Error ? error.message : String(error),\n });\n return ok(undefined);\n }\n\n const rejection = firstPrivateAddress(addresses);\n if (rejection !== null) {\n return err(\n new ConfigError(\n `Custom API base URL rejected (SSRF resolve guard, reason=\"${rejection.reason}\"): ` +\n `hostname \"${hostname}\" resolved to ${rejection.message}. ` +\n `Set ${CUSTOM_API_ALLOW_PRIVATE_ENV}=1 to bypass if the gateway runs on a trusted internal host.`\n )\n );\n }\n\n return ok(undefined);\n}\n\n/**\n * Returns the {@link RejectionDetail} for the first resolved address that\n * classifies as private/loopback/link-local/reserved, or `null` if every\n * address is public. Fail-closed: any single private hit trips the guard.\n */\nfunction firstPrivateAddress(\n addresses: ReadonlyArray<{ readonly address: string }>\n): RejectionDetail | null {\n for (const { address } of addresses) {\n const rejection = classifyIpAddress(address.toLowerCase());\n if (rejection !== null && rejection !== 'not_an_ip') {\n return rejection;\n }\n }\n return null;\n}\n\n/** IPv4 ranges the SSRF guard rejects, in order of specificity. */\nconst IPV4_RULES: ReadonlyArray<{\n readonly match: (a: number, b: number) => boolean;\n readonly reason: BaseUrlRejectionReason;\n readonly label: string;\n}> = [\n { match: (a) => a === 127, reason: 'loopback', label: 'IPv4 loopback' },\n { match: (a) => a === 10, reason: 'private_range', label: 'IPv4 private (10/8)' },\n {\n match: (a, b) => a === 172 && b >= 16 && b <= 31,\n reason: 'private_range',\n label: 'IPv4 private (172.16/12)',\n },\n {\n match: (a, b) => a === 192 && b === 168,\n reason: 'private_range',\n label: 'IPv4 private (192.168/16)',\n },\n {\n match: (a, b) => a === 169 && b === 254,\n reason: 'link_local',\n label: 'IPv4 link-local (169.254/16 — AWS IMDS)',\n },\n { match: (a) => a === 0, reason: 'reserved', label: 'IPv4 reserved (0/8)' },\n];\n\nfunction classifyIPv4(ip: string): RejectionDetail | null {\n const parts = ip.split('.').map((p) => Number.parseInt(p, 10));\n if (parts.length !== 4 || parts.some((n) => Number.isNaN(n))) return null;\n const [a, b] = parts as [number, number, number, number];\n for (const rule of IPV4_RULES) {\n if (rule.match(a, b)) {\n return { reason: rule.reason, message: `${rule.label} (${ip})` };\n }\n }\n return null;\n}\n\nfunction classifyIPv6(ip: string): RejectionDetail | null {\n const lower = ip.toLowerCase();\n if (lower === '::1') return { reason: 'loopback', message: `IPv6 loopback (${ip})` };\n if (lower.startsWith('fe80:'))\n return { reason: 'link_local', message: `IPv6 link-local (${ip})` };\n // Unique-local: fc00::/7 → first byte has high bit set and second-high bit set\n if (/^fc|^fd/.test(lower)) {\n return { reason: 'private_range', message: `IPv6 unique-local (${ip}, fc00::/7)` };\n }\n return null;\n}\n","/**\n * Central Configuration Defaults\n *\n * Consolidates common default values used across the codebase.\n * This prevents scattered magic numbers and ensures consistency.\n *\n * Usage:\n * import { DEFAULTS, getTimeout, TIMEOUT_PROFILES } from '../config/defaults.js';\n * const timeout = options.timeout ?? DEFAULTS.TIMEOUT_DEFAULTS.cliMs;\n * const cliTimeout = getTimeoutForCli('claude', 'complex');\n *\n * Environment overrides can be added via NEXUS_* environment variables.\n *\n * @module config/defaults\n * (Source: Central config consolidation initiative)\n */\n\n// Re-export types from defaults-types\nexport type {\n TaskComplexity,\n TimeoutProfile,\n KnownCliName,\n TimeoutDefaults,\n RateLimitDefaults,\n ToolRateLimitConfig,\n RetryDefaults,\n CircuitBreakerDefaults,\n} from './defaults-types.js';\n\nexport { isTaskComplexity, isKnownCliName } from './defaults-types.js';\n\n// Re-export timeout profiles (delegates to config/timeouts.ts)\nexport {\n TIMEOUT_PROFILES,\n getTimeoutProfile,\n getTimeoutForCli,\n} from './defaults-timeout-profiles.js';\n\n// Re-export canonical timeout modules (Issue #984)\nexport {\n CLI_TIMEOUTS,\n VOTE_TIMEOUTS,\n MCP_TIMEOUTS,\n WORKFLOW_TIMEOUTS,\n GRAPH_TIMEOUTS,\n PER_CLI_TASK_TIMEOUTS,\n API_TIMEOUTS,\n INTERNAL_TIMEOUTS,\n TEST_TIMEOUTS,\n TIMEOUT_ENV_VARS,\n getCliTimeoutProfile,\n getCliTimeout,\n resolveVoteTimeout,\n resolveEnvTimeout,\n validateTimeout,\n BACKOFF_CONFIG,\n AGENT_ROUTER_TIMEOUTS,\n CODEX_MCP_TIMEOUTS,\n} from './timeouts.js';\n\n// Re-export env helpers (internal use)\nexport { parseIntEnv, parseFloatEnv, parseBoolEnv } from './defaults-env.js';\n\nimport {\n createGetTimeout,\n createGetRetryConfig,\n createGetRateLimitConfig,\n createGetCircuitBreakerConfig,\n createGetToolRateLimit,\n createGetEnvVarDocumentation,\n} from './defaults-env.js';\nimport {\n API_TIMEOUTS as _API,\n WORKFLOW_TIMEOUTS as _WF,\n MCP_TIMEOUTS as _MCP,\n INTERNAL_TIMEOUTS as _INT,\n TEST_TIMEOUTS as _TEST,\n CLI_TIMEOUTS as _CLI,\n} from './timeouts.js';\n\n// ============================================================================\n// Default Model IDs (#2200 Child 4)\n// ============================================================================\n\n/**\n * Default model identifier for the custom OpenAI-compatible API gateway.\n *\n * Used by both `cli/setup-custom-api.ts` (write to nexus-agents.yaml) and\n * `adapters/auto-adapter.ts` (NEXUS_CUSTOM_MODEL env-var fallback). Single\n * source of truth so changes flow through all consumers.\n *\n * `gpt-4o` is widely supported across OpenAI-compatible gateways (vLLM,\n * LiteLLM, Together AI, etc.) — a pragmatic baseline rather than the\n * cheapest or most capable. Operators are expected to override.\n */\nexport const CUSTOM_API_DEFAULT_MODEL = 'gpt-4o';\n\n// ============================================================================\n// Central Defaults Object\n// ============================================================================\n\n/**\n * Central defaults object containing all configuration categories.\n */\nexport const DEFAULTS = {\n /**\n * Default timeout settings in milliseconds.\n * Values sourced from config/timeouts.ts (Issue #984).\n */\n TIMEOUT_DEFAULTS: {\n /** CLI tool execution timeout in milliseconds. */\n cliMs: _CLI.default.standard,\n /** Simple CLI task timeout (single function, quick query). */\n cliSimpleMs: _CLI.default.simple,\n /** Complex CLI task timeout (codebase-wide, deep analysis). */\n cliComplexMs: _CLI.default.complex,\n /** API request timeout in milliseconds. */\n apiMs: _API.defaultMs,\n /** Maximum API timeout in milliseconds. */\n apiMaxMs: _API.maxMs,\n /** Workflow-level timeout in milliseconds (5 minutes). */\n workflowMs: _WF.workflowMs,\n /** Maximum workflow timeout in milliseconds (30 minutes). */\n workflowMaxMs: _WF.workflowMaxMs,\n /** Step-level timeout in milliseconds. */\n stepMs: _INT.selfEvalMs,\n /** MCP operation default timeout in milliseconds (generic, not per-tool). */\n mcpMs: _API.defaultMs,\n /** MCP operation maximum timeout in milliseconds. */\n mcpMaxMs: _MCP.maxMs,\n /** Health check timeout in milliseconds. */\n healthCheckMs: _INT.healthCheckMs,\n /** Global test run timeout in milliseconds (10 minutes). */\n testGlobalMs: _TEST.globalMs,\n /** Per-task test timeout in milliseconds. */\n testTaskMs: _TEST.taskMs,\n /** Circuit breaker reset timeout in milliseconds. */\n circuitBreakerResetMs: _INT.circuitBreakerResetMs,\n },\n\n /**\n * Default rate limit settings for outbound operations.\n */\n RATE_LIMIT_DEFAULTS: {\n /** Global requests per minute. */\n requestsPerMinute: 60,\n /** Whether rate limiting is enabled by default. */\n enabled: true,\n /** Maximum number of concurrent requests. */\n maxConcurrent: 4,\n /** Token bucket capacity. */\n capacity: 100,\n /** Token bucket refill rate per second. */\n refillRate: 10,\n /** Refill interval in milliseconds. */\n refillIntervalMs: 100,\n },\n\n /**\n * Per-tool rate limit defaults for MCP tools.\n * (Source: Issue #274 Phase 2 - per-tool rate limits)\n */\n TOOL_RATE_LIMITS: {\n orchestrate: { capacity: 10, refillRate: 10, refillIntervalMs: 60_000 },\n delegate: { capacity: 20, refillRate: 20, refillIntervalMs: 60_000 },\n workflow: { capacity: 5, refillRate: 5, refillIntervalMs: 60_000 },\n expert: { capacity: 30, refillRate: 30, refillIntervalMs: 60_000 },\n },\n\n /**\n * Default retry strategy settings for transient failures.\n */\n RETRY_DEFAULTS: {\n /** Maximum retry attempts before failing. */\n maxRetries: 3,\n /** Base delay between retries in milliseconds. */\n baseDelayMs: 1_000,\n /** Maximum delay between retries in milliseconds. */\n maxDelayMs: 30_000,\n /** Jitter factor (0-1) to randomize retry delays. */\n jitterFactor: 0.1,\n },\n\n /**\n * Workflow-specific retry defaults.\n */\n WORKFLOW_RETRY_DEFAULTS: {\n /** Maximum retry attempts for workflow steps. */\n maxRetries: 2,\n /** Base delay for workflow retries in milliseconds. */\n baseDelayMs: 2_000,\n /** Maximum delay for workflow retries in milliseconds. */\n maxDelayMs: 60_000,\n /** Jitter factor for workflow retries. */\n jitterFactor: 0.15,\n },\n\n /**\n * CLI-specific retry defaults.\n */\n CLI_RETRY_DEFAULTS: {\n /** Maximum retry attempts for CLI operations. */\n maxRetries: 2,\n /** Base delay for CLI retries in milliseconds. */\n baseDelayMs: 5_000,\n /** Maximum delay for CLI retries in milliseconds. */\n maxDelayMs: 60_000,\n /** Jitter factor for CLI retries. */\n jitterFactor: 0.2,\n },\n\n /**\n * Test framework retry defaults.\n */\n TEST_RETRY_DEFAULTS: {\n /** Maximum retries per test task. */\n maxRetries: 2,\n /** Whether to retry failed tasks by default. */\n retryFailedTasks: true,\n },\n\n /**\n * Default buffer sizing for batching and chunked processing.\n */\n BUFFER_DEFAULTS: {\n /** Preferred batch size for bulk operations. */\n batchSize: 100,\n /** Chunk size for streaming or segmented processing. */\n chunkSize: 256,\n /** Maximum items allowed in a buffer. */\n maxItems: 1_000,\n /** Maximum memory size in bytes (10 MB). */\n maxMemoryBytes: 10 * 1024 * 1024,\n /** Log buffer flush interval in milliseconds. */\n logFlushIntervalMs: 5_000,\n },\n\n // WORKER_DEFAULTS removed in #2977 — the eight settings under this category\n // (maxWorkers, poolSize, idleTimeoutMs, workflowMaxParallel, testParallelism,\n // evaluationMaxWorkers, eventBusMaxHistory, swarmObserverMaxEvents) had zero\n // production consumers. `getWorkerConfig()` was never called from anywhere\n // in src/, and the matching NEXUS_WORKERS_* env vars were silent no-ops.\n // Silent config rot is worse than missing knobs; re-add when a concrete\n // consumer exists.\n\n /**\n * Default circuit breaker settings.\n * (Source: Issue #81 - Circuit breaker for CLI failures)\n */\n CIRCUIT_BREAKER_DEFAULTS: {\n /** Failure threshold to open circuit. */\n failureThreshold: 5,\n /** Reset timeout in milliseconds. */\n resetTimeoutMs: 30_000,\n /** Success threshold to close circuit in half-open state. */\n halfOpenSuccessThreshold: 2,\n /** Whether to count timeouts as failures. */\n countTimeoutsAsFailures: true,\n /** Whether to count auth failures as failures. */\n countAuthFailuresAsFailures: false,\n /** Whether to count rate limit errors as failures (#1529). */\n countRateLimitsAsFailures: true,\n /** Maximum requests allowed in half-open state. */\n halfOpenMaxRequests: 3,\n },\n\n /**\n * Default context/memory settings.\n */\n CONTEXT_DEFAULTS: {\n /** Maximum context tokens. */\n maxTokens: 100_000,\n /** Token budget warning threshold (80%). */\n warningThreshold: 0.8,\n /** Token budget critical threshold (95%). */\n criticalThreshold: 0.95,\n /** Maximum history entries to retain. */\n maxHistoryEntries: 1_000,\n },\n\n /**\n * Default provider/model settings.\n */\n PROVIDER_DEFAULTS: {\n /** Default timeout for provider API calls in ms. */\n timeout: 30_000,\n /** Maximum retries for provider requests. */\n maxRetries: 3,\n /** Default model tier. */\n defaultTier: 'balanced' as const,\n /** Default temperature. */\n temperatureDefault: 0.3,\n /** Minimum temperature. */\n temperatureMin: 0,\n /** Maximum temperature. */\n temperatureMax: 1,\n /** Billing mode: 'plan' (monthly subscription) or 'api' (pay-per-token). Env: NEXUS_BILLING_MODE */\n billingMode: 'plan' as const,\n },\n\n /**\n * Security-related defaults.\n */\n SECURITY_DEFAULTS: {\n /** Maximum system prompt length in characters. */\n maxSystemPromptLength: 4_000,\n /** Default policy execution mode. */\n policyDefaultMode: 'read-only' as const,\n /** Default policy mode. */\n policyMode: 'enforce' as const,\n /** Default sandbox mode. */\n sandboxMode: 'policy' as const,\n /** Whether to fall back to policy mode if container unavailable. */\n sandboxFallbackToPolicy: true,\n /** Whether network is enabled in container mode. */\n sandboxNetworkEnabled: false,\n },\n} as const;\n\n// ============================================================================\n// Type Exports for DEFAULTS\n// ============================================================================\n\n/** Type for the DEFAULTS object (readonly/const). */\nexport type DefaultsConfig = typeof DEFAULTS;\n\n/** Type for timeout defaults (readonly/const). */\nexport type TimeoutDefaultsConst = typeof DEFAULTS.TIMEOUT_DEFAULTS;\n\n/** Type for rate limit defaults (readonly/const). */\nexport type RateLimitDefaultsConst = typeof DEFAULTS.RATE_LIMIT_DEFAULTS;\n\n/** Type for retry defaults (readonly/const). */\nexport type RetryDefaultsConst = typeof DEFAULTS.RETRY_DEFAULTS;\n\n/** Type for buffer defaults (readonly/const). */\nexport type BufferDefaults = typeof DEFAULTS.BUFFER_DEFAULTS;\n\n/** Type for circuit breaker defaults (readonly/const). */\nexport type CircuitBreakerDefaultsConst = typeof DEFAULTS.CIRCUIT_BREAKER_DEFAULTS;\n\n/** Type for context defaults (readonly/const). */\nexport type ContextDefaults = typeof DEFAULTS.CONTEXT_DEFAULTS;\n\n/** Type for provider defaults (readonly/const). */\nexport type ProviderDefaults = typeof DEFAULTS.PROVIDER_DEFAULTS;\n\n/** Type for security defaults (readonly/const). */\nexport type SecurityDefaults = typeof DEFAULTS.SECURITY_DEFAULTS;\n\n// ============================================================================\n// Environment Override Functions (bound to DEFAULTS)\n// ============================================================================\n\n/**\n * Get timeout with environment override support.\n *\n * @param key - Timeout key (e.g., 'cliMs', 'apiMs')\n * @returns Timeout value in milliseconds\n */\nexport const getTimeout = createGetTimeout(DEFAULTS.TIMEOUT_DEFAULTS);\n\n/**\n * Get retry config with environment override support.\n *\n * @returns Retry configuration\n */\nexport const getRetryConfig = createGetRetryConfig(DEFAULTS.RETRY_DEFAULTS);\n\n/**\n * Get rate limit config with environment override support.\n *\n * @returns Rate limit configuration\n */\nexport const getRateLimitConfig = createGetRateLimitConfig(DEFAULTS.RATE_LIMIT_DEFAULTS);\n\n/**\n * Gets the circuit breaker configuration.\n *\n * @returns Circuit breaker configuration\n */\nexport const getCircuitBreakerConfig = createGetCircuitBreakerConfig(\n DEFAULTS.CIRCUIT_BREAKER_DEFAULTS\n);\n\n/**\n * Gets the tool rate limit configuration for a specific tool category.\n *\n * @param tool - Tool category (orchestrate, delegate, workflow, expert)\n * @returns Rate limit configuration\n */\nexport const getToolRateLimit = createGetToolRateLimit(DEFAULTS.TOOL_RATE_LIMITS);\n\n// ============================================================================\n// Documentation Helper\n// ============================================================================\n\n/**\n * Returns documentation for all environment variable overrides.\n *\n * @returns Markdown documentation string\n */\nexport const getEnvVarDocumentation = createGetEnvVarDocumentation(DEFAULTS);\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/adapters/sdk/types.ts","../src/adapters/sdk/custom-api-validation.ts","../src/config/defaults.ts"],"sourcesContent":["/**\n * nexus-agents/adapters/sdk - Shared Types\n *\n * Type definitions for AI SDK adapter layer.\n *\n * @module adapters/sdk/types\n * (Source: Issue #1123 — AI SDK provider layer)\n */\n\n/**\n * Supported AI SDK provider identifiers.\n *\n * `custom-openai` is for OpenAI-compatible gateways (multi-vendor proxies,\n * self-hosted LLM servers, corporate model gateways) — uses the same\n * @ai-sdk/openai package but with a configurable `baseURL`.\n */\nexport type SdkProviderId = 'anthropic' | 'openai' | 'google' | 'custom-openai';\n\n/**\n * Configuration for creating an AI SDK adapter.\n */\nexport interface SdkAdapterConfig {\n /** Provider identifier */\n providerId: SdkProviderId;\n /** Model to use (e.g., 'claude-sonnet-4-6', 'gpt-4o') */\n modelId: string;\n /** API key (falls back to environment variable) */\n apiKey?: string;\n /**\n * Base URL for OpenAI-compatible gateways. Required when\n * `providerId === 'custom-openai'`, ignored otherwise. Falls back to\n * the `NEXUS_CUSTOM_API_BASE_URL` environment variable.\n */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Maximum retries on transient failures */\n maxRetries?: number;\n}\n\n/**\n * Maps provider IDs to their environment variable names.\n */\nexport const PROVIDER_ENV_KEYS: Record<SdkProviderId, string> = {\n anthropic: 'ANTHROPIC_API_KEY',\n openai: 'OPENAI_API_KEY',\n google: 'GOOGLE_AI_API_KEY',\n 'custom-openai': 'NEXUS_CUSTOM_API_KEY',\n};\n\n/**\n * Environment variable name for the custom gateway base URL.\n * Keep in sync with `SdkAdapterConfig.baseUrl`.\n */\nexport const CUSTOM_API_BASE_URL_ENV = 'NEXUS_CUSTOM_API_BASE_URL';\n\n/**\n * Escape hatch: set to `1`/`true` to allow the custom gateway base URL to\n * resolve to a loopback or RFC 1918 private address. Default is DENY —\n * SSRF defense. Only disable this when you know the gateway runs on a\n * trusted internal host and you accept the risk.\n */\nexport const CUSTOM_API_ALLOW_PRIVATE_ENV = 'NEXUS_CUSTOM_API_ALLOW_PRIVATE';\n","/**\n * Validation for the `custom-openai` SDK adapter's gateway URL.\n *\n * The base URL is user-provided, so without validation the adapter becomes\n * an SSRF vector: a malicious prompt that reshaped env vars, or a typo in\n * the config, could point nexus-agents at `http://169.254.169.254/` (AWS\n * metadata) or `http://localhost:5432/` (internal services). This module\n * rejects such URLs unless the user explicitly opts in via\n * `NEXUS_CUSTOM_API_ALLOW_PRIVATE=1`.\n *\n * Called out in the #2119 consensus vote by the Security Engineer role.\n *\n * @module adapters/sdk/custom-api-validation\n */\n\nimport { isIPv4, isIPv6 } from 'node:net';\nimport { lookup as dnsLookup } from 'node:dns/promises';\nimport { ConfigError, ok, err, createLogger, type Result } from '../../core/index.js';\nimport { CUSTOM_API_ALLOW_PRIVATE_ENV } from './types.js';\n\nconst logger = createLogger({ module: 'custom-api-validation' });\n\n/**\n * Why a given URL was rejected. Machine-readable so error messages can\n * distinguish root causes in downstream tooling.\n */\nexport type BaseUrlRejectionReason =\n | 'empty'\n | 'not_a_url'\n | 'not_http_https'\n | 'loopback'\n | 'link_local'\n | 'private_range'\n | 'reserved';\n\ninterface RejectionDetail {\n readonly reason: BaseUrlRejectionReason;\n readonly message: string;\n}\n\n/**\n * Validates a user-provided custom-gateway base URL. Returns the URL as an\n * `ok` Result if it passes, or a `ConfigError` with a machine-readable\n * reason if it fails.\n *\n * Pass `{ allowPrivate: true }` (or set the env var) to bypass the SSRF\n * checks — use this only when the gateway is on a trusted internal host\n * and you accept the risk.\n */\nexport function validateCustomApiBaseUrl(\n raw: string | undefined,\n opts: { readonly allowPrivate?: boolean } = {}\n): Result<URL, ConfigError> {\n if (raw === undefined || raw.trim() === '') {\n return err(\n new ConfigError(\n 'Custom API base URL is required but missing. Set NEXUS_CUSTOM_API_BASE_URL or pass `baseUrl` in config.'\n )\n );\n }\n\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n return err(new ConfigError(`Custom API base URL is not a valid URL: ${raw}`));\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return err(\n new ConfigError(`Custom API base URL must use http or https, got \"${url.protocol}\" in ${raw}`)\n );\n }\n\n const allowPrivate = opts.allowPrivate === true || resolveAllowPrivateFromEnv();\n if (!allowPrivate) {\n const rejection = classifyPrivateHost(url.hostname);\n if (rejection !== null) {\n return err(\n new ConfigError(\n `Custom API base URL rejected (SSRF guard, reason=\"${rejection.reason}\"): ${rejection.message}. ` +\n `Set ${CUSTOM_API_ALLOW_PRIVATE_ENV}=1 to bypass if the gateway runs on a trusted internal host.`\n )\n );\n }\n }\n\n return ok(url);\n}\n\nfunction resolveAllowPrivateFromEnv(): boolean {\n // Deliberately strict (case-sensitive, not parseBoolEnv): this disables an\n // SSRF guard, so we don't want extra case variants (e.g. `TRUE`) to loosen\n // the control. Fail-closed on anything but exact `1`/`true` (#3297).\n const v = process.env[CUSTOM_API_ALLOW_PRIVATE_ENV];\n return v === '1' || v === 'true';\n}\n\n/**\n * Returns a rejection reason if the hostname resolves (by string form) to\n * a loopback, link-local, or RFC 1918 private address; `null` otherwise.\n *\n * Note: this is a string-level check. It does NOT perform DNS resolution,\n * so a public DNS name that secretly resolves to a private IP will pass.\n * For that level of defense, callers should additionally run\n * {@link assertCustomApiHostResolvesPublic}, which performs a DNS lookup\n * and classifies each resolved address with the same range tables below.\n */\nfunction classifyPrivateHost(hostname: string): RejectionDetail | null {\n const normalized = normalizeHost(hostname);\n\n // Literal IP addresses — classify directly against the range tables.\n const literal = classifyIpAddress(normalized);\n if (literal !== 'not_an_ip') {\n return literal;\n }\n\n // Hostname literals that resolve to loopback without needing DNS\n if (\n normalized === 'localhost' ||\n normalized.endsWith('.localhost') ||\n normalized.endsWith('.local') // mDNS\n ) {\n return {\n reason: 'loopback',\n message: `hostname \"${hostname}\" resolves to loopback/mDNS`,\n };\n }\n\n return null;\n}\n\n/**\n * Strips IPv6 bracket wrapping (URL.hostname yields \"[::1]\") and lowercases,\n * giving the bare form the `node:net` checks expect. Shared by the sync and\n * async guards so the normalization rule lives in one place.\n */\nfunction normalizeHost(hostname: string): string {\n const stripped =\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n return stripped.toLowerCase();\n}\n\n/**\n * Classifies a single (already normalized, bracket-stripped) address string.\n * Returns:\n * - a {@link RejectionDetail} if it is a private/loopback/link-local/reserved IP,\n * - `null` if it is a public IP literal (safe),\n * - the sentinel `'not_an_ip'` if the string is not an IP literal at all.\n *\n * This is the shared per-address classifier reused by both the sync\n * string-level guard ({@link classifyPrivateHost}) and the async\n * DNS-resolve-time guard ({@link assertCustomApiHostResolvesPublic}), so the\n * IPv4/IPv6 range tables live in exactly one place.\n */\nfunction classifyIpAddress(normalized: string): RejectionDetail | null | 'not_an_ip' {\n if (isIPv4(normalized)) {\n return classifyIPv4(normalized);\n }\n if (isIPv6(normalized)) {\n return classifyIPv6(normalized);\n }\n return 'not_an_ip';\n}\n\n/**\n * DNS-resolve-time SSRF guard for the custom-openai gateway.\n *\n * The sync {@link validateCustomApiBaseUrl} only inspects the hostname as a\n * string, so a PUBLIC DNS name that resolves to a PRIVATE/loopback/link-local\n * IP (e.g. an attacker-controlled `gateway.evil.test` pointing at\n * `169.254.169.254`) slips past it. This function closes that gap: it resolves\n * the hostname and runs the EXISTING IP classification against every returned\n * address, failing closed if ANY of them is private.\n *\n * Behaviour:\n * - `allowPrivate` (opt or env) → bypass, returns `ok` (matches the sync guard).\n * - hostname is already an IP literal → no DNS needed; the sync guard already\n * classified literals at construction, so return `ok`.\n * - otherwise `dns.lookup(hostname, { all: true })` and classify each address.\n * If ANY resolves private → `err(ConfigError)`.\n * - on a `dns.lookup` THROW (transient/NXDOMAIN/network error) → log debug and\n * return `ok`. Failing closed here is too aggressive: it would break legit\n * gateways on a flaky resolver, and this is additive defense-in-depth layered\n * on top of the sync string guard that already ran at construction. We only\n * REJECT on a SUCCESSFUL resolution to a private address.\n *\n * Residual risk (TOCTOU): this is RESOLVE-time, not socket-connect-time. A name\n * that passes here could rebind to a private IP before the actual connect\n * (DNS rebinding). A full fix needs a custom `fetch` `lookup` hook validating\n * the peer address at the socket layer — out of scope for this LOW\n * defense-in-depth pass (#3426).\n */\nexport async function assertCustomApiHostResolvesPublic(\n hostname: string,\n opts: { readonly allowPrivate?: boolean } = {}\n): Promise<Result<void, ConfigError>> {\n const allowPrivate = opts.allowPrivate === true || resolveAllowPrivateFromEnv();\n if (allowPrivate) {\n return ok(undefined);\n }\n\n const normalized = normalizeHost(hostname);\n\n // IP literals are already handled by the sync guard at construction; no DNS.\n if (isIPv4(normalized) || isIPv6(normalized)) {\n return ok(undefined);\n }\n\n // Only `address` is read; the resolver's `family` is intentionally NOT\n // trusted — `classifyIpAddress` re-derives v4/v6 from the address string, so\n // a mislabeled family in the lookup result cannot let a private IP slip past.\n let addresses: ReadonlyArray<{ readonly address: string }>;\n try {\n addresses = await dnsLookup(hostname, { all: true });\n } catch (error) {\n // Fail OPEN: transient/NXDOMAIN/network errors must not break legit\n // gateways. The sync string guard already ran; this is additive only.\n logger.debug('custom-api SSRF resolve check: DNS lookup failed, skipping (fail-open)', {\n hostname,\n error: error instanceof Error ? error.message : String(error),\n });\n return ok(undefined);\n }\n\n const rejection = firstPrivateAddress(addresses);\n if (rejection !== null) {\n return err(\n new ConfigError(\n `Custom API base URL rejected (SSRF resolve guard, reason=\"${rejection.reason}\"): ` +\n `hostname \"${hostname}\" resolved to ${rejection.message}. ` +\n `Set ${CUSTOM_API_ALLOW_PRIVATE_ENV}=1 to bypass if the gateway runs on a trusted internal host.`\n )\n );\n }\n\n return ok(undefined);\n}\n\n/**\n * Returns the {@link RejectionDetail} for the first resolved address that\n * classifies as private/loopback/link-local/reserved, or `null` if every\n * address is public. Fail-closed: any single private hit trips the guard.\n */\nfunction firstPrivateAddress(\n addresses: ReadonlyArray<{ readonly address: string }>\n): RejectionDetail | null {\n for (const { address } of addresses) {\n const rejection = classifyIpAddress(address.toLowerCase());\n if (rejection !== null && rejection !== 'not_an_ip') {\n return rejection;\n }\n }\n return null;\n}\n\n/** IPv4 ranges the SSRF guard rejects, in order of specificity. */\nconst IPV4_RULES: ReadonlyArray<{\n readonly match: (a: number, b: number) => boolean;\n readonly reason: BaseUrlRejectionReason;\n readonly label: string;\n}> = [\n { match: (a) => a === 127, reason: 'loopback', label: 'IPv4 loopback' },\n { match: (a) => a === 10, reason: 'private_range', label: 'IPv4 private (10/8)' },\n {\n match: (a, b) => a === 172 && b >= 16 && b <= 31,\n reason: 'private_range',\n label: 'IPv4 private (172.16/12)',\n },\n {\n match: (a, b) => a === 192 && b === 168,\n reason: 'private_range',\n label: 'IPv4 private (192.168/16)',\n },\n {\n match: (a, b) => a === 169 && b === 254,\n reason: 'link_local',\n label: 'IPv4 link-local (169.254/16 — AWS IMDS)',\n },\n { match: (a) => a === 0, reason: 'reserved', label: 'IPv4 reserved (0/8)' },\n];\n\nfunction classifyIPv4(ip: string): RejectionDetail | null {\n const parts = ip.split('.').map((p) => Number.parseInt(p, 10));\n if (parts.length !== 4 || parts.some((n) => Number.isNaN(n))) return null;\n const [a, b] = parts as [number, number, number, number];\n for (const rule of IPV4_RULES) {\n if (rule.match(a, b)) {\n return { reason: rule.reason, message: `${rule.label} (${ip})` };\n }\n }\n return null;\n}\n\nfunction classifyIPv6(ip: string): RejectionDetail | null {\n const lower = ip.toLowerCase();\n if (lower === '::1') return { reason: 'loopback', message: `IPv6 loopback (${ip})` };\n if (lower.startsWith('fe80:'))\n return { reason: 'link_local', message: `IPv6 link-local (${ip})` };\n // Unique-local: fc00::/7 → first byte has high bit set and second-high bit set\n if (/^fc|^fd/.test(lower)) {\n return { reason: 'private_range', message: `IPv6 unique-local (${ip}, fc00::/7)` };\n }\n return null;\n}\n","/**\n * Central Configuration Defaults\n *\n * Consolidates common default values used across the codebase.\n * This prevents scattered magic numbers and ensures consistency.\n *\n * Usage:\n * import { DEFAULTS, getTimeout, TIMEOUT_PROFILES } from '../config/defaults.js';\n * const timeout = options.timeout ?? DEFAULTS.TIMEOUT_DEFAULTS.cliMs;\n * const cliTimeout = getTimeoutForCli('claude', 'complex');\n *\n * Environment overrides can be added via NEXUS_* environment variables.\n *\n * @module config/defaults\n * (Source: Central config consolidation initiative)\n */\n\n// Re-export types from defaults-types\nexport type {\n TaskComplexity,\n TimeoutProfile,\n KnownCliName,\n TimeoutDefaults,\n RateLimitDefaults,\n ToolRateLimitConfig,\n RetryDefaults,\n CircuitBreakerDefaults,\n} from './defaults-types.js';\n\nexport { isTaskComplexity, isKnownCliName } from './defaults-types.js';\n\n// Re-export timeout profiles (delegates to config/timeouts.ts)\nexport {\n TIMEOUT_PROFILES,\n getTimeoutProfile,\n getTimeoutForCli,\n} from './defaults-timeout-profiles.js';\n\n// Re-export canonical timeout modules (Issue #984)\nexport {\n CLI_TIMEOUTS,\n VOTE_TIMEOUTS,\n MCP_TIMEOUTS,\n WORKFLOW_TIMEOUTS,\n GRAPH_TIMEOUTS,\n PER_CLI_TASK_TIMEOUTS,\n API_TIMEOUTS,\n INTERNAL_TIMEOUTS,\n TEST_TIMEOUTS,\n TIMEOUT_ENV_VARS,\n getCliTimeoutProfile,\n getCliTimeout,\n resolveVoteTimeout,\n resolveEnvTimeout,\n validateTimeout,\n BACKOFF_CONFIG,\n AGENT_ROUTER_TIMEOUTS,\n CODEX_MCP_TIMEOUTS,\n} from './timeouts.js';\n\n// Re-export env helpers (internal use)\nexport { parseIntEnv, parseFloatEnv, parseBoolEnv } from './defaults-env.js';\n\nimport {\n createGetTimeout,\n createGetRetryConfig,\n createGetRateLimitConfig,\n createGetCircuitBreakerConfig,\n createGetToolRateLimit,\n createGetEnvVarDocumentation,\n} from './defaults-env.js';\nimport {\n API_TIMEOUTS as _API,\n WORKFLOW_TIMEOUTS as _WF,\n MCP_TIMEOUTS as _MCP,\n INTERNAL_TIMEOUTS as _INT,\n TEST_TIMEOUTS as _TEST,\n CLI_TIMEOUTS as _CLI,\n} from './timeouts.js';\n\n// ============================================================================\n// Default Model IDs (#2200 Child 4)\n// ============================================================================\n\n/**\n * Default model identifier for the custom OpenAI-compatible API gateway.\n *\n * Used by both `cli/setup-custom-api.ts` (write to nexus-agents.yaml) and\n * `adapters/auto-adapter.ts` (NEXUS_CUSTOM_MODEL env-var fallback). Single\n * source of truth so changes flow through all consumers.\n *\n * `gpt-4o` is widely supported across OpenAI-compatible gateways (vLLM,\n * LiteLLM, Together AI, etc.) — a pragmatic baseline rather than the\n * cheapest or most capable. Operators are expected to override.\n */\nexport const CUSTOM_API_DEFAULT_MODEL = 'gpt-4o';\n\n// ============================================================================\n// Central Defaults Object\n// ============================================================================\n\n/**\n * Central defaults object containing all configuration categories.\n */\nexport const DEFAULTS = {\n /**\n * Default timeout settings in milliseconds.\n * Values sourced from config/timeouts.ts (Issue #984).\n */\n TIMEOUT_DEFAULTS: {\n /** CLI tool execution timeout in milliseconds. */\n cliMs: _CLI.default.standard,\n // cliSimpleMs / cliComplexMs removed in #4180 — never read by any production\n // code (the matching NEXUS_TIMEOUT_CLISIMPLE/CLICOMPLEX env vars were silent\n // no-ops, #2977 class). Per-complexity CLI timeouts come from\n // getTimeoutForCli/TIMEOUT_PROFILES (CLI_TIMEOUTS in config/timeouts.ts).\n /** API request timeout in milliseconds. */\n apiMs: _API.defaultMs,\n /** Maximum API timeout in milliseconds. */\n apiMaxMs: _API.maxMs,\n /** Workflow-level timeout in milliseconds (5 minutes). */\n workflowMs: _WF.workflowMs,\n /** Maximum workflow timeout in milliseconds (30 minutes). */\n workflowMaxMs: _WF.workflowMaxMs,\n /** Step-level timeout in milliseconds. */\n stepMs: _INT.selfEvalMs,\n /** MCP operation default timeout in milliseconds (generic, not per-tool). */\n mcpMs: _API.defaultMs,\n /** MCP operation maximum timeout in milliseconds. */\n mcpMaxMs: _MCP.maxMs,\n /** Health check timeout in milliseconds. */\n healthCheckMs: _INT.healthCheckMs,\n /** Global test run timeout in milliseconds (10 minutes). */\n testGlobalMs: _TEST.globalMs,\n /** Per-task test timeout in milliseconds. */\n testTaskMs: _TEST.taskMs,\n /** Circuit breaker reset timeout in milliseconds. */\n circuitBreakerResetMs: _INT.circuitBreakerResetMs,\n },\n\n /**\n * Default rate limit settings for outbound operations.\n */\n RATE_LIMIT_DEFAULTS: {\n /** Global requests per minute. */\n requestsPerMinute: 60,\n /** Whether rate limiting is enabled by default. */\n enabled: true,\n /** Maximum number of concurrent requests. */\n maxConcurrent: 4,\n /** Token bucket capacity. */\n capacity: 100,\n /** Token bucket refill rate per second. */\n refillRate: 10,\n /** Refill interval in milliseconds. */\n refillIntervalMs: 100,\n },\n\n /**\n * Per-tool rate limit defaults for MCP tools.\n * (Source: Issue #274 Phase 2 - per-tool rate limits)\n */\n TOOL_RATE_LIMITS: {\n orchestrate: { capacity: 10, refillRate: 10, refillIntervalMs: 60_000 },\n delegate: { capacity: 20, refillRate: 20, refillIntervalMs: 60_000 },\n workflow: { capacity: 5, refillRate: 5, refillIntervalMs: 60_000 },\n expert: { capacity: 30, refillRate: 30, refillIntervalMs: 60_000 },\n },\n\n /**\n * Default retry strategy settings for transient failures.\n */\n RETRY_DEFAULTS: {\n /** Maximum retry attempts before failing. */\n maxRetries: 3,\n /** Base delay between retries in milliseconds. */\n baseDelayMs: 1_000,\n /** Maximum delay between retries in milliseconds. */\n maxDelayMs: 30_000,\n /** Jitter factor (0-1) to randomize retry delays. */\n jitterFactor: 0.1,\n },\n\n /**\n * Workflow-specific retry defaults.\n */\n WORKFLOW_RETRY_DEFAULTS: {\n /** Maximum retry attempts for workflow steps. */\n maxRetries: 2,\n /** Base delay for workflow retries in milliseconds. */\n baseDelayMs: 2_000,\n /** Maximum delay for workflow retries in milliseconds. */\n maxDelayMs: 60_000,\n /** Jitter factor for workflow retries. */\n jitterFactor: 0.15,\n },\n\n /**\n * CLI-specific retry defaults.\n */\n CLI_RETRY_DEFAULTS: {\n /** Maximum retry attempts for CLI operations. */\n maxRetries: 2,\n /** Base delay for CLI retries in milliseconds. */\n baseDelayMs: 5_000,\n /** Maximum delay for CLI retries in milliseconds. */\n maxDelayMs: 60_000,\n /** Jitter factor for CLI retries. */\n jitterFactor: 0.2,\n },\n\n /**\n * Test framework retry defaults.\n */\n TEST_RETRY_DEFAULTS: {\n /** Maximum retries per test task. */\n maxRetries: 2,\n /** Whether to retry failed tasks by default. */\n retryFailedTasks: true,\n },\n\n /**\n * Default buffer sizing for batching and chunked processing.\n */\n BUFFER_DEFAULTS: {\n /** Preferred batch size for bulk operations. */\n batchSize: 100,\n /** Chunk size for streaming or segmented processing. */\n chunkSize: 256,\n /** Maximum items allowed in a buffer. */\n maxItems: 1_000,\n /** Maximum memory size in bytes (10 MB). */\n maxMemoryBytes: 10 * 1024 * 1024,\n /** Log buffer flush interval in milliseconds. */\n logFlushIntervalMs: 5_000,\n },\n\n // WORKER_DEFAULTS removed in #2977 — the eight settings under this category\n // (maxWorkers, poolSize, idleTimeoutMs, workflowMaxParallel, testParallelism,\n // evaluationMaxWorkers, eventBusMaxHistory, swarmObserverMaxEvents) had zero\n // production consumers. `getWorkerConfig()` was never called from anywhere\n // in src/, and the matching NEXUS_WORKERS_* env vars were silent no-ops.\n // Silent config rot is worse than missing knobs; re-add when a concrete\n // consumer exists.\n\n /**\n * Default circuit breaker settings.\n * (Source: Issue #81 - Circuit breaker for CLI failures)\n */\n CIRCUIT_BREAKER_DEFAULTS: {\n /** Failure threshold to open circuit. */\n failureThreshold: 5,\n /** Reset timeout in milliseconds. */\n resetTimeoutMs: 30_000,\n /** Success threshold to close circuit in half-open state. */\n halfOpenSuccessThreshold: 2,\n /** Whether to count timeouts as failures. */\n countTimeoutsAsFailures: true,\n /** Whether to count auth failures as failures. */\n countAuthFailuresAsFailures: false,\n /** Whether to count rate limit errors as failures (#1529). */\n countRateLimitsAsFailures: true,\n /** Maximum requests allowed in half-open state. */\n halfOpenMaxRequests: 3,\n },\n\n /**\n * Default context/memory settings.\n */\n CONTEXT_DEFAULTS: {\n /** Maximum context tokens. */\n maxTokens: 100_000,\n /** Token budget warning threshold (80%). */\n warningThreshold: 0.8,\n /** Token budget critical threshold (95%). */\n criticalThreshold: 0.95,\n /** Maximum history entries to retain. */\n maxHistoryEntries: 1_000,\n },\n\n /**\n * Default provider/model settings.\n */\n PROVIDER_DEFAULTS: {\n /** Default timeout for provider API calls in ms. */\n timeout: 30_000,\n /** Maximum retries for provider requests. */\n maxRetries: 3,\n /** Default model tier. */\n defaultTier: 'balanced' as const,\n /** Default temperature. */\n temperatureDefault: 0.3,\n /** Minimum temperature. */\n temperatureMin: 0,\n /** Maximum temperature. */\n temperatureMax: 1,\n /** Billing mode: 'plan' (monthly subscription) or 'api' (pay-per-token). Env: NEXUS_BILLING_MODE */\n billingMode: 'plan' as const,\n },\n\n /**\n * Security-related defaults.\n */\n SECURITY_DEFAULTS: {\n /** Maximum system prompt length in characters. */\n maxSystemPromptLength: 4_000,\n /** Default policy execution mode. */\n policyDefaultMode: 'read-only' as const,\n /** Default policy mode. */\n policyMode: 'enforce' as const,\n /** Default sandbox mode. */\n sandboxMode: 'policy' as const,\n /** Whether to fall back to policy mode if container unavailable. */\n sandboxFallbackToPolicy: true,\n /** Whether network is enabled in container mode. */\n sandboxNetworkEnabled: false,\n },\n} as const;\n\n// ============================================================================\n// Type Exports for DEFAULTS\n// ============================================================================\n\n/** Type for the DEFAULTS object (readonly/const). */\nexport type DefaultsConfig = typeof DEFAULTS;\n\n/** Type for timeout defaults (readonly/const). */\nexport type TimeoutDefaultsConst = typeof DEFAULTS.TIMEOUT_DEFAULTS;\n\n/** Type for rate limit defaults (readonly/const). */\nexport type RateLimitDefaultsConst = typeof DEFAULTS.RATE_LIMIT_DEFAULTS;\n\n/** Type for retry defaults (readonly/const). */\nexport type RetryDefaultsConst = typeof DEFAULTS.RETRY_DEFAULTS;\n\n/** Type for buffer defaults (readonly/const). */\nexport type BufferDefaults = typeof DEFAULTS.BUFFER_DEFAULTS;\n\n/** Type for circuit breaker defaults (readonly/const). */\nexport type CircuitBreakerDefaultsConst = typeof DEFAULTS.CIRCUIT_BREAKER_DEFAULTS;\n\n/** Type for context defaults (readonly/const). */\nexport type ContextDefaults = typeof DEFAULTS.CONTEXT_DEFAULTS;\n\n/** Type for provider defaults (readonly/const). */\nexport type ProviderDefaults = typeof DEFAULTS.PROVIDER_DEFAULTS;\n\n/** Type for security defaults (readonly/const). */\nexport type SecurityDefaults = typeof DEFAULTS.SECURITY_DEFAULTS;\n\n// ============================================================================\n// Environment Override Functions (bound to DEFAULTS)\n// ============================================================================\n\n/**\n * Get timeout with environment override support.\n *\n * @param key - Timeout key (e.g., 'cliMs', 'apiMs')\n * @returns Timeout value in milliseconds\n */\nexport const getTimeout = createGetTimeout(DEFAULTS.TIMEOUT_DEFAULTS);\n\n/**\n * Get retry config with environment override support.\n *\n * @returns Retry configuration\n */\nexport const getRetryConfig = createGetRetryConfig(DEFAULTS.RETRY_DEFAULTS);\n\n/**\n * Get rate limit config with environment override support.\n *\n * @returns Rate limit configuration\n */\nexport const getRateLimitConfig = createGetRateLimitConfig(DEFAULTS.RATE_LIMIT_DEFAULTS);\n\n/**\n * Gets the circuit breaker configuration.\n *\n * @returns Circuit breaker configuration\n */\nexport const getCircuitBreakerConfig = createGetCircuitBreakerConfig(\n DEFAULTS.CIRCUIT_BREAKER_DEFAULTS\n);\n\n/**\n * Gets the tool rate limit configuration for a specific tool category.\n *\n * @param tool - Tool category (orchestrate, delegate, workflow, expert)\n * @returns Rate limit configuration\n */\nexport const getToolRateLimit = createGetToolRateLimit(DEFAULTS.TOOL_RATE_LIMITS);\n\n// ============================================================================\n// Documentation Helper\n// ============================================================================\n\n/**\n * Returns documentation for all environment variable overrides.\n *\n * @returns Markdown documentation string\n */\nexport const getEnvVarDocumentation = createGetEnvVarDocumentation(DEFAULTS);\n"],"mappings":"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","names":[]}
@@ -11,7 +11,7 @@ import {
11
11
  isRateLimitLikeError,
12
12
  lookupInTreeCapability,
13
13
  ok
14
- } from "./chunk-E7LG7L4O.js";
14
+ } from "./chunk-E5XTAHAS.js";
15
15
 
16
16
  // src/config/model-parameter-support.ts
17
17
  function parseClaudeMajorMinor(bareId) {
@@ -828,4 +828,4 @@ export {
828
828
  DEFAULT_COLLECT_STREAM_MAX_CHUNKS,
829
829
  collectStream
830
830
  };
831
- //# sourceMappingURL=chunk-I6NTUVGW.js.map
831
+ //# sourceMappingURL=chunk-HUXMIDNV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/model-parameter-support.ts","../src/config/temperature-support.ts","../src/adapters/optional-params.ts","../src/adapters/base-adapter.ts","../src/adapters/streaming-types.ts","../src/adapters/stream-operators-helpers.ts","../src/adapters/stream-operators.ts","../src/adapters/streaming.ts"],"sourcesContent":["/**\n * nexus-agents/config — data-driven model request-parameter capability resolver\n * (#4067, epic #4066 layer 1).\n *\n * Generalizes the ad-hoc `temperatureUnsupportedForModel` (#4061/#4062) into a\n * registry-first resolver. Two questions every adapter param-builder asks before\n * forwarding a request parameter:\n *\n * 1. Does this model REJECT a given parameter (so the adapter must omit it)?\n * {@link unsupportedParametersForModel} / {@link modelSupportsParameter}.\n * 2. Which max-tokens param name does it expect — `max_tokens` (chat-completions\n * default) or `max_completion_tokens` (OpenAI reasoning models, #4049)?\n * {@link getMaxTokensParamForModel}.\n *\n * RESOLUTION ORDER (each function): (a) registry capability data — the in-tree\n * `ModelCapability.unsupportedParameters` / `.maxTokensParam` looked up via\n * `lookupInTreeCapability`; if present, it WINS; (b) otherwise the regex fallback\n * below, preserving the EXACT logic that lived in `temperature-support.ts` so\n * unregistered ids (Claude 4.7/4.8, bare o-series) keep resolving correctly.\n *\n * Deterministic: a given id (with a stable registry) yields the same result every\n * call. Biased AGAINST false-positive stripping — a missed rejection is a 400\n * outage, a wrongly-stripped param only loses a tuning knob (the same bias the\n * temperature predicate documented). `temperature-support.ts` is now a thin shim\n * over {@link modelSupportsParameter}.\n *\n * @module config/model-parameter-support\n */\n\nimport { lookupInTreeCapability } from './model-config-helpers.js';\n\n// ---------------------------------------------------------------------------\n// Regex fallback internals (moved verbatim from temperature-support.ts, #4061)\n// ---------------------------------------------------------------------------\n\ninterface ClaudeMajorMinor {\n readonly major: number;\n readonly minor: number;\n}\n\n/**\n * Parse the FIRST numeric version from a (provider-prefix-stripped) Claude model\n * id — a major with an OPTIONAL minor, tolerating `-`, `_`, and `.` separators.\n *\n * A trailing snapshot date (`-20250514`, 6+ digits) is stripped FIRST so it cannot\n * be mistaken for a minor: `claude-opus-4-20250514` is Opus **4.0**, not 4.20250514.\n * A bare major with no minor is treated as `.0` (`claude-opus-4` → 4.0,\n * `claude-fable-5` → 5.0). major/minor are kept as separate integers so `4.10`\n * compares ABOVE `4.6` (a `parseFloat` would collapse to 4.1). Returns `null` only\n * when the id carries no version digits at all (e.g. `claude-instant`,\n * `claude-newfamily`).\n */\nfunction parseClaudeMajorMinor(bareId: string): ClaudeMajorMinor | null {\n const undated = bareId.replace(/[-_]\\d{6,}$/, '');\n const match = /(\\d+)(?:[-_.](\\d+))?/.exec(undated);\n if (match === null) return null;\n const major = Number.parseInt(match[1] as string, 10);\n const minor = match[2] !== undefined ? Number.parseInt(match[2], 10) : 0;\n if (Number.isNaN(major) || Number.isNaN(minor)) return null;\n return { major, minor };\n}\n\n/** Recognized LEGACY Claude families that still support `temperature` (pre-4.x). */\nconst LEGACY_TEMPERATURE_SUPPORTING = /claude[-_](?:instant|1|2|3)(?:[-_.]|$)/;\n\n/**\n * Claude branch of the temperature regex fallback (#4061). `bare` is the id\n * sliced from the first `claude` (provider prefix stripped). Unsupported when the\n * version is after Opus 4.6, or the family is unrecognized/non-numbered\n * (`claude-fable-5`, future) — a deliberate SAFE-DROP, since a benign fall-back to\n * the API default beats a 400.\n */\nfunction claudeTemperatureUnsupported(bare: string): boolean {\n const version = parseClaudeMajorMinor(bare);\n if (version !== null) {\n // \"after Opus 4.6\": major > 4, or 4.7+ within the 4.x line.\n return version.major > 4 || (version.major === 4 && version.minor >= 7);\n }\n if (LEGACY_TEMPERATURE_SUPPORTING.test(bare)) return false;\n return true;\n}\n\n/**\n * OpenAI REASONING-model detection (#4062). True ONLY for the reasoning models\n * documented to reject `temperature` and to use `max_completion_tokens`;\n * everything else (gpt-4o, gpt-4, gpt-3.5, gemini, openrouter-*, …) returns false.\n * `id` is the full lower-cased model id.\n *\n * - o-series: `o1`/`o3`/`o3-mini`/`o4-mini` — `o` + digit at the START of the last\n * path segment (so `claude-opus`/`openrouter-*` cannot match).\n * - codex: all current `codex…` routes are GPT-5-reasoning-based.\n * - GPT-5 family: `gpt-5` / `gpt5` (anchored after the `5` so `gpt-50`/`gpt-512`\n * do NOT match) — EXCEPT the non-reasoning `gpt-5-chat` variant.\n */\nfunction openAiReasoning(id: string): boolean {\n const segment = id.includes('/') ? id.slice(id.lastIndexOf('/') + 1) : id;\n if (/^o[0-9]/.test(segment)) return true;\n if (segment.includes('codex')) return true;\n if (/gpt-?5(?![0-9])/.test(segment) && !segment.includes('gpt-5-chat')) return true;\n return false;\n}\n\n/**\n * Regex fallback for whether `modelId` rejects a non-default `temperature`. The\n * EXACT predicate that was `temperatureUnsupportedForModel` before #4067 — Claude\n * after Opus 4.6, OpenAI o-series / GPT-5 family / codex; everything else false.\n * Robust to gateway id variants (provider prefixes, `-`/`_` separators, dated\n * suffixes).\n */\nfunction regexRejectsTemperature(modelId: string): boolean {\n const id = modelId.toLowerCase();\n const claudeAt = id.indexOf('claude');\n if (claudeAt !== -1) {\n return claudeTemperatureUnsupported(id.slice(claudeAt)); // strip provider prefix\n }\n return openAiReasoning(id);\n}\n\n/** Regex fallback for OpenAI-reasoning detection (Claude ids are never reasoning here). */\nfunction regexIsOpenAiReasoning(modelId: string): boolean {\n const id = modelId.toLowerCase();\n if (id.includes('claude')) return false;\n return openAiReasoning(id);\n}\n\n// ---------------------------------------------------------------------------\n// Public resolver API\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters `modelId` REJECTS. Registry capability data first\n * (`ModelCapability.unsupportedParameters`), else the regex fallback for\n * unregistered models (Claude>4.6, OpenAI o-series/codex/gpt-5 reject\n * `'temperature'`; nothing else, for now). Deterministic.\n */\nexport function unsupportedParametersForModel(modelId: string): readonly string[] {\n const cap = lookupInTreeCapability(modelId);\n if (cap?.unsupportedParameters !== undefined) return cap.unsupportedParameters;\n return regexRejectsTemperature(modelId) ? ['temperature'] : [];\n}\n\n/** True iff `modelId` accepts `param`. */\nexport function modelSupportsParameter(modelId: string, param: string): boolean {\n return !unsupportedParametersForModel(modelId).includes(param);\n}\n\n/**\n * The max-tokens param name `modelId` expects: registry `maxTokensParam` first,\n * else regex fallback (OpenAI reasoning → `'max_completion_tokens'`, else\n * `'max_tokens'`).\n */\nexport function getMaxTokensParamForModel(modelId: string): 'max_tokens' | 'max_completion_tokens' {\n const cap = lookupInTreeCapability(modelId);\n if (cap?.maxTokensParam !== undefined) return cap.maxTokensParam;\n return regexIsOpenAiReasoning(modelId) ? 'max_completion_tokens' : 'max_tokens';\n}\n\n// ---------------------------------------------------------------------------\n// Known-incompatibility registry — the drift guard's source of truth (#4070)\n// ---------------------------------------------------------------------------\n\n/**\n * One DOCUMENTED model-parameter incompatibility — a real incident the resolver\n * MUST keep handling. A `param` entry asserts the model rejects that request\n * parameter ({@link modelSupportsParameter} must be false); a `maxTokensParam`\n * entry asserts the max-tokens field name ({@link getMaxTokensParamForModel}).\n */\nexport interface KnownParameterIncompatibility {\n /** A model id that hits the case (registry-encoded OR regex-fallback). */\n readonly modelId: string;\n /** The rejected request parameter (mutually exclusive with `maxTokensParam`). */\n readonly param?: string;\n /** The expected max-tokens field name (mutually exclusive with `param`). */\n readonly maxTokensParam?: 'max_tokens' | 'max_completion_tokens';\n /** The GitHub incident this case locks in, so a reviewer sees WHY it matters. */\n readonly issue: number;\n}\n\n/**\n * The documented model-parameter incompatibilities (#4061/#4062/#4049) as a single\n * declarative, greppable source of truth. The layer-4 drift guard (#4070) asserts\n * every entry against the resolver, so the next param drift — a bumped Claude\n * threshold, an edited regex, a removed `unsupportedParameters` on a registered\n * model — fails CI instead of silently 400-ing in production. Exported so it doubles\n * as documentation and as the anchor the (deferred) provider-reality reconciliation\n * checks against. Spans BOTH the registry data path and the regex fallback path.\n */\nexport const KNOWN_PARAMETER_INCOMPATIBILITIES: readonly KnownParameterIncompatibility[] = [\n // #4061 — Claude after Opus 4.6 rejects a non-1.0 temperature with a 400 (regex fallback; unregistered concrete id).\n { modelId: 'claude-opus-4-8', param: 'temperature', issue: 4061 },\n // #4176 — Claude Fable 5 (frontier) rejects temperature; registry-encoded via `unsupportedParameters` on the in-tree entry (regex fallback also covers it: fable→5.0 > 4.6).\n { modelId: 'claude-fable-5', param: 'temperature', issue: 4176 },\n // #4062 — OpenAI reasoning families reject temperature (o-series/gpt-5 via regex fallback; codex via registry data).\n { modelId: 'o3-mini', param: 'temperature', issue: 4062 },\n { modelId: 'gpt-5', param: 'temperature', issue: 4062 },\n { modelId: 'codex-5.3', param: 'temperature', issue: 4062 },\n // #4176 — GPT-5.5 (frontier reasoning) rejects temperature and expects `max_completion_tokens`; registry-encoded, mirroring codex-5.3.\n { modelId: 'gpt-5.5', param: 'temperature', issue: 4176 },\n { modelId: 'gpt-5.5', maxTokensParam: 'max_completion_tokens', issue: 4176 },\n // #4049 — OpenAI reasoning models expect `max_completion_tokens`, not `max_tokens` (codex via registry; o-series via fallback).\n { modelId: 'codex-5.3', maxTokensParam: 'max_completion_tokens', issue: 4049 },\n { modelId: 'o3-mini', maxTokensParam: 'max_completion_tokens', issue: 4049 },\n];\n","/**\n * nexus-agents/config — model `temperature` support (#4061, #4062).\n *\n * Some models reject a custom `temperature` with a hard 400, so both adapters\n * must OMIT the param for them. Two families:\n *\n * 1. Anthropic Claude AFTER Opus 4.6 (#4061). Per the installed `@anthropic-ai/sdk`\n * (messages.d.ts): \"Models released after Claude Opus 4.6 do not support setting\n * temperature. A value of 1.0 will be accepted for backwards compatibility, all\n * other values will be rejected with a 400 error.\"\n * 2. OpenAI REASONING models (#4062): the o-series (o1/o3/o3-mini/o4-mini) reject\n * `temperature` outright (\"Unsupported parameter\"), and the GPT-5 family accepts\n * only the default (\"Only the default (1) value is supported\") — except the\n * non-reasoning `gpt-5-chat` variant. This repo routes codex-5.3→gpt-5.4,\n * codex-5.2→gpt-5.2-codex, codex-5.1-mini→o3-mini, so gateway voters at the\n * default 0.3 400 on all of them.\n *\n * {@link temperatureUnsupportedForModel} is the single source of truth both the\n * native Claude adapter and the OpenAI-compatible gateway adapter consult before\n * forwarding `temperature`. When it returns true the adapter OMITS the param\n * (value 1.0 is the API default, so omitting is equivalent). It returns FALSE for\n * every model NOT known to reject temperature (gpt-4o, gpt-4, gemini, …), biasing\n * AGAINST false-positive stripping — a false negative is a 400, a false positive\n * only loses the consistency setting.\n *\n * As of #4067 the predicate is a THIN SHIM over the data-driven resolver in\n * `model-parameter-support.ts` (registry `unsupportedParameters` first, then the\n * same regex fallback that used to live here). The three adapter call sites and\n * the `warnTemperatureDropped` / `_resetTemperatureWarnings` surface are unchanged.\n *\n * @module config/temperature-support\n */\n\nimport { createLogger } from '../core/index.js';\nimport { modelSupportsParameter } from './model-parameter-support.js';\n\nconst logger = createLogger({ component: 'temperature-support' });\n\n/**\n * Models we have ALREADY warned about dropping `temperature` for, so the loud\n * warning fires once per model per process rather than on every request (a voter\n * panel makes many calls). Repeats log at debug.\n */\nconst warnedDroppedModels = new Set<string>();\n\n/**\n * FAIL LOUDLY when `temperature` is omitted because the target model rejects it\n * (#4066 layer 3). `temperature` is a BEHAVIORAL parameter — silently dropping it\n * means a determinism/consistency setting is ignored with no signal (e.g. 0.0 and\n * 0.7 yield identical output), the canonical footgun. So the first drop per model\n * is a WARN that says the param was omitted and the request runs at the provider\n * default; subsequent drops for that model log at debug to avoid per-call spam.\n */\nexport function warnTemperatureDropped(modelId: string): void {\n if (warnedDroppedModels.has(modelId)) {\n logger.debug('Omitted unsupported temperature (already warned for this model)', {\n modelId,\n parameter: 'temperature',\n });\n return;\n }\n warnedDroppedModels.add(modelId);\n logger.warn(\n `Model \"${modelId}\" does not support a custom \\`temperature\\` (the provider rejects ` +\n `non-default values with a 400). nexus-agents omitted it; the request runs at the ` +\n `provider default. Any determinism/consistency you expected from temperature has NO ` +\n `effect on this model.`,\n { modelId, parameter: 'temperature', severity: 'behavioral' }\n );\n}\n\n/** Test seam: clear the once-per-model warning dedupe set. */\nexport function _resetTemperatureWarnings(): void {\n warnedDroppedModels.clear();\n}\n\n/**\n * Whether `modelId` REJECTS a non-default `temperature` and the param must be\n * dropped before the request is sent. Single source of truth for both adapters.\n *\n * Thin shim over {@link modelSupportsParameter} (#4067): registry\n * `unsupportedParameters` data wins, else the regex fallback (Claude after Opus\n * 4.6 #4061; OpenAI o-series / GPT-5 family / codex #4062; everything else\n * `false`). Biased AGAINST false positives: a missed model is a 400 outage, a\n * wrongly matched one only loses the consistency setting. Robust to gateway id\n * variants — provider prefixes (`anthropic/…`, `openai/…`), `-`/`_` separators,\n * dated suffixes.\n */\nexport function temperatureUnsupportedForModel(modelId: string): boolean {\n return !modelSupportsParameter(modelId, 'temperature');\n}\n","/**\n * nexus-agents/adapters — shared optional-parameter decision seam (#4068, epic #4066 layer 2).\n *\n * The claude / openai / sdk adapters each inlined an IDENTICAL temperature\n * drop-decision before forwarding a request: consult the layer-1 capability\n * resolver, drop `temperature` (and warn once) when the model rejects it, else\n * pass it through. This module is the single seam for that decision so the three\n * call sites stop duplicating it.\n *\n * It returns DECISION METADATA, not a provider-neutral params dict: each adapter\n * still owns its own wire shape (field names + nesting for stop/tools/\n * response_format/max-tokens), so the seam only decides the shared bit\n * (temperature) and records what it dropped/transformed for the layer-3 telemetry\n * child (#4069). Behavior-preserving by construction.\n *\n * @module adapters/optional-params\n */\n\nimport { modelSupportsParameter } from '../config/model-parameter-support.js';\nimport { warnTemperatureDropped } from '../config/temperature-support.js';\nimport type { CompletionRequest } from '../core/index.js';\n\n/**\n * Severity of a dropped param (#4069, epic #4066 layer 3). Behavioral params\n * (temperature/seed/top_p) affect determinism/output — dropping one silently is\n * the canonical footgun, so it is surfaced LOUDLY (WARN). Everything else is\n * cosmetic — dropping it is quiet (DEBUG).\n */\nexport type ParamSeverity = 'behavioral' | 'cosmetic';\n\n/** Params whose silent drop changes model output/determinism — loud when dropped. */\nconst BEHAVIORAL_PARAMS = new Set<string>(['temperature', 'seed', 'top_p']);\n\n/** Classify a request param as behavioral (loud-on-drop) or cosmetic (quiet). */\nexport function parameterSeverity(param: string): ParamSeverity {\n return BEHAVIORAL_PARAMS.has(param) ? 'behavioral' : 'cosmetic';\n}\n\n/** A request param the seam dropped, with why (feeds the layer-3 telemetry child #4069). */\nexport interface DroppedParam {\n readonly param: string;\n readonly reason: string;\n /** Behavioral (loud) vs cosmetic (quiet) — see {@link parameterSeverity}. */\n readonly severity: ParamSeverity;\n}\n\n/**\n * Would-have-self-healed counter (#4069, epic #4066 layer 3). Keyed\n * `${modelId}:${param}`. Counts every PROACTIVE drop (this module) AND every\n * REACTIVE param-naming 400 the adapter classifies as MODEL_PARAMETER_UNSUPPORTED\n * (base-adapter). Both are exactly the events the reactive self-heal path (#4071)\n * would catch, so this single counter measures how often #4071 would have fired.\n */\nconst wouldHaveSelfHealed = new Map<string, number>();\n\n/** Record one would-have-self-healed event for `modelId`'s `param` (#4069). */\nexport function recordWouldHaveSelfHealed(modelId: string, param: string): void {\n const key = `${modelId}:${param}`;\n wouldHaveSelfHealed.set(key, (wouldHaveSelfHealed.get(key) ?? 0) + 1);\n}\n\n/** Snapshot of the would-have-self-healed counts (defensive copy). */\nexport function getWouldHaveSelfHealedCounts(): ReadonlyMap<string, number> {\n return new Map(wouldHaveSelfHealed);\n}\n\n/** Test seam: clear the would-have-self-healed counter. */\nexport function _resetWouldHaveSelfHealed(): void {\n wouldHaveSelfHealed.clear();\n}\n\n/** A request param the seam transformed (name/value). Reserved for #4069 / a later max-tokens increment; empty today. */\nexport interface TransformedParam {\n readonly param: string;\n readonly from: unknown;\n readonly to: unknown;\n}\n\n/** The provider-NEUTRAL decision the adapters apply to their own wire shape. */\nexport interface OptionalParamPlan {\n /** Present iff temperature should be sent (the adapter sets it under its own field name — all 3 use `temperature`). Absent = drop it. */\n readonly temperature?: number;\n readonly dropped: readonly DroppedParam[];\n readonly transformed: readonly TransformedParam[];\n}\n\n/**\n * Centralizes the temperature drop-decision shared by the claude/openai/sdk adapters\n * (#4068, epic #4066 layer 2). Consults the layer-1 resolver; when the model rejects\n * temperature it is dropped (and `warnTemperatureDropped` fires, exactly as before) and\n * recorded in `dropped` for the layer-3 telemetry child (#4069). Behavior-preserving:\n * the adapters previously inlined this identically. Returns DECISION METADATA, not a\n * neutral params dict (each adapter still owns its wire names/nesting for stop/tools/etc).\n */\nexport function planOptionalParams(request: CompletionRequest, modelId: string): OptionalParamPlan {\n const dropped: DroppedParam[] = [];\n let temperature: number | undefined;\n if (request.temperature !== undefined) {\n if (modelSupportsParameter(modelId, 'temperature')) {\n temperature = request.temperature;\n } else {\n // ONE loud line per drop, deduped: warnTemperatureDropped is the consolidated\n // behavioral WARN (severity:'behavioral'), once per model then debug (#4066\n // layer 3). temperature is the only param dropped today and it is behavioral,\n // so there is no second emit — adding one would double-warn.\n warnTemperatureDropped(modelId);\n // Record the proactive drop: every time the reactive self-heal path (#4071)\n // would have fired on a temperature-rejecting 400.\n recordWouldHaveSelfHealed(modelId, 'temperature');\n dropped.push({\n param: 'temperature',\n reason: `model_rejects:${modelId}`,\n severity: parameterSeverity('temperature'),\n });\n }\n }\n return { ...(temperature !== undefined ? { temperature } : {}), dropped, transformed: [] };\n}\n","/**\n * nexus-agents/adapters - Base Adapter\n *\n * Abstract base class that all model adapters extend.\n * Provides common functionality for token counting, logging, error transformation,\n * and capability checking.\n */\n\nimport type {\n Result,\n IModelAdapter,\n CompletionRequest,\n CompletionResponse,\n StreamChunk,\n ILogger,\n ModelCapability,\n} from '../core/index.js';\nimport { getErrorMessage } from '../core/index.js';\nimport { isRateLimitLikeError } from './rate-limit-detector.js';\nimport { recordWouldHaveSelfHealed } from './optional-params.js';\n\nimport {\n ok,\n err,\n ConfigError,\n ModelError,\n ErrorCode,\n createLogger,\n getTokenEstimator,\n type NexusErrorOptions,\n} from '../core/index.js';\n\n/**\n * Configuration options for BaseAdapter.\n */\nexport interface BaseAdapterConfig {\n /** Provider identifier (e.g., 'anthropic', 'openai') */\n providerId: string;\n /** Model identifier (e.g., 'claude-sonnet-4', 'gpt-4o') */\n modelId: string;\n /** Capabilities this model supports */\n capabilities: readonly ModelCapability[];\n /** Optional custom logger */\n logger?: ILogger;\n /** API key for authentication (optional, may come from environment) */\n apiKey?: string;\n /** Base URL for the API (optional, uses provider default) */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Maximum number of retries for failed requests */\n maxRetries?: number;\n}\n\n/**\n * Extended ModelError that supports specific error codes.\n *\n * While ModelError from core uses MODEL_ERROR by default, this subclass\n * allows adapters to specify more granular error codes like\n * MODEL_RATE_LIMITED, MODEL_TIMEOUT, etc.\n *\n * Extends ModelError so `instanceof ModelError` checks pass naturally\n * without requiring `as unknown as ModelError` casts.\n */\nexport class AdapterModelError extends ModelError {\n constructor(message: string, options: NexusErrorOptions) {\n super(message, options);\n this.name = 'ModelError';\n }\n}\n\n// ============================================================================\n// API Key Validation Helpers (#1446 — DRY extraction)\n// ============================================================================\n\n/**\n * Returns true if the given API key is missing or blank.\n */\nexport function isApiKeyMissing(apiKey: string | undefined): boolean {\n return apiKey === undefined || apiKey === '' || apiKey.trim() === '';\n}\n\n/**\n * Validates API key presence in constructor — throws ConfigError if missing.\n * Use in adapter constructors where throwing is appropriate.\n */\nexport function requireApiKey(\n apiKey: string | undefined,\n providerName: string,\n modelId: string\n): void {\n if (isApiKeyMissing(apiKey)) {\n throw new ConfigError(`${providerName} API key is required`, {\n context: { providerId: providerName.toLowerCase(), modelId },\n });\n }\n}\n\n/**\n * Validates API key presence — returns Result for validate-style methods.\n * Use in adapter validateConfig() methods that return Result.\n */\nexport function validateApiKeyPresence(\n apiKey: string | undefined,\n providerId: string,\n modelId: string\n): Result<void, ConfigError> {\n if (isApiKeyMissing(apiKey)) {\n return err(\n new ConfigError(`${providerId} API key is required`, {\n context: { providerId, modelId },\n })\n );\n }\n return ok(undefined);\n}\n\n/**\n * Abstract base class for model adapters.\n *\n * Provides default implementations for common adapter functionality while\n * leaving the core API interaction methods abstract for provider-specific\n * implementations.\n *\n * @example\n * ```typescript\n * class ClaudeAdapter extends BaseAdapter {\n * constructor(config: ClaudeAdapterConfig) {\n * super({\n * providerId: 'anthropic',\n * modelId: config.modelId,\n * capabilities: [ModelCapability.COMPLETION, ModelCapability.STREAMING],\n * apiKey: config.apiKey,\n * });\n * }\n *\n * async complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>> {\n * this.logRequest(request);\n * // Provider-specific implementation...\n * }\n *\n * async *stream(request: CompletionRequest): AsyncIterable<StreamChunk> {\n * this.logRequest(request);\n * // Provider-specific streaming implementation...\n * }\n * }\n * ```\n */\nexport abstract class BaseAdapter implements IModelAdapter {\n readonly providerId: string;\n readonly modelId: string;\n readonly capabilities: readonly ModelCapability[];\n\n /** Logger for request/response logging */\n protected readonly logger: ILogger;\n\n /** Configuration for the adapter */\n protected readonly config: BaseAdapterConfig;\n\n /**\n * Creates a new BaseAdapter instance.\n *\n * @param config - Adapter configuration\n */\n constructor(config: BaseAdapterConfig) {\n this.providerId = config.providerId;\n this.modelId = config.modelId;\n this.capabilities = config.capabilities;\n this.config = config;\n this.logger =\n config.logger ??\n createLogger({\n adapter: config.providerId,\n model: config.modelId,\n });\n }\n\n /**\n * Send a completion request to the model.\n * Must be implemented by concrete adapter classes.\n *\n * @param request - The completion request\n * @returns Result with response or ModelError\n */\n abstract complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>>;\n\n /**\n * Stream a completion request from the model.\n * Must be implemented by concrete adapter classes.\n *\n * @param request - The completion request\n * @yields StreamChunk objects as they arrive\n */\n abstract stream(request: CompletionRequest): AsyncIterable<StreamChunk>;\n\n /**\n * Count tokens in text using the unified TokenEstimator.\n *\n * This provides a reasonable estimate for most use cases.\n * Concrete adapters may override this with provider-specific tokenizers.\n *\n * @param text - Text to count tokens for\n * @returns Approximate token count\n */\n countTokens(text: string): Promise<number> {\n return Promise.resolve(getTokenEstimator().estimateText(text));\n }\n\n /**\n * Validate adapter configuration.\n *\n * Checks that required configuration fields are present and valid.\n * Concrete adapters may override to add provider-specific validation.\n *\n * @returns Ok if valid, ConfigError if invalid\n */\n validateConfig(): Result<void, ConfigError> {\n const errors: string[] = [];\n\n if (!this.providerId || this.providerId.trim() === '') {\n errors.push('Provider ID is required');\n }\n\n if (!this.modelId || this.modelId.trim() === '') {\n errors.push('Model ID is required');\n }\n\n if (this.config.timeout !== undefined && this.config.timeout <= 0) {\n errors.push('Timeout must be positive');\n }\n\n if (this.config.maxRetries !== undefined && this.config.maxRetries < 0) {\n errors.push('Max retries cannot be negative');\n }\n\n if (errors.length > 0) {\n return err(\n new ConfigError(`Invalid adapter configuration: ${errors.join('; ')}`, {\n context: {\n providerId: this.providerId,\n modelId: this.modelId,\n errors,\n },\n })\n );\n }\n\n return ok(undefined);\n }\n\n /**\n * Check if this adapter supports a specific capability.\n *\n * @param capability - The capability to check for\n * @returns True if the capability is supported\n */\n hasCapability(capability: ModelCapability): boolean {\n return this.capabilities.includes(capability);\n }\n\n /**\n * Log details about an outgoing request.\n * Sanitizes sensitive information before logging.\n *\n * @param request - The completion request to log\n */\n protected logRequest(request: CompletionRequest): void {\n const messageCount = request.messages.length;\n const hasTools = request.tools !== undefined && request.tools.length > 0;\n const toolCount = request.tools?.length ?? 0;\n\n this.logger.debug('Sending completion request', {\n messageCount,\n hasSystemPrompt: request.systemPrompt !== undefined,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n hasTools,\n toolCount,\n responseFormat: request.responseFormat?.type,\n stopSequences: request.stop?.length ?? 0,\n });\n }\n\n /**\n * Log details about a received response.\n *\n * @param response - The completion response to log\n */\n protected logResponse(response: CompletionResponse): void {\n this.logger.debug('Received completion response', {\n contentBlocks: response.content.length,\n stopReason: response.stopReason,\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n model: response.model,\n });\n }\n\n /**\n * Transform a provider-specific error into a standardized ModelError.\n *\n * Maps common error patterns to appropriate error codes:\n * - Rate limiting (429, quota exceeded)\n * - Timeouts (ETIMEDOUT, ESOCKETTIMEDOUT)\n * - Authentication (401, 403)\n * - Model unavailable (503, 502)\n *\n * @param error - The original error from the provider\n * @returns A standardized ModelError\n */\n protected transformError(error: unknown): ModelError {\n if (error instanceof ModelError) {\n return error;\n }\n\n const errorMessage = getErrorMessage(error);\n const errorCode = this.determineErrorCode(error);\n\n // #4069: a param-naming 400 carries the offending param name in context, and\n // counts as a would-have-self-healed event (the reactive #4071 path would catch\n // exactly this 400). Only set for MODEL_PARAMETER_UNSUPPORTED — all other codes\n // are unchanged.\n const param =\n errorCode === ErrorCode.MODEL_PARAMETER_UNSUPPORTED\n ? this.extractErrorParam(error)\n : undefined;\n if (param !== undefined) {\n recordWouldHaveSelfHealed(this.modelId, param);\n }\n\n const modelError = this.createModelError(errorMessage, errorCode, error, param);\n\n this.logger.error('Model adapter error', modelError, {\n errorCode,\n providerId: this.providerId,\n modelId: this.modelId,\n });\n\n return modelError;\n }\n\n /**\n * Create a ModelError with appropriate error code.\n */\n private createModelError(\n message: string,\n errorCode: (typeof ErrorCode)[keyof typeof ErrorCode],\n originalError: unknown,\n param?: string\n ): ModelError {\n const fullMessage = `${this.providerId}/${this.modelId}: ${message}`;\n\n // Build options object conditionally to satisfy exactOptionalPropertyTypes\n const context: Record<string, unknown> = {\n providerId: this.providerId,\n modelId: this.modelId,\n };\n // #4069: surface the offending param name for a param-naming 400 so callers\n // and the reactive self-heal path (#4071) can read which param to retry without.\n if (param !== undefined) {\n context.param = param;\n }\n const options: NexusErrorOptions = {\n code: errorCode,\n context,\n };\n\n // Only set cause if originalError is an Error\n if (originalError instanceof Error) {\n options.cause = originalError;\n }\n\n // AdapterModelError extends ModelError — no cast needed\n return new AdapterModelError(fullMessage, options);\n }\n\n /**\n * Determine the appropriate error code based on error characteristics.\n */\n private determineErrorCode(error: unknown): (typeof ErrorCode)[keyof typeof ErrorCode] {\n if (!(error instanceof Error)) {\n return ErrorCode.MODEL_ERROR;\n }\n\n const message = error.message.toLowerCase();\n const errorObj = error as { status?: number; code?: string };\n\n // Check for rate limiting (canonical detection from rate-limit-detector)\n if (isRateLimitLikeError(error)) {\n return ErrorCode.MODEL_RATE_LIMITED;\n }\n\n // Check for timeout\n if (this.isTimeoutError(message, errorObj)) {\n return ErrorCode.MODEL_TIMEOUT;\n }\n\n // Check for model-not-found (#2540 PR 8) — distinct from transient\n // MODEL_UNAVAILABLE (502/503). 404 + vendor-specific phrases (\"model\n // not found\", \"deprecated\", \"no such model\") all mean: this id is\n // gone, retry won't help, route to a different one.\n if (this.isModelNotFoundError(message, errorObj)) {\n return ErrorCode.MODEL_NOT_FOUND;\n }\n\n // Check for model unavailable\n if (this.isUnavailableError(message, errorObj)) {\n return ErrorCode.MODEL_UNAVAILABLE;\n }\n\n // Check for a param-naming 400 (#4069): a 400 that identifies an unsupported\n // parameter by name. Distinct from generic MODEL_ERROR — non-retryable, and the\n // param name is threaded into context. Only changes 400s that NAME a param; a\n // 400 with no param, and every non-400, stay MODEL_ERROR.\n if (this.extractErrorParam(error) !== undefined) {\n return ErrorCode.MODEL_PARAMETER_UNSUPPORTED;\n }\n\n return ErrorCode.MODEL_ERROR;\n }\n\n /**\n * Extract the offending parameter name from a param-naming 400 (#4069).\n *\n * Returns the param only when the error is a 400 AND carries a non-empty `param`\n * field (the OpenAI SDK / OpenAI-compatible gateways set this on a rejected\n * parameter; the OpenAI adapter threads it onto the classification probe).\n * Returns undefined otherwise, so non-400s and param-less 400s are untouched.\n */\n private extractErrorParam(error: unknown): string | undefined {\n if (!(error instanceof Error)) {\n return undefined;\n }\n const errorObj = error as { status?: number; param?: unknown };\n if (errorObj.status !== 400) {\n return undefined;\n }\n return typeof errorObj.param === 'string' && errorObj.param !== '' ? errorObj.param : undefined;\n }\n\n /**\n * (#2540 PR 8) Detect model-retirement errors. Distinct from transient\n * 502/503: 404 + vendor messages indicating the model id is gone.\n */\n private isModelNotFoundError(\n message: string,\n errorObj: { status?: number; code?: string }\n ): boolean {\n if (errorObj.status === 404) return true;\n const patterns = [\n 'model not found',\n 'model_not_found',\n 'no such model',\n 'model is deprecated',\n 'model has been deprecated',\n 'model is no longer available',\n ];\n return patterns.some((p) => message.includes(p));\n }\n\n /**\n * Check if error indicates a timeout.\n */\n private isTimeoutError(message: string, errorObj: { status?: number; code?: string }): boolean {\n const timeoutPatterns = ['timeout', 'etimedout', 'esockettimedout'];\n return (\n errorObj.code === 'ETIMEDOUT' ||\n errorObj.code === 'ESOCKETTIMEDOUT' ||\n timeoutPatterns.some((pattern) => message.includes(pattern))\n );\n }\n\n /**\n * Check if error indicates model unavailability.\n */\n private isUnavailableError(\n message: string,\n errorObj: { status?: number; code?: string }\n ): boolean {\n const unavailablePatterns = ['unavailable', 'service unavailable', 'overloaded'];\n return (\n errorObj.status === 502 ||\n errorObj.status === 503 ||\n unavailablePatterns.some((pattern) => message.includes(pattern))\n );\n }\n}\n","/**\n * nexus-agents/adapters - Streaming Types and Core Utilities\n *\n * Shared types, errors, and core streaming primitives used by both\n * streaming.ts and stream-operators.ts to avoid circular dependencies.\n */\n\nimport { type Result, ok, err } from '../core/index.js';\nimport { NexusError, ErrorCode } from '../core/index.js';\n\n/**\n * Error thrown when a stream operation fails.\n */\nexport class StreamError extends NexusError {\n constructor(message: string, options?: { cause?: Error; context?: Record<string, unknown> }) {\n super(message, { code: ErrorCode.INTERNAL_ERROR, ...options });\n this.name = 'StreamError';\n }\n}\n\n/**\n * Error thrown when a stream is cancelled.\n */\nexport class StreamCancelledError extends NexusError {\n constructor(reason?: string) {\n super(reason ?? 'Stream was cancelled', { code: ErrorCode.INTERNAL_ERROR });\n this.name = 'StreamCancelledError';\n }\n}\n\n/**\n * State of a stream controller.\n */\nexport type StreamState = 'idle' | 'streaming' | 'paused' | 'cancelled' | 'completed' | 'error';\n\n/**\n * Options for creating a stream.\n */\nexport interface CreateStreamOptions {\n /** AbortSignal for cancellation support */\n signal?: AbortSignal;\n /** Maximum buffer size for backpressure (default: 100) */\n maxBufferSize?: number;\n}\n\n/**\n * Controller for managing stream lifecycle.\n * Provides push/complete/error methods and cancellation support.\n */\nexport class StreamController<T> {\n private readonly chunks: T[] = [];\n private readonly waiters: Array<{\n resolve: (result: IteratorResult<T, void>) => void;\n reject: (error: Error) => void;\n }> = [];\n\n private _state: StreamState = 'idle';\n private _error: Error | undefined;\n private readonly maxBufferSize: number;\n private readonly abortHandler: (() => void) | undefined;\n private readonly abortSignal: AbortSignal | undefined;\n\n /**\n * Creates a new StreamController.\n * @param options - Stream creation options\n */\n constructor(options: CreateStreamOptions = {}) {\n this.maxBufferSize = options.maxBufferSize ?? 100;\n\n if (options.signal) {\n this.abortSignal = options.signal;\n this.abortHandler = (): void => {\n this.cancel('AbortSignal triggered');\n };\n options.signal.addEventListener('abort', this.abortHandler);\n }\n }\n\n /**\n * Current state of the stream.\n */\n get state(): StreamState {\n return this._state;\n }\n\n /**\n * Whether the stream is still active (can receive chunks).\n */\n get isActive(): boolean {\n return this._state === 'idle' || this._state === 'streaming' || this._state === 'paused';\n }\n\n /**\n * Current buffer size.\n */\n get bufferSize(): number {\n return this.chunks.length;\n }\n\n /**\n * Push a chunk to the stream.\n * @param chunk - The chunk to push\n * @returns Result indicating success or backpressure\n */\n push(chunk: T): Result<void, StreamError> {\n if (!this.isActive) {\n return err(new StreamError(`Cannot push to stream in state: ${this._state}`));\n }\n\n if (this._state === 'idle') {\n this._state = 'streaming';\n }\n\n // If there's a waiting consumer, deliver directly\n const waiter = this.waiters.shift();\n if (waiter) {\n waiter.resolve({ done: false, value: chunk });\n return ok(undefined);\n }\n\n // Check backpressure\n if (this.chunks.length >= this.maxBufferSize) {\n this._state = 'paused';\n return err(\n new StreamError('Buffer full - backpressure applied', {\n context: { bufferSize: this.chunks.length, maxBufferSize: this.maxBufferSize },\n })\n );\n }\n\n this.chunks.push(chunk);\n return ok(undefined);\n }\n\n /**\n * Complete the stream successfully.\n */\n complete(): void {\n if (!this.isActive) {\n return;\n }\n\n this._state = 'completed';\n this.removeAbortListener();\n this.resolveAllWaiters();\n }\n\n /**\n * Complete the stream with an error.\n * @param error - The error that occurred\n */\n error(error: Error): void {\n if (!this.isActive) {\n return;\n }\n\n this._state = 'error';\n this._error = error;\n this.removeAbortListener();\n this.rejectAllWaiters(error);\n }\n\n /**\n * Cancel the stream.\n * @param reason - Optional reason for cancellation\n */\n cancel(reason?: string): void {\n if (!this.isActive) {\n return;\n }\n\n this._state = 'cancelled';\n this._error = new StreamCancelledError(reason);\n this.removeAbortListener();\n this.rejectAllWaiters(this._error);\n }\n\n /**\n * Get the AsyncIterable for consuming the stream.\n */\n getIterable(): AsyncIterable<T> {\n // Store reference to controller methods for closure\n const nextChunk = (): Promise<IteratorResult<T, void>> => this.nextChunk();\n const cancel = (reason: string): void => {\n this.cancel(reason);\n };\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n async next(): Promise<IteratorResult<T, void>> {\n return nextChunk();\n },\n return(): Promise<IteratorResult<T, void>> {\n cancel('Iterator returned');\n return Promise.resolve({ done: true, value: undefined });\n },\n };\n },\n };\n }\n\n private async nextChunk(): Promise<IteratorResult<T, void>> {\n // If we have buffered chunks, return one\n const chunk = this.chunks.shift();\n if (chunk !== undefined) {\n // Resume if we were paused and buffer is now below threshold\n if (this._state === 'paused' && this.chunks.length < this.maxBufferSize / 2) {\n this._state = 'streaming';\n }\n return { done: false, value: chunk };\n }\n\n // Check terminal states\n if (this._state === 'completed') {\n return { done: true, value: undefined };\n }\n\n if (this._state === 'cancelled' || this._state === 'error') {\n throw this._error ?? new StreamCancelledError();\n }\n\n // Wait for next chunk\n return new Promise((resolve, reject) => {\n this.waiters.push({ resolve, reject });\n });\n }\n\n private removeAbortListener(): void {\n if (this.abortSignal && this.abortHandler) {\n this.abortSignal.removeEventListener('abort', this.abortHandler);\n }\n }\n\n private resolveAllWaiters(): void {\n for (const waiter of this.waiters) {\n waiter.resolve({ done: true, value: undefined });\n }\n this.waiters.length = 0;\n }\n\n private rejectAllWaiters(error: Error): void {\n for (const waiter of this.waiters) {\n waiter.reject(error);\n }\n this.waiters.length = 0;\n }\n}\n\n/**\n * Creates a controllable stream.\n * @param options - Stream creation options\n * @returns Tuple of [controller, iterable]\n */\nexport function createStream<T>(\n options: CreateStreamOptions = {}\n): [StreamController<T>, AsyncIterable<T>] {\n const controller = new StreamController<T>(options);\n return [controller, controller.getIterable()];\n}\n","/**\n * nexus-agents/adapters - Stream Operators Helpers\n *\n * Helper functions for stream operations extracted for maintainability.\n */\n\nimport { type Result, ok, err } from '../core/index.js';\nimport { StreamError, StreamCancelledError } from './streaming-types.js';\n\n/**\n * Takes the first N chunks from a stream.\n * @param stream - The source stream\n * @param count - Number of chunks to take\n * @param options - Options including optional AbortSignal\n * @returns Stream of first N chunks\n */\nexport async function* take<T>(\n stream: AsyncIterable<T>,\n count: number,\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n if (count <= 0) {\n return;\n }\n\n let taken = 0;\n\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('take aborted');\n }\n\n yield chunk;\n taken++;\n\n if (taken >= count) {\n return;\n }\n }\n}\n\n/**\n * Skips the first N chunks from a stream.\n * @param stream - The source stream\n * @param count - Number of chunks to skip\n * @param options - Options including optional AbortSignal\n * @returns Stream with first N chunks skipped\n */\nexport async function* skip<T>(\n stream: AsyncIterable<T>,\n count: number,\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n let skipped = 0;\n\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('skip aborted');\n }\n\n if (skipped < count) {\n skipped++;\n continue;\n }\n\n yield chunk;\n }\n}\n\n/**\n * Concatenates multiple streams sequentially.\n * @param streams - The streams to concatenate\n * @param options - Options including optional AbortSignal\n * @returns Concatenated stream\n */\nexport async function* concatStreams<T>(\n streams: AsyncIterable<T>[],\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n for (const stream of streams) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('concat aborted');\n }\n\n yield* stream;\n }\n}\n\n/**\n * Creates a stream from an array of values.\n * @param values - The values to stream\n * @param options - Options including optional delay between chunks\n * @returns Stream of values\n */\nexport async function* fromArray<T>(\n values: T[],\n options: { delayMs?: number; signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n for (const value of values) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('fromArray aborted');\n }\n\n if (options.delayMs !== undefined && options.delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, options.delayMs));\n }\n\n yield value;\n }\n}\n\n/**\n * Taps into a stream without modifying it (for side effects like logging).\n * @param stream - The source stream\n * @param fn - Side effect function called for each chunk\n * @param options - Options including optional AbortSignal\n * @returns Original stream unchanged\n */\nexport async function* tapStream<T>(\n stream: AsyncIterable<T>,\n fn: (chunk: T, index: number) => void | Promise<void>,\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n let index = 0;\n\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('tap aborted');\n }\n\n await fn(chunk, index);\n yield chunk;\n index++;\n }\n}\n\n/**\n * Reduces a stream to a single value.\n * @param stream - The source stream\n * @param reducer - Reducer function\n * @param initialValue - Initial accumulator value\n * @param options - Options including optional AbortSignal\n * @returns Result containing the final value or error\n */\nexport async function reduceStream<T, U>(\n stream: AsyncIterable<T>,\n reducer: (accumulator: U, chunk: T, index: number) => U | Promise<U>,\n initialValue: U,\n options: { signal?: AbortSignal } = {}\n): Promise<Result<U, StreamError>> {\n let accumulator = initialValue;\n let index = 0;\n\n try {\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n return err(new StreamError('Reduce aborted'));\n }\n\n accumulator = await reducer(accumulator, chunk, index);\n index++;\n }\n\n return ok(accumulator);\n } catch (error) {\n return err(\n new StreamError('Failed to reduce stream', {\n cause: error instanceof Error ? error : new Error(String(error)),\n })\n );\n }\n}\n","/**\n * nexus-agents/adapters - Stream Operators\n *\n * Stream transformation operators for AsyncIterables.\n * Provides filter, map, merge, concat, buffer, and other stream operations.\n */\n\nimport { TimeoutError } from '../core/index.js';\nimport {\n StreamError,\n StreamCancelledError,\n createStream,\n type CreateStreamOptions,\n} from './streaming-types.js';\n\n// Re-export helper functions for backward compatibility\nexport {\n take,\n skip,\n concatStreams,\n fromArray,\n tapStream,\n reduceStream,\n} from './stream-operators-helpers.js';\n\n/**\n * Transforms stream chunks using a mapping function.\n * @param stream - The source stream\n * @param fn - Transformation function\n * @param options - Options including optional AbortSignal\n * @returns Transformed stream\n */\nexport async function* transformStream<T, U>(\n stream: AsyncIterable<T>,\n fn: (chunk: T, index: number) => U | Promise<U>,\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<U> {\n let index = 0;\n\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('Transform aborted');\n }\n\n yield await fn(chunk, index);\n index++;\n }\n}\n\n/**\n * Merges multiple streams into a single stream.\n * Chunks are yielded as they arrive from any source.\n * @param streams - The streams to merge\n * @param options - Options including optional AbortSignal\n * @returns Merged stream\n */\nexport async function* mergeStreams<T>(\n streams: AsyncIterable<T>[],\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n if (streams.length === 0) {\n return;\n }\n\n const streamOptions: CreateStreamOptions = {};\n if (options.signal) {\n streamOptions.signal = options.signal;\n }\n const [controller, merged] = createStream<T>(streamOptions);\n let activeCount = streams.length;\n\n // Start consuming all streams in parallel\n const consumers = streams.map(async (stream, streamIndex) => {\n try {\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n break;\n }\n controller.push(chunk);\n }\n } catch (error) {\n if (error instanceof StreamCancelledError) {\n // Propagate cancellation\n controller.cancel(`Stream ${String(streamIndex)} was cancelled`);\n return;\n }\n controller.error(error instanceof Error ? error : new Error(String(error)));\n return;\n } finally {\n activeCount--;\n if (activeCount === 0) {\n controller.complete();\n }\n }\n });\n\n // Start all consumers without blocking (Issue #541)\n // Each consumer has try-catch that forwards errors to controller.error(),\n // so Promise.all should always resolve. Add defensive catch for edge cases.\n Promise.all(consumers).catch((error: unknown) => {\n // This should not happen since each consumer catches its own errors,\n // but handle it defensively to prevent silent failures.\n controller.error(error instanceof Error ? error : new StreamError(String(error)));\n });\n\n yield* merged;\n}\n\n/**\n * Takes chunks from a stream until a predicate returns true.\n * @param stream - The source stream\n * @param predicate - Function that returns true to stop taking\n * @param options - Options including whether to include the matching chunk\n * @returns Stream of chunks up to (and optionally including) the match\n */\nexport async function* takeUntil<T>(\n stream: AsyncIterable<T>,\n predicate: (chunk: T, index: number) => boolean | Promise<boolean>,\n options: { signal?: AbortSignal; inclusive?: boolean } = {}\n): AsyncIterable<T> {\n let index = 0;\n\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('takeUntil aborted');\n }\n\n const shouldStop = await predicate(chunk, index);\n\n if (shouldStop) {\n if (options.inclusive === true) {\n yield chunk;\n }\n return;\n }\n\n yield chunk;\n index++;\n }\n}\n\n/**\n * Filters stream chunks based on a predicate.\n * @param stream - The source stream\n * @param predicate - Function that returns true to keep the chunk\n * @param options - Options including optional AbortSignal\n * @returns Filtered stream\n */\nexport async function* filterStream<T>(\n stream: AsyncIterable<T>,\n predicate: (chunk: T, index: number) => boolean | Promise<boolean>,\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n let index = 0;\n\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('filter aborted');\n }\n\n if (await predicate(chunk, index)) {\n yield chunk;\n }\n\n index++;\n }\n}\n\n/**\n * Adds a timeout to a stream. If no chunk is received within the timeout,\n * the stream throws a TimeoutError.\n * @param stream - The source stream\n * @param timeoutMs - Timeout in milliseconds\n * @param options - Options including optional AbortSignal\n * @returns Stream with timeout applied\n */\nexport async function* withTimeout<T>(\n stream: AsyncIterable<T>,\n timeoutMs: number,\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T> {\n const iterator = stream[Symbol.asyncIterator]();\n\n try {\n let running = true;\n while (running) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('withTimeout aborted');\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n const result = await Promise.race([\n iterator.next().then((res) => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n return res;\n }),\n new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(\n new TimeoutError(`Stream timed out after ${String(timeoutMs)}ms`, {\n context: { timeoutMs },\n })\n );\n }, timeoutMs);\n }),\n ]);\n\n if (result.done === true) {\n running = false;\n } else {\n yield result.value;\n }\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n }\n } finally {\n // Ensure the iterator is properly closed\n if (iterator.return !== undefined) {\n await iterator.return();\n }\n }\n}\n\n/**\n * Buffers stream chunks into groups of a specified size.\n * @param stream - The source stream\n * @param size - Buffer size\n * @param options - Options including optional AbortSignal\n * @returns Stream of chunk arrays\n */\nexport async function* bufferStream<T>(\n stream: AsyncIterable<T>,\n size: number,\n options: { signal?: AbortSignal } = {}\n): AsyncIterable<T[]> {\n if (size <= 0) {\n throw new StreamError('Buffer size must be positive');\n }\n\n let buffer: T[] = [];\n\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n throw new StreamCancelledError('buffer aborted');\n }\n\n buffer.push(chunk);\n\n if (buffer.length >= size) {\n yield buffer;\n buffer = [];\n }\n }\n\n // Yield remaining chunks\n if (buffer.length > 0) {\n yield buffer;\n }\n}\n","/**\n * nexus-agents/adapters - Streaming Utilities\n *\n * AsyncIterator-based streaming utilities for model responses.\n * Provides stream creation, backpressure handling, cancellation support,\n * and chunk collection helpers.\n *\n * For stream transformation operators (map, filter, merge, etc.),\n * see ./stream-operators.ts\n */\n\nimport { type Result, ok, err } from '../core/index.js';\n\n// Re-export core streaming types and utilities from shared module\nexport {\n StreamError,\n StreamCancelledError,\n StreamController,\n createStream,\n type StreamState,\n type CreateStreamOptions,\n} from './streaming-types.js';\n\n// Import for use in this file\nimport { StreamError, StreamCancelledError } from './streaming-types.js';\n\n/**\n * Default cap on collected chunks — prevents unbounded memory growth when\n * callers forget to pass `maxChunks`. Callers that genuinely need no cap\n * must opt in explicitly with `{ maxChunks: Infinity }`. (#1913 Class F)\n */\nexport const DEFAULT_COLLECT_STREAM_MAX_CHUNKS = 100_000;\n\n/**\n * Collects all chunks from a stream into an array.\n *\n * @param stream - The stream to collect\n * @param options - Options including optional AbortSignal.\n * `maxChunks` defaults to {@link DEFAULT_COLLECT_STREAM_MAX_CHUNKS} to\n * prevent unbounded memory growth on forgotten limits. Pass\n * `Infinity` explicitly for truly unbounded collection.\n * @returns Result containing collected chunks or error\n */\nexport async function collectStream<T>(\n stream: AsyncIterable<T>,\n options: { signal?: AbortSignal; maxChunks?: number } = {}\n): Promise<Result<T[], StreamError>> {\n const chunks: T[] = [];\n const maxChunks = options.maxChunks ?? DEFAULT_COLLECT_STREAM_MAX_CHUNKS;\n\n try {\n for await (const chunk of stream) {\n if (options.signal?.aborted === true) {\n return err(new StreamError('Collection aborted'));\n }\n\n chunks.push(chunk);\n\n if (chunks.length >= maxChunks) {\n break;\n }\n }\n\n return ok(chunks);\n } catch (error) {\n if (error instanceof StreamCancelledError) {\n return err(new StreamError('Stream was cancelled during collection', { cause: error }));\n }\n return err(\n new StreamError('Failed to collect stream', {\n cause: error instanceof Error ? error : new Error(String(error)),\n })\n );\n }\n}\n\n// Re-export all stream operators for convenience\nexport {\n transformStream,\n mergeStreams,\n takeUntil,\n take,\n skip,\n filterStream,\n withTimeout,\n bufferStream,\n concatStreams,\n fromArray,\n tapStream,\n reduceStream,\n} from './stream-operators.js';\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getTimeProvider
3
- } from "./chunk-E7LG7L4O.js";
3
+ } from "./chunk-E5XTAHAS.js";
4
4
 
5
5
  // src/security/audit-trail.ts
6
6
  var MAX_EVENTS = 1e4;
@@ -205,4 +205,4 @@ export {
205
205
  createGraphAuditBridge,
206
206
  createAuditTrail
207
207
  };
208
- //# sourceMappingURL=chunk-QVIQAIOK.js.map
208
+ //# sourceMappingURL=chunk-I3RJEXY2.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createAutoAdapter
3
- } from "./chunk-QD653D5O.js";
3
+ } from "./chunk-LEMQDF4W.js";
4
4
  import {
5
5
  mapModelErrorToCategory
6
- } from "./chunk-3QIXGEY7.js";
6
+ } from "./chunk-POHORI2I.js";
7
7
  import {
8
8
  CLI_NAMES,
9
9
  CircularBuffer,
@@ -24,7 +24,7 @@ import {
24
24
  ok,
25
25
  recordRateLimitEvent,
26
26
  toRateLimitError
27
- } from "./chunk-E7LG7L4O.js";
27
+ } from "./chunk-E5XTAHAS.js";
28
28
 
29
29
  // src/agents/collaboration/event-bus-helpers.ts
30
30
  import { randomUUID } from "crypto";
@@ -1041,4 +1041,4 @@ export {
1041
1041
  getGlobalRegistry,
1042
1042
  resetGlobalRegistry
1043
1043
  };
1044
- //# sourceMappingURL=chunk-JYV5MZC6.js.map
1044
+ //# sourceMappingURL=chunk-KFWCF32D.js.map
@@ -5,24 +5,24 @@ import {
5
5
  planOptionalParams,
6
6
  requireApiKey,
7
7
  validateApiKeyPresence
8
- } from "./chunk-I6NTUVGW.js";
8
+ } from "./chunk-HUXMIDNV.js";
9
9
  import {
10
10
  CUSTOM_API_BASE_URL_ENV,
11
11
  CUSTOM_API_DEFAULT_MODEL,
12
12
  PROVIDER_ENV_KEYS,
13
13
  assertCustomApiHostResolvesPublic,
14
14
  validateCustomApiBaseUrl
15
- } from "./chunk-SHFCJJTY.js";
15
+ } from "./chunk-FKXR4ELM.js";
16
16
  import {
17
17
  CliCircuitBreaker,
18
18
  DEFAULT_CIRCUIT_BREAKER_CONFIG
19
- } from "./chunk-3QIXGEY7.js";
19
+ } from "./chunk-POHORI2I.js";
20
20
  import {
21
21
  getAvailabilityCache
22
- } from "./chunk-RU336IEH.js";
22
+ } from "./chunk-WVKEKRZZ.js";
23
23
  import {
24
24
  generateHyphenId
25
- } from "./chunk-WRISLYLK.js";
25
+ } from "./chunk-7ABXSM2X.js";
26
26
  import {
27
27
  CLI_SUBPROCESS_TIMEOUTS,
28
28
  CLI_TIMEOUTS,
@@ -58,7 +58,7 @@ import {
58
58
  loadModelsDevSnapshot,
59
59
  ok,
60
60
  resolveCliAlias
61
- } from "./chunk-E7LG7L4O.js";
61
+ } from "./chunk-E5XTAHAS.js";
62
62
 
63
63
  // src/cli-adapters/cli-to-model-adapter.ts
64
64
  var CliToModelAdapter = class {
@@ -4867,4 +4867,4 @@ export {
4867
4867
  SdkAdapter,
4868
4868
  createAutoAdapter
4869
4869
  };
4870
- //# sourceMappingURL=chunk-QD653D5O.js.map
4870
+ //# sourceMappingURL=chunk-LEMQDF4W.js.map
@@ -2,7 +2,7 @@ import {
2
2
  createLogger,
3
3
  err,
4
4
  ok
5
- } from "./chunk-E7LG7L4O.js";
5
+ } from "./chunk-E5XTAHAS.js";
6
6
 
7
7
  // src/scm/token-resolver.ts
8
8
  import { execFile } from "child_process";
@@ -87,4 +87,4 @@ export {
87
87
  hasToken,
88
88
  getTokenEnvVars
89
89
  };
90
- //# sourceMappingURL=chunk-Q6EGZKLE.js.map
90
+ //# sourceMappingURL=chunk-MMPZLMSH.js.map
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-6T3EPABN.js";
6
6
  import {
7
7
  SessionMemory
8
- } from "./chunk-XLEZBTQG.js";
8
+ } from "./chunk-SDJQ2H7V.js";
9
9
  import {
10
10
  StatsOnlyAdapter,
11
11
  ensureSharedMemoryRegistry
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-KSQSWEFH.js";
16
16
  import {
17
17
  generateId
18
- } from "./chunk-WRISLYLK.js";
18
+ } from "./chunk-7ABXSM2X.js";
19
19
  import {
20
20
  ErrorCode,
21
21
  NexusError,
@@ -28,7 +28,7 @@ import {
28
28
  getTimeProvider,
29
29
  ok,
30
30
  setSharedMobiMemDbPathResolver
31
- } from "./chunk-E7LG7L4O.js";
31
+ } from "./chunk-E5XTAHAS.js";
32
32
  import {
33
33
  nexusDataPath
34
34
  } from "./chunk-DHVMSIT5.js";
@@ -5552,4 +5552,4 @@ export {
5552
5552
  reinitializeMemoryBackends,
5553
5553
  ToolMemoryManager
5554
5554
  };
5555
- //# sourceMappingURL=chunk-WP6UBBNJ.js.map
5555
+ //# sourceMappingURL=chunk-MONR3CEL.js.map