nexus-agents 10.1.0 → 10.2.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 (145) hide show
  1. package/dist/{ast-rule-runner-AAOBENF2.js → ast-rule-runner-RI7ZJ4ZI.js} +3 -3
  2. package/dist/{child-mcp-config-FRWGQIHP.js → child-mcp-config-73BX4OTR.js} +2 -2
  3. package/dist/{chunk-NUXSGWDS.js → chunk-23QA6GQD.js} +5 -5
  4. package/dist/{chunk-EGUISJBB.js → chunk-2DYCHHWW.js} +4 -4
  5. package/dist/{chunk-TLITBKMZ.js → chunk-2TA6KTRF.js} +15 -15
  6. package/dist/{chunk-YHY7GMAL.js → chunk-4JJI34RV.js} +2 -2
  7. package/dist/{chunk-KPGWNBDA.js → chunk-7EV3QAKO.js} +2 -2
  8. package/dist/{chunk-SCQ5YAYO.js → chunk-D6E3LJGP.js} +4 -4
  9. package/dist/{chunk-XYYXVJSO.js → chunk-EJ5EBTAV.js} +2 -2
  10. package/dist/{chunk-BJLP4E6Q.js → chunk-FNHVTDHZ.js} +3 -3
  11. package/dist/{chunk-VGCRYAEH.js → chunk-FWQSOPBA.js} +4 -4
  12. package/dist/{chunk-RBFHY2LF.js → chunk-GAX75XCV.js} +2 -2
  13. package/dist/{chunk-O46IOND3.js → chunk-GX5ZHZR2.js} +7 -7
  14. package/dist/{chunk-33C22IY4.js → chunk-J44RKRGQ.js} +3 -3
  15. package/dist/{chunk-L4P4A7Z2.js → chunk-JGY5HMWI.js} +2 -2
  16. package/dist/{chunk-WCHN7B2Q.js → chunk-JUUGLXSN.js} +8 -10
  17. package/dist/{chunk-WCHN7B2Q.js.map → chunk-JUUGLXSN.js.map} +1 -1
  18. package/dist/{chunk-BK6Q3VQK.js → chunk-KASBBKAQ.js} +2 -2
  19. package/dist/chunk-KASBBKAQ.js.map +1 -0
  20. package/dist/chunk-KLSNDPU6.js +2412 -0
  21. package/dist/chunk-KLSNDPU6.js.map +1 -0
  22. package/dist/{chunk-HQWQ7MR5.js → chunk-LP5ISXKM.js} +4 -4
  23. package/dist/{chunk-QPU7QKPT.js → chunk-LXYT2P2Y.js} +3 -3
  24. package/dist/{chunk-C6MM6Z65.js → chunk-OMSKBBL7.js} +45 -27
  25. package/dist/chunk-OMSKBBL7.js.map +1 -0
  26. package/dist/{chunk-M4IJ3H6M.js → chunk-PXYSAG5B.js} +2 -2
  27. package/dist/{chunk-52Q72CPP.js → chunk-QG3VDSWD.js} +3 -3
  28. package/dist/{chunk-IRFKJ2KR.js → chunk-QM5W3T3O.js} +2 -2
  29. package/dist/{chunk-O3VPGING.js → chunk-QRC3QLUQ.js} +92 -95
  30. package/dist/chunk-QRC3QLUQ.js.map +1 -0
  31. package/dist/{chunk-MCWIMVG2.js → chunk-QS5HGPCN.js} +2 -2
  32. package/dist/{chunk-O5OUJ3PX.js → chunk-SS53PZO6.js} +5 -5
  33. package/dist/{chunk-VHOOJ4FG.js → chunk-SX2XWCGA.js} +2 -2
  34. package/dist/{chunk-2VD5OQQR.js → chunk-TDUXUVUU.js} +2 -2
  35. package/dist/{chunk-XFTTKOHK.js → chunk-U37AITDA.js} +2 -2
  36. package/dist/{chunk-V5FGXVSX.js → chunk-UZJ6IPJR.js} +5 -5
  37. package/dist/{chunk-MYM2TPNL.js → chunk-V26YQQK4.js} +2 -2
  38. package/dist/{chunk-HVZVVDFN.js → chunk-VLOPXV47.js} +5 -5
  39. package/dist/{chunk-AMK4BTAV.js → chunk-WD4DENPC.js} +3 -3
  40. package/dist/{chunk-WI73OZAU.js → chunk-WKFPKPEM.js} +13 -13
  41. package/dist/chunk-WKFPKPEM.js.map +1 -0
  42. package/dist/{chunk-IYEZVAJT.js → chunk-XDUTAUK3.js} +40 -42
  43. package/dist/{chunk-IYEZVAJT.js.map → chunk-XDUTAUK3.js.map} +1 -1
  44. package/dist/{cli-circuit-breaker-AM425BRL.js → cli-circuit-breaker-62YOQQT3.js} +3 -3
  45. package/dist/{cli-readiness-LWOMHZ34.js → cli-readiness-O6EOQV4L.js} +7 -7
  46. package/dist/cli.js +61 -56
  47. package/dist/cli.js.map +1 -1
  48. package/dist/{composite-router-VXQFXNET.js → composite-router-YPZ3D5Y6.js} +2 -2
  49. package/dist/{consensus-vote-V2JQHILD.js → consensus-vote-RNQQUBXO.js} +16 -17
  50. package/dist/{context-retriever-GEQIPCVL.js → context-retriever-HVPLM6DH.js} +8 -8
  51. package/dist/{doctor-deep-DSOZGB5J.js → doctor-deep-UZQTD65D.js} +3 -3
  52. package/dist/{doctor-gateway-report-RJOSOHGA.js → doctor-gateway-report-LRBPPJD4.js} +6 -7
  53. package/dist/{doctor-live-7LVRGOS5.js → doctor-live-QFLT5SDB.js} +11 -11
  54. package/dist/{expert-bridge-5A4ADUBO.js → expert-bridge-O3UZXLGB.js} +4 -4
  55. package/dist/{factory-UBAUIA2M.js → factory-KCKQQAEH.js} +10 -10
  56. package/dist/{factory-4RZLP7QV.js → factory-LUKUIB6C.js} +5 -5
  57. package/dist/{improvement-review-UIYSAI36.js → improvement-review-7IABFAU3.js} +6 -6
  58. package/dist/index.d.ts +20 -22
  59. package/dist/index.js +35 -37
  60. package/dist/index.js.map +1 -1
  61. package/dist/{init-opencode-WUN3CTBM.js → init-opencode-RYPBCM4P.js} +5 -6
  62. package/dist/{init-opencode-WUN3CTBM.js.map → init-opencode-RYPBCM4P.js.map} +1 -1
  63. package/dist/{issue-triage-VKEHVHO4.js → issue-triage-YBVJVAUU.js} +6 -6
  64. package/dist/{model-config-helpers-GYPIIXOP.js → model-config-helpers-QNV3KD2W.js} +2 -2
  65. package/dist/{openai-compat-adapter-GSDOJ7TQ.js → openai-compat-adapter-GPZDIR3D.js} +11 -8
  66. package/dist/{outcome-store-adapter-PXT7AL6T.js → outcome-store-adapter-WRONSTUD.js} +2 -2
  67. package/dist/{pr-reviewer-helpers-GUUT7G43.js → pr-reviewer-helpers-7SMNNDFJ.js} +4 -4
  68. package/dist/{registry-command-4G3WGKS5.js → registry-command-U7K6HIBK.js} +2 -2
  69. package/dist/{repo-security-plan-QO6ACTPZ.js → repo-security-plan-LFWLVEL2.js} +3 -3
  70. package/dist/{research-helpers-synthesize-MPEJHPYR.js → research-helpers-synthesize-X6MVAAKT.js} +4 -4
  71. package/dist/{routing-memory-VHQDJ6XZ.js → routing-memory-OCIVXKOU.js} +2 -2
  72. package/dist/{session-memory-M3CQFFL6.js → session-memory-4LMEWO3X.js} +3 -3
  73. package/dist/{setup-config-VGEBCEKX.js → setup-config-YNNNR4AE.js} +3 -3
  74. package/dist/{setup-custom-api-DX7CNYKT.js → setup-custom-api-QEPUCHOX.js} +3 -3
  75. package/dist/setup-data-dir-XM5DWH7R.js +35 -0
  76. package/dist/{tool-memory-7QUPGCWV.js → tool-memory-EFGFXF65.js} +5 -5
  77. package/dist/{unified-registry-CLZK3H64.js → unified-registry-KLNC24HA.js} +11 -11
  78. package/dist/{weather-report-OKMXF73V.js → weather-report-PMYQ3WBW.js} +2 -2
  79. package/package.json +1 -1
  80. package/dist/chunk-BK6Q3VQK.js.map +0 -1
  81. package/dist/chunk-C6MM6Z65.js.map +0 -1
  82. package/dist/chunk-K6M2ZWX5.js +0 -1116
  83. package/dist/chunk-K6M2ZWX5.js.map +0 -1
  84. package/dist/chunk-O3VPGING.js.map +0 -1
  85. package/dist/chunk-WI73OZAU.js.map +0 -1
  86. package/dist/chunk-XQMQGUJT.js +0 -995
  87. package/dist/chunk-XQMQGUJT.js.map +0 -1
  88. package/dist/setup-data-dir-75Z5PSSB.js +0 -36
  89. /package/dist/{ast-rule-runner-AAOBENF2.js.map → ast-rule-runner-RI7ZJ4ZI.js.map} +0 -0
  90. /package/dist/{child-mcp-config-FRWGQIHP.js.map → child-mcp-config-73BX4OTR.js.map} +0 -0
  91. /package/dist/{chunk-NUXSGWDS.js.map → chunk-23QA6GQD.js.map} +0 -0
  92. /package/dist/{chunk-EGUISJBB.js.map → chunk-2DYCHHWW.js.map} +0 -0
  93. /package/dist/{chunk-TLITBKMZ.js.map → chunk-2TA6KTRF.js.map} +0 -0
  94. /package/dist/{chunk-YHY7GMAL.js.map → chunk-4JJI34RV.js.map} +0 -0
  95. /package/dist/{chunk-KPGWNBDA.js.map → chunk-7EV3QAKO.js.map} +0 -0
  96. /package/dist/{chunk-SCQ5YAYO.js.map → chunk-D6E3LJGP.js.map} +0 -0
  97. /package/dist/{chunk-XYYXVJSO.js.map → chunk-EJ5EBTAV.js.map} +0 -0
  98. /package/dist/{chunk-BJLP4E6Q.js.map → chunk-FNHVTDHZ.js.map} +0 -0
  99. /package/dist/{chunk-VGCRYAEH.js.map → chunk-FWQSOPBA.js.map} +0 -0
  100. /package/dist/{chunk-RBFHY2LF.js.map → chunk-GAX75XCV.js.map} +0 -0
  101. /package/dist/{chunk-O46IOND3.js.map → chunk-GX5ZHZR2.js.map} +0 -0
  102. /package/dist/{chunk-33C22IY4.js.map → chunk-J44RKRGQ.js.map} +0 -0
  103. /package/dist/{chunk-L4P4A7Z2.js.map → chunk-JGY5HMWI.js.map} +0 -0
  104. /package/dist/{chunk-HQWQ7MR5.js.map → chunk-LP5ISXKM.js.map} +0 -0
  105. /package/dist/{chunk-QPU7QKPT.js.map → chunk-LXYT2P2Y.js.map} +0 -0
  106. /package/dist/{chunk-M4IJ3H6M.js.map → chunk-PXYSAG5B.js.map} +0 -0
  107. /package/dist/{chunk-52Q72CPP.js.map → chunk-QG3VDSWD.js.map} +0 -0
  108. /package/dist/{chunk-IRFKJ2KR.js.map → chunk-QM5W3T3O.js.map} +0 -0
  109. /package/dist/{chunk-MCWIMVG2.js.map → chunk-QS5HGPCN.js.map} +0 -0
  110. /package/dist/{chunk-O5OUJ3PX.js.map → chunk-SS53PZO6.js.map} +0 -0
  111. /package/dist/{chunk-VHOOJ4FG.js.map → chunk-SX2XWCGA.js.map} +0 -0
  112. /package/dist/{chunk-2VD5OQQR.js.map → chunk-TDUXUVUU.js.map} +0 -0
  113. /package/dist/{chunk-XFTTKOHK.js.map → chunk-U37AITDA.js.map} +0 -0
  114. /package/dist/{chunk-V5FGXVSX.js.map → chunk-UZJ6IPJR.js.map} +0 -0
  115. /package/dist/{chunk-MYM2TPNL.js.map → chunk-V26YQQK4.js.map} +0 -0
  116. /package/dist/{chunk-HVZVVDFN.js.map → chunk-VLOPXV47.js.map} +0 -0
  117. /package/dist/{chunk-AMK4BTAV.js.map → chunk-WD4DENPC.js.map} +0 -0
  118. /package/dist/{cli-circuit-breaker-AM425BRL.js.map → cli-circuit-breaker-62YOQQT3.js.map} +0 -0
  119. /package/dist/{cli-readiness-LWOMHZ34.js.map → cli-readiness-O6EOQV4L.js.map} +0 -0
  120. /package/dist/{composite-router-VXQFXNET.js.map → composite-router-YPZ3D5Y6.js.map} +0 -0
  121. /package/dist/{consensus-vote-V2JQHILD.js.map → consensus-vote-RNQQUBXO.js.map} +0 -0
  122. /package/dist/{context-retriever-GEQIPCVL.js.map → context-retriever-HVPLM6DH.js.map} +0 -0
  123. /package/dist/{doctor-deep-DSOZGB5J.js.map → doctor-deep-UZQTD65D.js.map} +0 -0
  124. /package/dist/{doctor-gateway-report-RJOSOHGA.js.map → doctor-gateway-report-LRBPPJD4.js.map} +0 -0
  125. /package/dist/{doctor-live-7LVRGOS5.js.map → doctor-live-QFLT5SDB.js.map} +0 -0
  126. /package/dist/{expert-bridge-5A4ADUBO.js.map → expert-bridge-O3UZXLGB.js.map} +0 -0
  127. /package/dist/{factory-4RZLP7QV.js.map → factory-KCKQQAEH.js.map} +0 -0
  128. /package/dist/{factory-UBAUIA2M.js.map → factory-LUKUIB6C.js.map} +0 -0
  129. /package/dist/{improvement-review-UIYSAI36.js.map → improvement-review-7IABFAU3.js.map} +0 -0
  130. /package/dist/{issue-triage-VKEHVHO4.js.map → issue-triage-YBVJVAUU.js.map} +0 -0
  131. /package/dist/{model-config-helpers-GYPIIXOP.js.map → model-config-helpers-QNV3KD2W.js.map} +0 -0
  132. /package/dist/{openai-compat-adapter-GSDOJ7TQ.js.map → openai-compat-adapter-GPZDIR3D.js.map} +0 -0
  133. /package/dist/{outcome-store-adapter-PXT7AL6T.js.map → outcome-store-adapter-WRONSTUD.js.map} +0 -0
  134. /package/dist/{pr-reviewer-helpers-GUUT7G43.js.map → pr-reviewer-helpers-7SMNNDFJ.js.map} +0 -0
  135. /package/dist/{registry-command-4G3WGKS5.js.map → registry-command-U7K6HIBK.js.map} +0 -0
  136. /package/dist/{repo-security-plan-QO6ACTPZ.js.map → repo-security-plan-LFWLVEL2.js.map} +0 -0
  137. /package/dist/{research-helpers-synthesize-MPEJHPYR.js.map → research-helpers-synthesize-X6MVAAKT.js.map} +0 -0
  138. /package/dist/{routing-memory-VHQDJ6XZ.js.map → routing-memory-OCIVXKOU.js.map} +0 -0
  139. /package/dist/{session-memory-M3CQFFL6.js.map → session-memory-4LMEWO3X.js.map} +0 -0
  140. /package/dist/{setup-config-VGEBCEKX.js.map → setup-config-YNNNR4AE.js.map} +0 -0
  141. /package/dist/{setup-custom-api-DX7CNYKT.js.map → setup-custom-api-QEPUCHOX.js.map} +0 -0
  142. /package/dist/{setup-data-dir-75Z5PSSB.js.map → setup-data-dir-XM5DWH7R.js.map} +0 -0
  143. /package/dist/{tool-memory-7QUPGCWV.js.map → tool-memory-EFGFXF65.js.map} +0 -0
  144. /package/dist/{unified-registry-CLZK3H64.js.map → unified-registry-KLNC24HA.js.map} +0 -0
  145. /package/dist/{weather-report-OKMXF73V.js.map → weather-report-PMYQ3WBW.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/openai-compat-adapter.ts","../src/adapters/gateway-host-status.ts","../src/adapters/openai-adapter.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","../src/adapters/openai-types.ts","../src/config/model-parameter-support.ts","../src/config/temperature-support.ts","../src/adapters/optional-params.ts","../src/adapters/openai-mappers.ts","../src/adapters/openai-responses.ts","../src/adapters/openai-responses-stream.ts","../src/adapters/gateway-usage-recording.ts","../src/config/opencode-bridge.ts","../src/adapters/gateway-client-guard.ts","../src/adapters/gateway-http.ts"],"sourcesContent":["/**\n * OpenAI-compatible gateway adapter — talk to any HTTP gateway that exposes\n * the OpenAI Chat Completions API or the opt-in Responses API. The gateway may itself be a multi-model\n * router (Bedrock/Vertex/Azure proxy, OpenRouter, vLLM, etc.). nexus-agents\n * sees one adapter, the gateway exposes N models, and the existing routing\n * pipeline picks among them.\n *\n * Source: Issue #2468 (epic #2467 child).\n *\n * Configuration precedence (#2503, child 3 of epic #2500):\n * 1. NEXUS_OPENAI_COMPAT_URL + NEXUS_OPENAI_COMPAT_KEY env vars (both required)\n * 2. NEXUS_OPENCODE_CONFIG path → opencode.json → providers.openai-compat\n * 3. Unconfigured → adapter not built\n *\n * Models are discovered via GET {base}/models at first use, where {base} is\n * NEXUS_OPENAI_COMPAT_URL and already ends in `/v1` (the SDK appends only\n * `/models`, so a base without `/v1` probes the wrong path). Each model\n * the gateway exposes can be selected by ID; the adapter wraps the existing\n * `OpenAIAdapter` for the actual chat or Responses request, so streaming +\n * tool use + the full IModelAdapter contract come for free.\n */\n\nimport OpenAI from 'openai';\nimport {\n checkGatewayHost,\n GATEWAY_HOST_LOOKUP_TIMED_OUT,\n GatewayHostRefusedError,\n} from './gateway-host-status.js';\n\nimport type { Result, ILogger, IModelAdapter } from '../core/index.js';\nimport { ok, err, ConfigError, createLogger, getErrorMessage } from '../core/index.js';\nimport { OpenAIAdapter } from './openai-adapter.js';\nimport { withGatewayUsageRecording } from './gateway-usage-recording.js';\nimport { readOpencodeGateway } from '../config/opencode-bridge.js';\nimport { isEndpointArmId, type EndpointArmId } from '../cli-adapters/types-core.js';\nimport { gatewayEndpointRejection } from './sdk/gateway-cost.js';\nimport {\n DEFAULT_OPENAI_COMPAT_ENDPOINT,\n OPENAI_COMPAT_ENDPOINT_ENV,\n OPENAI_COMPAT_KEY_ENV,\n OPENAI_COMPAT_MODELS_ENV,\n OPENAI_COMPAT_URL_ENV,\n} from './sdk/types.js';\nimport { guardedGatewayFetch, validateOpenAICompatBaseUrl } from './gateway-client-guard.js';\nexport { validateOpenAICompatBaseUrl } from './gateway-client-guard.js';\nimport { hostnameOf } from './sdk/gateway-env.js';\nimport { redactGatewaySecrets } from './gateway-redaction.js';\nimport { readModelAllowlist, refineGatewayCatalog } from './gateway-catalog-filter.js';\nimport {\n gatewayClientOptions,\n readGatewayTransport,\n type GatewayTransport,\n} from './gateway-http.js';\n\nexport interface OpenAICompatConfig extends GatewayTransport {\n /** Gateway base URL — ends in `/v1`; the SDK appends `/models` and `/chat/completions`. */\n readonly baseUrl: string;\n /** Preserve custom-openai requests without an implicit output token cap. */\n readonly omitDefaultTokenCap?: boolean;\n /** API key the gateway expects. */\n readonly apiKey: string;\n /** Per-request timeout for an explicitly constructed gateway client. */\n readonly timeout?: number;\n /** SDK retries for an explicitly constructed gateway client. */\n readonly maxRetries?: number;\n /** Caller logger used by explicitly constructed compatibility clients. */\n readonly logger?: ILogger;\n /**\n * Endpoint identity the gateway registers as — the `<endpoint>` of its\n * `api:<endpoint>` arm (#4392 increment 2, step 2). Always set by\n * {@link readOpenAICompatEnv}; optional on the type so a hand-built config\n * (tests, embedders) keeps working, with the default applying at\n * registration. Never the URL.\n */\n readonly endpoint?: string;\n /**\n * Model-id allowlist (`NEXUS_OPENAI_COMPAT_MODELS`, #6600), applied before\n * the adapter cap; `*` is a wildcard. Absent or empty means no allowlist.\n */\n readonly modelAllowlist?: readonly string[];\n /** Discovery matched this model id. Absent for a hand-built, unmeasured adapter. */\n readonly modelVerified?: boolean;\n}\n\n/**\n * A per-model gateway adapter, marked with the `api:<endpoint>` arm it\n * registers under (#4392 increment 2, step 4). The telemetry writers key on\n * this — the usage log here, the vote rollup in `decision-cost-recording` —\n * to price a call by the arm's `NEXUS_GATEWAY_COST` declaration instead of\n * by the model id alone. `providerId` stays `'openai'` on purpose:\n * `inFamilyFallback` and `authRemediation` take their inputs from it.\n * Reached through {@link isGatewayModelAdapter} (narrowing) and\n * {@link createOpenAICompatAdapter} (construction); not exported by name\n * because nothing outside this module needs to spell it.\n */\ninterface GatewayModelAdapter extends IModelAdapter {\n readonly gatewayArm: EndpointArmId;\n /**\n * The `/models` `created` stamp (epoch seconds) discovery listed for this\n * model, when it listed one. Read by the family-slot ranking (#6604).\n */\n readonly created?: number;\n}\n\n/**\n * True iff `adapter` carries a valid gateway arm id. Checked by shape, not\n * by construction site: a hand-built config can name an endpoint that is not\n * an endpoint id, and a marker that fails the id rule is no marker.\n */\nexport function isGatewayModelAdapter(adapter: IModelAdapter): adapter is GatewayModelAdapter {\n const arm: unknown = (adapter as Partial<GatewayModelAdapter>).gatewayArm;\n return typeof arm === 'string' && isEndpointArmId(arm);\n}\n\nexport interface DiscoveredModel {\n readonly id: string;\n /** Unix epoch seconds when the model was created (per OpenAI API). */\n readonly created?: number;\n /** Owning organization or upstream provider name. */\n readonly ownedBy?: string;\n}\n\n/**\n * Read the gateway config with the precedence chain documented in the\n * module docstring: env vars > opencode.json > unconfigured.\n *\n * The env-var path (#2468) wins when both `NEXUS_OPENAI_COMPAT_URL` and\n * `NEXUS_OPENAI_COMPAT_KEY` are set. Otherwise, when `NEXUS_OPENCODE_CONFIG`\n * names a path, the opencode.json bridge tries to source the gateway from\n * `providers.openai-compat.options.{baseURL, apiKey}` (#2503). Returns\n * `null` when neither path yields a config — caller treats unset gateway\n * as \"no adapter from this source.\"\n */\nexport function readOpenAICompatEnv(): OpenAICompatConfig | null {\n const fromEnv = readGatewayFromEnv();\n if (fromEnv !== null) return fromEnv;\n return readGatewayFromOpencode();\n}\n\n/** Read canonical URL/key names; the old alias pair was removed in 10.0 (#7144). */\nfunction readGatewayFromEnv(): OpenAICompatConfig | null {\n const envUrl = process.env[OPENAI_COMPAT_URL_ENV]?.trim();\n const envKey = process.env[OPENAI_COMPAT_KEY_ENV]?.trim();\n if (envUrl === undefined || envUrl === '') return null;\n if (envKey === undefined || envKey === '') return null;\n return {\n baseUrl: envUrl,\n apiKey: envKey,\n endpoint: readOpenAICompatEndpoint(),\n modelAllowlist: readModelAllowlist(),\n ...readGatewayTransport(envUrl, process.env, endpointLogger),\n };\n}\n\nfunction readGatewayFromOpencode(): OpenAICompatConfig | null {\n const opencodePath = process.env['NEXUS_OPENCODE_CONFIG']?.trim();\n if (opencodePath === undefined || opencodePath === '') return null;\n const fromFile = readOpencodeGateway(opencodePath);\n if (fromFile === null) return null;\n return {\n baseUrl: fromFile.baseURL,\n apiKey: fromFile.apiKey,\n endpoint: readOpenAICompatEndpoint(),\n modelAllowlist: readModelAllowlist(),\n ...readGatewayTransport(fromFile.baseURL, process.env, endpointLogger),\n };\n}\n\nconst endpointLogger = createLogger({ component: 'openai-compat-adapter' });\n\n/**\n * The gateway's endpoint identity (#4392 increment 2, step 2):\n * `NEXUS_OPENAI_COMPAT_ENDPOINT` when `api:<value>` is a GATEWAY arm id, else\n * {@link DEFAULT_OPENAI_COMPAT_ENDPOINT}. The fallback is deliberate: the env\n * schema reports an invalid value at startup, and this reader must never turn\n * a pasted URL — or a credential inside one — into an arm id, telemetry key\n * or display string, nor register the gateway as a VENDOR arm (`api:openai`),\n * where its cost declaration is unreachable (#6409). The same rule decides\n * both (`gatewayEndpointRejection`), and the fallback is warned with the\n * reason, never the value. Both config paths (env, opencode.json) share it.\n */\nexport function readOpenAICompatEndpoint(\n env: NodeJS.ProcessEnv = process.env,\n logger: ILogger = endpointLogger\n): string {\n const raw = env[OPENAI_COMPAT_ENDPOINT_ENV]?.trim();\n if (raw === undefined || raw === '') return DEFAULT_OPENAI_COMPAT_ENDPOINT;\n const reason = gatewayEndpointRejection(raw);\n if (reason === undefined) return raw;\n logger.warn(\n `${OPENAI_COMPAT_ENDPOINT_ENV} ignored (${reason}); the gateway registers as api:${DEFAULT_OPENAI_COMPAT_ENDPOINT}`,\n { env: OPENAI_COMPAT_ENDPOINT_ENV, reason, value: '<redacted>' }\n );\n return DEFAULT_OPENAI_COMPAT_ENDPOINT;\n}\n\n/**\n * Ceiling on how many models one gateway may contribute.\n *\n * `buildOpenAICompatAdapters` constructs one adapter per discovered model, so an\n * unbounded list becomes unbounded objects during bootstrap. Aggregators\n * legitimately serve hundreds — models.dev lists 339 for one and 620 for\n * another — so this is a sanity ceiling on adapter construction, not a claim\n * about what a gateway may offer. It is checked AFTER deduplication, the\n * non-chat filter and the operator allowlist (#6600), so a large catalogue is\n * served by allowlisting the models wanted rather than refused.\n */\nconst MAX_DISCOVERED_MODELS = 256;\n\n/** Bound on the discovery call. Bootstrap must not hang on a dead gateway. */\nconst MODEL_DISCOVERY_TIMEOUT_MS = 10_000;\n\n/**\n * Shape of a model id this adapter will dispatch to (#4392 increment 2, step\n * 2). A discovered id becomes a request field, a usage-log key and — through\n * the gateway catalogue — a pricing key, so whitespace and control characters\n * are refused; `/`, `:`, `.` and `_` are kept because aggregators use them\n * (`org/model:tag`). Length is capped at 128.\n */\nconst MODEL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/;\n\n/**\n * Keep the ids that satisfy {@link MODEL_ID_PATTERN}. Warns with the dropped\n * COUNT only — an offending id is exactly the string that must not reach a\n * log line, and the count is what tells an operator the gateway's listing\n * needs a look.\n */\nfunction keepValidModelIds<T extends { readonly id: string }>(\n models: readonly T[],\n logger: ILogger | undefined\n): readonly T[] {\n const kept = models.filter((m) => MODEL_ID_PATTERN.test(m.id));\n const dropped = models.length - kept.length;\n if (dropped > 0) {\n logger?.warn(\n `Dropped ${String(dropped)} gateway model id(s) that are not a valid model id shape (whitespace, control characters, or over 128 chars)`,\n { dropped, kept: kept.length }\n );\n }\n return kept;\n}\n\n/**\n * Discover available models by calling `GET {baseUrl}/models` ({baseUrl} ends\n * in `/v1`). Uses the\n * official `openai` SDK's `client.models.list()` so we benefit from its\n * pagination + retry handling. The list is the strongly authoritative\n * source: nexus-agents won't try to dispatch to a model the gateway doesn't\n * expose.\n */\nexport async function discoverModels(\n config: OpenAICompatConfig,\n logger?: ILogger\n): Promise<Result<readonly DiscoveredModel[], ConfigError>> {\n const catalog = await discoverGatewayCatalog(config, logger);\n return catalog.ok ? ok(catalog.value.models) : catalog;\n}\n\n/**\n * {@link discoverModels} plus the raw listing size (#6609), so `doctor\n * --gateway` can report the count before and after the chat filter from the\n * same call the server makes. `listedCount` is the rows `GET /models`\n * returned, before deduplication, the chat filter and the allowlist; `models`\n * is what {@link discoverModels} returns.\n */\nexport async function discoverGatewayCatalog(\n config: OpenAICompatConfig,\n logger?: ILogger\n): Promise<\n Result<{ readonly listedCount: number; readonly models: readonly DiscoveredModel[] }, ConfigError>\n> {\n // Reuse the SDK path's DNS-resolve-time SSRF guard (#3426) rather than\n // growing a second one. This path needs it at least as much: it can read its\n // base URL from a FILE (`NEXUS_OPENCODE_CONFIG` -> opencode.json), not only\n // from an env var, so the input is not always direct operator intent.\n // The guard fails OPEN on transient resolver errors and rejects only a\n // confirmed private/loopback/link-local resolution.\n // #6608: the refusal is a typed error so the bootstrap can say which\n // variable allows it and that the gateway is not in use.\n const hostCheck = await checkGatewayHost(config.baseUrl);\n if (hostCheck.state === 'refused_private_host') {\n return err(new GatewayHostRefusedError(hostCheck));\n }\n if (hostCheck.state === 'lookup_timed_out') {\n // Fail closed for this attempt (#6671 review): a plain ConfigError, so the\n // bootstrap treats it as retryable and lazy re-discovery tries again.\n return err(new ConfigError(`${GATEWAY_HOST_LOOKUP_TIMED_OUT} (host ${hostCheck.host})`));\n }\n try {\n const client = new OpenAI({\n baseURL: config.baseUrl,\n apiKey: config.apiKey,\n // Discovery runs during server bootstrap, so an unresponsive gateway must\n // not stall startup indefinitely. The SDK's own default is far longer.\n timeout: MODEL_DISCOVERY_TIMEOUT_MS,\n maxRetries: 1,\n // Auth header, extra headers and proxy (#6608) — the same options every\n // per-model adapter gets, so discovery cannot pass where completions fail.\n ...gatewayClientOptions(config),\n });\n const list = await client.models.list();\n // `listing` is the raw row: gateways add fields beyond the SDK's `Model`\n // type (`type`, `mode`, `architecture`) that say whether it can chat.\n const listed = list.data.map((m) => ({ id: m.id, listing: m, model: m }));\n const allowlist = config.modelAllowlist ?? [];\n const refined = refineGatewayCatalog(keepValidModelIds(listed, logger), allowlist, logger);\n if (refined.length > MAX_DISCOVERED_MODELS) {\n return err(overCapError(config, list.data.length, refined.length, allowlist.length > 0));\n }\n return ok({\n listedCount: list.data.length,\n models: refined.map(({ model: m }) => ({\n id: m.id,\n created: m.created,\n ownedBy: m.owned_by,\n })),\n });\n } catch (e: unknown) {\n // This message lands on cli-server-gateway's probe-failed warn line, so it\n // names the host (a base URL can carry userinfo) and never the key or an\n // extra header value: a gateway's error body may echo what it received\n // (#4392 increment 3).\n return err(\n new ConfigError(\n `Failed to discover models from ${hostnameOf(config.baseUrl)}: ` +\n `${redactGatewaySecrets(getErrorMessage(e), { apiKey: config.apiKey, headers: config.extraHeaders })}. ` +\n `Verify ${OPENAI_COMPAT_URL_ENV} and ${OPENAI_COMPAT_KEY_ENV}, then retry.`\n )\n );\n }\n}\n\n/**\n * The refusal for a catalogue still above the cap after refinement. It names\n * the allowlist variable, which is the operator's way through (#6600).\n */\nfunction overCapError(\n config: OpenAICompatConfig,\n listed: number,\n refined: number,\n allowlisted: boolean\n): ConfigError {\n const cap = String(MAX_DISCOVERED_MODELS);\n const host = hostnameOf(config.baseUrl);\n const detail = allowlisted\n ? `${OPENAI_COMPAT_MODELS_ENV} matched ${String(refined)} of its ${String(listed)} listed models`\n : `it listed ${String(listed)} models (${String(refined)} chat models)`;\n return new ConfigError(\n `Gateway ${host}: ${detail}, above the ${cap} cap. Refusing to build an adapter per model. ` +\n `Set ${OPENAI_COMPAT_MODELS_ENV} to a comma-separated allowlist of model ids ` +\n `(\\`*\\` is a wildcard) naming at most ${cap} models.`\n );\n}\n\n/**\n * Create an OpenAIAdapter pointed at the gateway for a specific model ID,\n * wrapped with usage recording so eligible completions append a UsageEvent\n * to the JSONL log consumed by `nexus-agents usage`.\n *\n * The wrapper is transparent — same IModelAdapter contract, same fields,\n * same error handling — plus the {@link GatewayModelAdapter} arm marker,\n * `api:<config.endpoint>` (the default endpoint when a hand-built config\n * omits it, matching registration). Recording is best-effort (telemetry\n * never fails the user's call).\n *\n * When invoked via MCP, the host harness's model identifier is passed\n * through verbatim — nexus-agents doesn't second-guess what the host is\n * already routing.\n */\nexport function createOpenAICompatAdapter(\n modelId: string,\n config: OpenAICompatConfig,\n created?: number\n): GatewayModelAdapter {\n // Verbatim: the id goes to the gateway exactly as it listed it. The direct\n // adapter's alias table (`gpt-4o` -> a dated snapshot) names models the\n // gateway may not serve, and would make `NEXUS_VOTER_MODEL_*` pins miss\n // (#6605).\n const inner = createOpenAICompatClient(modelId, config);\n const wrapped = withGatewayUsageRecording(\n inner,\n `api:${config.endpoint ?? DEFAULT_OPENAI_COMPAT_ENDPOINT}`,\n config.modelVerified\n );\n return created === undefined ? wrapped : Object.assign(wrapped, { created });\n}\n\n/** Construct the shared gateway client without adding a usage writer. */\nexport function createOpenAICompatClient(\n modelId: string,\n config: OpenAICompatConfig\n): OpenAIAdapter {\n const baseUrl = validateOpenAICompatBaseUrl(config.baseUrl);\n return new OpenAIAdapter({\n modelId,\n apiKey: config.apiKey,\n baseUrl,\n verbatimModelId: true,\n ...(config.omitDefaultTokenCap !== undefined && {\n omitDefaultTokenCap: config.omitDefaultTokenCap,\n }),\n ...gatewayClientOptions(config),\n fetch: guardedGatewayFetch(baseUrl),\n ...(config.logger !== undefined && { logger: config.logger }),\n ...(config.timeout !== undefined && { timeout: config.timeout }),\n ...(config.maxRetries !== undefined && { maxRetries: config.maxRetries }),\n });\n}\n\n/**\n * Convenience: read env, discover, return adapter instances for every\n * discovered model. Returns `null` (not an error) when env vars aren't set\n * — the caller treats unset gateway as \"no adapter from this source.\"\n *\n * Use case: the unified registry / factory calls this at startup; if the\n * operator has configured a gateway, every discovered model becomes a\n * dispatch target alongside the existing claude/codex/gemini/opencode\n * adapter slots.\n */\nexport async function buildOpenAICompatAdapters(\n logger?: ILogger\n): Promise<Result<readonly IModelAdapter[], ConfigError> | null> {\n const config = readOpenAICompatEnv();\n if (config === null) return null;\n const discovered = await discoverModels(config, logger);\n if (!discovered.ok) return discovered;\n return ok(\n discovered.value.map((m) =>\n createOpenAICompatAdapter(m.id, { ...config, modelVerified: true }, m.created)\n )\n );\n}\n","/**\n * Whether the private-address guard lets the gateway's host through (#6608\n * item 3), as a value a report surface can read.\n *\n * A corporate gateway commonly resolves to a 10.x address, which the SSRF\n * guard refuses unless `NEXUS_CUSTOM_API_ALLOW_PRIVATE=1`. Outside a sandbox\n * that used to surface as a generic \"probe failed\" warn line while the server\n * quietly fell back to CLI subprocesses. {@link checkGatewayHost} is the one\n * place the refusal and its remedy are phrased; discovery refuses with\n * {@link GatewayHostRefusedError}, the bootstrap reports it by name, and\n * `doctor` can call {@link checkGatewayHost} directly (#6609).\n *\n * @module adapters/gateway-host-status\n */\n\nimport { ConfigError } from '../core/index.js';\nimport { assertCustomApiHostResolvesPublic } from './sdk/custom-api-validation.js';\nimport { hostnameOf } from './sdk/gateway-env.js';\nimport { CUSTOM_API_ALLOW_PRIVATE_ENV } from './sdk/types.js';\n\n/** The guard refused the host: the gateway is not used. */\nexport interface GatewayHostRefused {\n readonly state: 'refused_private_host';\n readonly host: string;\n /** The guard's classification (private, loopback, link-local, …). */\n readonly reason: string;\n /** What the operator sets to allow it; names the variable. */\n readonly remedy: string;\n}\n\nexport type GatewayHostStatus =\n | { readonly state: 'allowed'; readonly host: string }\n | GatewayHostRefused\n /**\n * The guard's lookup did not answer in time. Unlike a DNS error (the\n * connection could not resolve either), the connection's own lookup may\n * still answer, with a private address, so the host is NOT allowed. Not a\n * refusal: the next attempt runs the guard again.\n */\n | { readonly state: 'lookup_timed_out'; readonly host: string };\n\n/** The message discovery fails with on `lookup_timed_out`; lazy re-discovery retries it. */\nexport const GATEWAY_HOST_LOOKUP_TIMED_OUT =\n 'gateway host check timed out; the gateway is not wired this attempt, will retry';\n\nconst REMEDY =\n `Set ${CUSTOM_API_ALLOW_PRIVATE_ENV}=1 if the gateway runs on a trusted internal host, ` +\n 'then restart the server.';\n\n/**\n * Run the private-address guard against `baseUrl`'s host. The guard fails\n * OPEN on a DNS error (a flaky resolver must not break a legitimate gateway),\n * so `allowed` means \"not refused\", not \"reachable\". It fails CLOSED on a\n * lookup that does not answer within the bound: `lookup_timed_out`.\n */\nexport async function checkGatewayHost(\n baseUrl: string,\n options: { readonly lookupTimeoutMs?: number } = {}\n): Promise<GatewayHostStatus> {\n const host = hostnameOf(baseUrl);\n const guard = await withLookupTimeout(\n assertCustomApiHostResolvesPublic(host),\n options.lookupTimeoutMs ?? GATEWAY_HOST_LOOKUP_TIMEOUT_MS\n );\n if (guard === 'timed_out') return { state: 'lookup_timed_out', host };\n if (guard.ok) return { state: 'allowed', host };\n return { state: 'refused_private_host', host, reason: guard.error.message, remedy: REMEDY };\n}\n\n/**\n * Upper bound on the guard's DNS lookup (#6671 review). `dns.lookup` has no\n * timeout of its own, and discovery (at boot and on lazy re-discovery) runs\n * the guard before its bounded HTTP request, so an unresponsive resolver\n * would otherwise hold discovery open indefinitely.\n */\nconst GATEWAY_HOST_LOOKUP_TIMEOUT_MS = 5_000;\n\nasync function withLookupTimeout<T>(work: Promise<T>, ms: number): Promise<T | 'timed_out'> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<'timed_out'>((resolve) => {\n timer = setTimeout(() => {\n resolve('timed_out');\n }, ms);\n timer.unref();\n });\n try {\n return await Promise.race([work, timeout]);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** Discovery's refusal when {@link checkGatewayHost} says `refused_private_host`. */\nexport class GatewayHostRefusedError extends ConfigError {\n readonly status: GatewayHostRefused;\n\n constructor(status: GatewayHostRefused) {\n super(`Gateway URL rejected: ${status.reason}`);\n this.name = 'GatewayHostRefusedError';\n this.status = status;\n }\n}\n","/**\n * nexus-agents/adapters - OpenAI Model Adapter\n *\n * Adapter for OpenAI models (GPT-4o, GPT-4-turbo, GPT-3.5-turbo).\n * Implements the IModelAdapter interface with streaming support, rate limiting,\n * and proper error handling.\n *\n * Verified 2026-01-03: openai@6.15.0 is current stable\n * (Source: npm registry)\n */\n\nimport OpenAI, { APIError } from 'openai';\nimport type { ChatCompletionMessageParam, ChatCompletion } from 'openai/resources/chat/completions';\nimport type {\n Result,\n CompletionRequest,\n CompletionResponse,\n ModelMetadata,\n StreamChunk,\n TokenUsage,\n} from '../core/index.js';\nimport { ok, err, ModelError, ConfigError, ErrorCode, getTokenEstimator } from '../core/index.js';\nimport { BaseAdapter, requireApiKey, validateApiKeyPresence } from './base-adapter.js';\nimport type { BaseAdapterConfig } from './base-adapter.js';\nimport { createStream } from './streaming.js';\nimport {\n DEFAULT_MAX_TOKENS,\n resolveModelId,\n getModelCapabilities,\n type OpenAIAdapterConfig,\n} from './openai-types.js';\nimport { planOptionalParams, type DroppedParam } from './optional-params.js';\nimport { getMaxTokensParamForModel } from '../config/model-parameter-support.js';\nimport {\n mapMessage,\n mapTool,\n mapStopReason,\n mapChoiceToContentBlocks,\n mapResponseUsage,\n mapStreamChunk,\n createStreamToolCallState,\n detectNonAnswer,\n CONTENT_FILTERED,\n type NonAnswer,\n} from './openai-mappers.js';\nimport { REDACTED_KEY_PLACEHOLDER, sanitizeErrorDetails } from '../security/output-sanitizer.js';\nimport { redactGatewaySecrets, type GatewaySecretSource } from './gateway-redaction.js';\nimport {\n buildResponsesParams,\n completeResponses,\n responsesToChatCompletion,\n} from './openai-responses.js';\nimport { mapResponsesStream } from './openai-responses-stream.js';\n\n// Re-export types and constants for public API\nexport { OPENAI_MODELS, OPENAI_MODEL_ALIASES, type OpenAIAdapterConfig } from './openai-types.js';\n\n/**\n * OpenAI model adapter.\n *\n * Provides a unified interface for interacting with OpenAI's GPT models.\n * Supports completion, streaming, tool use, and vision capabilities.\n *\n * @example\n * ```typescript\n * const adapter = new OpenAIAdapter({\n * modelId: 'gpt-4o',\n * apiKey: process.env.OPENAI_API_KEY,\n * });\n *\n * const result = await adapter.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * maxTokens: 1024,\n * });\n *\n * if (result.ok) {\n * console.log(result.value.content);\n * }\n * ```\n */\n\n/**\n * Compose a diagnostic string from an OpenAI SDK `APIError`'s real fields\n * (#4047). The SDK's `.message` alone can be as useless as\n * `\"400 status code (no body)\"` for an OpenAI-compatible gateway; this pulls the\n * HTTP status, structured error fields, and the raw body so the actual rejection\n * reason is visible.\n */\n/** Typed structural view of the OpenAI SDK `APIError` fields we read (the SDK's\n * generic `APIError<any,…>` otherwise leaks `any`). */\ninterface ApiErrorView {\n readonly status?: number | null;\n readonly type?: string | null;\n readonly code?: string | null;\n readonly param?: string | null;\n readonly requestID?: string | null;\n readonly error?: unknown;\n readonly message?: string;\n}\n\n/** `key=value` tag, or `''` when the value is absent. */\nfunction kvTag(key: string, val: string | number | null | undefined): string {\n return val === null || val === undefined || val === '' ? '' : `${key}=${String(val)}`;\n}\n\n/**\n * Error text with the configured credentials removed: the key and every\n * header value by exact match (a gateway's custom auth header and extra\n * headers have no vendor shape), then the pattern sanitizer.\n */\nfunction redactErrorText(text: string, secrets: GatewaySecretSource): string {\n return sanitizeErrorDetails(\n redactGatewaySecrets(text, secrets, REDACTED_KEY_PLACEHOLDER),\n secrets.apiKey\n );\n}\n\nfunction describeOpenAIApiError(v: ApiErrorView, secrets: GatewaySecretSource): string {\n const tags = [\n `HTTP ${String(v.status ?? 'unknown')}`,\n kvTag('type', v.type),\n kvTag('code', v.code),\n kvTag('param', v.param),\n kvTag('request_id', v.requestID),\n ].filter((t) => t !== '');\n let body = '';\n if (v.error !== undefined && v.error !== null) {\n try {\n const raw = JSON.stringify(v.error);\n body = ` body=${raw.length > MAX_ERROR_BODY_CHARS ? `${raw.slice(0, MAX_ERROR_BODY_CHARS)}…` : raw}`;\n } catch {\n body = ' body=<unserializable>';\n }\n }\n return redactErrorText(`${tags.join(' ')}: ${v.message ?? ''}${body}`, secrets);\n}\n\n/** Cap the surfaced gateway error body so a huge response can't bloat logs/messages. */\nconst MAX_ERROR_BODY_CHARS = 600;\n\nexport class OpenAIAdapter extends BaseAdapter {\n private readonly client: OpenAI;\n private readonly resolvedModelId: string;\n private readonly apiSurface: 'chat' | 'responses';\n private readonly omitDefaultTokenCap: boolean;\n private readonly apiKey: string | undefined;\n /** Headers sent on every request; each value is redacted from error text. */\n private readonly headers: OpenAIAdapterConfig['defaultHeaders'];\n\n /**\n * Creates a new OpenAIAdapter instance.\n *\n * @param config - OpenAI adapter configuration\n * @throws {ConfigError} If API key is missing\n */\n constructor(config: OpenAIAdapterConfig) {\n const resolvedModelId =\n config.verbatimModelId === true ? config.modelId : resolveModelId(config.modelId);\n\n // Build baseConfig conditionally to satisfy exactOptionalPropertyTypes\n const baseConfig: BaseAdapterConfig = {\n providerId: 'openai',\n modelId: resolvedModelId,\n capabilities: getModelCapabilities(config.modelId),\n apiKey: config.apiKey,\n ...(config.logger !== undefined && { logger: config.logger }),\n };\n\n // Only set optional properties if defined\n if (config.baseUrl !== undefined) {\n baseConfig.baseUrl = config.baseUrl;\n }\n if (config.timeout !== undefined) {\n baseConfig.timeout = config.timeout;\n }\n if (config.maxRetries !== undefined) {\n baseConfig.maxRetries = config.maxRetries;\n }\n\n super(baseConfig);\n\n this.apiKey = config.apiKey;\n this.headers = config.defaultHeaders;\n this.resolvedModelId = resolvedModelId;\n this.apiSurface = config.apiSurface ?? 'chat';\n this.omitDefaultTokenCap = config.omitDefaultTokenCap ?? false;\n\n // Validate API key presence\n requireApiKey(config.apiKey, 'OpenAI', config.modelId);\n\n this.client = this.createClient(config);\n }\n\n /**\n * Creates the OpenAI client with configuration.\n */\n private createClient(config: OpenAIAdapterConfig): OpenAI {\n const clientOptions: ConstructorParameters<typeof OpenAI>[0] = {\n apiKey: config.apiKey,\n maxRetries: config.maxRetries ?? 2,\n };\n\n if (config.baseUrl !== undefined) {\n clientOptions.baseURL = config.baseUrl;\n }\n if (config.timeout !== undefined) {\n clientOptions.timeout = config.timeout;\n }\n if (config.organization !== undefined) {\n clientOptions.organization = config.organization;\n }\n if (config.defaultHeaders !== undefined) {\n clientOptions.defaultHeaders = config.defaultHeaders;\n }\n if (config.fetchOptions !== undefined) {\n clientOptions.fetchOptions = config.fetchOptions;\n }\n clientOptions.fetch = config.fetch;\n\n return new OpenAI(clientOptions);\n }\n\n /**\n * Validates adapter configuration.\n * Extends base validation with OpenAI-specific checks.\n */\n override validateConfig(): Result<void, ConfigError> {\n const baseResult = super.validateConfig();\n if (!baseResult.ok) {\n return baseResult;\n }\n\n // Validate API key is present\n const keyResult = validateApiKeyPresence(this.config.apiKey, this.providerId, this.modelId);\n if (!keyResult.ok) return keyResult;\n\n return ok(undefined);\n }\n\n /**\n * Send a completion request to OpenAI.\n *\n * @param request - The completion request\n * @returns Result with response or ModelError\n */\n async complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>> {\n this.logRequest(request);\n\n try {\n const response = await this.executeCompletion(request);\n this.logResponse(response);\n return ok(response);\n } catch (error) {\n return err(this.transformError(error));\n }\n }\n\n /**\n * Surface an OpenAI / OpenAI-compatible gateway's REAL HTTP status + response\n * body in the error (#4047). The OpenAI SDK's default message collapses a\n * gateway rejection to e.g. `\"400 status code (no body)\"`, which hides WHY a\n * litellm-style gateway rejected a request — exactly the wall hit when\n * diagnosing degraded voter panels on a custom gateway. We re-message with the\n * status/type/code/param/request-id/body. Error-code routing is unchanged: we\n * classify on the ORIGINAL signal (`status`/`code`/`message`) via a clean probe\n * error, so the diagnostic `request_id`/`body` can't pollute the message-\n * substring classifier, then re-message the result with the full detail.\n * Applies to direct OpenAI and the compat gateway alike.\n */\n protected override transformError(error: unknown): ModelError {\n const secrets = { apiKey: this.apiKey, headers: this.headers };\n if (error instanceof APIError) {\n // The SDK wraps a guarded-fetch refusal as a connection error. Preserve\n // its configuration classification and remedy instead of hiding both.\n if (error.cause instanceof ConfigError) {\n const message = redactErrorText(error.cause.message, secrets);\n return new ModelError(message, { code: error.cause.code, cause: error.cause });\n }\n const v = error as ApiErrorView;\n // Classify on the original SDK message + status/code/param only. #4069: thread\n // `param` so a param-naming 400 classifies as MODEL_PARAMETER_UNSUPPORTED and\n // the param name reaches the error context.\n const probe: Error & {\n status?: number | undefined;\n code?: string | null | undefined;\n param?: string | undefined;\n } = new Error(typeof v.message === 'string' ? v.message : '');\n probe.status = typeof v.status === 'number' ? v.status : undefined;\n probe.code = v.code ?? undefined;\n probe.param = typeof v.param === 'string' && v.param !== '' ? v.param : undefined;\n probe.cause = error;\n const classified = super.transformError(probe);\n // Surface the full diagnostic detail in the final message (code/cause kept).\n classified.message = `${this.providerId}/${this.modelId}: ${describeOpenAIApiError(v, secrets)}`;\n return classified;\n }\n const err = super.transformError(error);\n err.message = redactErrorText(err.message, secrets);\n return err;\n }\n\n /**\n * Stream a completion request from OpenAI.\n *\n * @param request - The completion request\n * @yields StreamChunk objects as they arrive\n */\n async *stream(request: CompletionRequest): AsyncIterable<StreamChunk> {\n this.logRequest(request);\n\n const [controller, iterable] = createStream<StreamChunk>();\n\n // Start streaming in the background\n this.executeStream(request, controller).catch((error: unknown) => {\n const modelError = this.transformError(error);\n controller.error(modelError);\n });\n\n yield* iterable;\n }\n\n /**\n * Count tokens in text using OpenAI-specific estimation.\n *\n * @param text - Text to count tokens for\n * @returns Approximate token count\n */\n override countTokens(text: string): Promise<number> {\n // Use unified TokenEstimator with OpenAI-specific ratio (~4 chars/token)\n return Promise.resolve(getTokenEstimator().estimateText(text, 'openai'));\n }\n\n /**\n * Executes the completion request against the OpenAI API.\n */\n private async executeCompletion(request: CompletionRequest): Promise<CompletionResponse> {\n const { params, dropped } = this.buildRequestParams(request);\n if (this.apiSurface === 'responses') {\n const result = await completeResponses(this.client, { params, dropped }, request.signal);\n return this.mapResponse(result.response, result.dropped);\n }\n // #3036: forward AbortSignal into the OpenAI SDK so withWatchdog\n // timeouts cancel the HTTP request instead of leaking it past the\n // Promise.race boundary. Branch on signal presence — vitest 4\n // toHaveBeenCalledWith treats `(params, undefined)` as a distinct\n // call shape from `(params)`.\n const response =\n request.signal !== undefined\n ? await this.client.chat.completions.create(params, { signal: request.signal })\n : await this.client.chat.completions.create(params);\n // #4069: surface params dropped by the seam (e.g. temperature) as warnings.\n return this.mapResponse(response, dropped);\n }\n\n /**\n * Executes streaming completion and pushes chunks to the controller.\n */\n private async executeStream(\n request: CompletionRequest,\n controller: {\n push: (chunk: StreamChunk) => Result<void, Error>;\n complete: () => void;\n error: (error: Error) => void;\n }\n ): Promise<void> {\n try {\n const { params } = this.buildRequestParams(request);\n if (this.apiSurface === 'responses') {\n const stream = await this.client.responses.create(\n { ...buildResponsesParams(params), stream: true },\n { signal: request.signal }\n );\n for await (const chunk of mapResponsesStream(stream, (response) =>\n this.mapResponse(responsesToChatCompletion(response))\n ))\n controller.push(chunk);\n controller.complete();\n return;\n }\n const stream = await this.client.chat.completions.create({ ...params, stream: true });\n\n let contentIndex = 0;\n let hasStarted = false;\n const toolCalls = createStreamToolCallState();\n\n for await (const chunk of stream) {\n // #6607: a filtered stream is a refusal. Error the stream instead of\n // finishing it normally over whatever partial text arrived.\n if (chunk.choices[0]?.finish_reason === 'content_filter') {\n throw nonAnswerError(`${this.providerId}/${this.modelId}`, CONTENT_FILTERED, chunk.model);\n }\n const mappedChunks = mapStreamChunk(chunk, contentIndex, hasStarted, toolCalls);\n\n for (const mappedChunk of mappedChunks) {\n if (mappedChunk.type === 'message_start') {\n hasStarted = true;\n }\n if (mappedChunk.type === 'content_block_start') {\n contentIndex++;\n }\n controller.push(mappedChunk);\n }\n }\n\n controller.complete();\n } catch (error) {\n const modelError = this.transformError(error);\n controller.error(modelError);\n }\n }\n\n /**\n * Builds OpenAI API request parameters from our CompletionRequest.\n */\n private buildRequestParams(request: CompletionRequest): {\n params: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming;\n dropped: readonly DroppedParam[];\n } {\n const messages = this.buildMessages(request);\n\n const params: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming = {\n model: this.resolvedModelId,\n messages,\n ...(request.maxTokens !== undefined || !this.omitDefaultTokenCap\n ? { max_completion_tokens: request.maxTokens ?? this.defaultMaxCompletionTokens() }\n : {}),\n };\n\n const dropped = this.addOptionalParams(params, request);\n return { params, dropped };\n }\n\n /**\n * Builds the messages array for the request.\n */\n private buildMessages(request: CompletionRequest): ChatCompletionMessageParam[] {\n const messages: ChatCompletionMessageParam[] = [];\n\n // Add system prompt if provided explicitly\n if (request.systemPrompt !== undefined && request.systemPrompt !== '') {\n messages.push({ role: 'system', content: request.systemPrompt });\n }\n\n // Map and add all messages (filtering out system if already added via systemPrompt)\n for (const msg of request.messages) {\n if (msg.role === 'system' && request.systemPrompt !== undefined) {\n continue;\n }\n messages.push(...mapMessage(msg));\n }\n\n return messages;\n }\n\n /**\n * Adds optional parameters to the request.\n */\n private addOptionalParams(\n params: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming,\n request: CompletionRequest\n ): readonly DroppedParam[] {\n // #4068: the temperature drop-decision (#4061: a gateway routing to a Claude\n // model after Opus 4.6, or an OpenAI reasoning model, rejects a non-1.0\n // temperature with a 400; omit it so a gateway-routed voter panel at the\n // default 0.3 does not 400) is centralized in the shared planOptionalParams\n // seam. NOTE: a gateway that injects its OWN default when the field is absent\n // is outside our control — our contract is only to not SEND a rejected value.\n const plan = planOptionalParams(request, this.resolvedModelId);\n if (plan.temperature !== undefined) {\n params.temperature = plan.temperature;\n }\n\n if (request.stop !== undefined && request.stop.length > 0) {\n params.stop = request.stop;\n }\n\n if (request.tools !== undefined && request.tools.length > 0) {\n params.tools = request.tools.map(mapTool);\n }\n\n this.addResponseFormat(params, request);\n\n // #4069: report dropped params so mapResponse can surface them as warnings.\n return plan.dropped;\n }\n\n /**\n * Adds response format to the request if specified.\n */\n private addResponseFormat(\n params: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming,\n request: CompletionRequest\n ): void {\n if (request.responseFormat === undefined) {\n return;\n }\n\n if (request.responseFormat.type === 'json_object') {\n params.response_format = { type: 'json_object' };\n } else if (request.responseFormat.type === 'json_schema') {\n params.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'response',\n schema: request.responseFormat.schema,\n },\n };\n }\n }\n\n /**\n * Maps OpenAI API response to our CompletionResponse format.\n */\n private mapResponse(\n response: ChatCompletion,\n dropped: readonly DroppedParam[] = []\n ): CompletionResponse {\n // #6607: a refusal, an empty `choices` array or a reasoning-exhausted reply\n // is not an answer. Consumers (voters, experts, orchestrate) read any mapped\n // response as one and never branch on `stopReason`, so the only signal they\n // honour is an error.\n const firstChoice = response.choices[0];\n if (firstChoice === undefined) {\n throw nonAnswerError(\n `${this.providerId}/${this.modelId}`,\n { reason: 'no_choices', detail: 'the response contained no choices' },\n response.model\n );\n }\n const nonAnswer = detectNonAnswer(firstChoice, response.usage, this.isReasoningFamily());\n if (nonAnswer !== undefined)\n throw nonAnswerError(`${this.providerId}/${this.modelId}`, nonAnswer, response.model);\n\n const content = mapChoiceToContentBlocks(firstChoice);\n const usage: TokenUsage | undefined = mapResponseUsage(response);\n\n return {\n content,\n ...(usage !== undefined ? { usage } : {}),\n stopReason: mapStopReason(firstChoice.finish_reason),\n model: response.model,\n // #4069: surface dropped params (e.g. an omitted temperature). Omitted\n // entirely when nothing was dropped (exactOptionalPropertyTypes).\n ...(dropped.length > 0 ? { warnings: dropped } : {}),\n };\n }\n\n /**\n * Reasoning families are the models that take `max_completion_tokens`\n * (o-series, gpt-5, codex); the registry answers first, a regex second.\n */\n private isReasoningFamily(): boolean {\n return getMaxTokensParamForModel(this.resolvedModelId) === 'max_completion_tokens';\n }\n\n /**\n * Default completion cap when the request sets none (#6607). On a reasoning\n * model the cap covers hidden reasoning tokens AND the visible reply, and\n * 4,096 can be spent entirely on reasoning, leaving an empty reply. OpenAI's\n * reasoning guide recommends reserving at least 25,000 tokens for reasoning\n * and output when starting out, so that is the reasoning default. It is a\n * ceiling, not a spend: a reply that finishes early is billed for what it\n * used. Other models keep `DEFAULT_MAX_TOKENS`.\n */\n private defaultMaxCompletionTokens(): number {\n return this.isReasoningFamily() ? REASONING_DEFAULT_MAX_COMPLETION_TOKENS : DEFAULT_MAX_TOKENS;\n }\n\n /**\n * (#2529) List models served by this OpenAI-compatible endpoint.\n *\n * Wraps `GET /v1/models`. Result is cached for `LIST_MODELS_TTL_MS`\n * so identity resolution doesn't round-trip on every adapter.\n * Concurrent callers share the in-flight promise.\n *\n * Throws on non-2xx so the harness-side identity resolver knows to\n * fall back to modelId parsing — silent empty-list returns would be\n * indistinguishable from \"this gateway has no models\", which a\n * misconfigured endpoint shouldn't be allowed to claim.\n */\n async listModels(): Promise<readonly ModelMetadata[]> {\n const now = Date.now();\n if (this.modelsCache !== null && now - this.modelsCache.fetchedAt < LIST_MODELS_TTL_MS) {\n return this.modelsCache.value;\n }\n if (this.modelsInFlight !== null) {\n return this.modelsInFlight;\n }\n const inFlight = this.fetchModels();\n this.modelsInFlight = inFlight;\n try {\n const value = await inFlight;\n this.modelsCache = { value, fetchedAt: Date.now() };\n return value;\n } finally {\n this.modelsInFlight = null;\n }\n }\n\n private modelsCache: { value: readonly ModelMetadata[]; fetchedAt: number } | null = null;\n private modelsInFlight: Promise<readonly ModelMetadata[]> | null = null;\n\n private async fetchModels(): Promise<readonly ModelMetadata[]> {\n const list = await this.client.models.list();\n return list.data.map((m): ModelMetadata => {\n const meta: ModelMetadata = { id: m.id };\n if (typeof m.owned_by === 'string') {\n return { ...meta, ownedBy: m.owned_by, createdAt: m.created };\n }\n if (typeof m.created === 'number') {\n return { ...meta, createdAt: m.created };\n }\n return meta;\n });\n }\n}\n\nconst LIST_MODELS_TTL_MS = 5 * 60 * 1000;\n\n/** See `defaultMaxCompletionTokens` for why 25,000 (#6607). */\nconst REASONING_DEFAULT_MAX_COMPLETION_TOKENS = 25_000;\n\n/**\n * A non-answer as a non-retryable `MODEL_ERROR` (#6607). `context.reason`\n * names which kind it was, so telemetry can tell a refusal from a\n * reasoning-exhausted budget. `source` is `provider/model`.\n *\n * Module-level rather than a private method: the API-surface snapshot follows\n * types named anywhere in an exported class, private members included.\n */\nfunction nonAnswerError(source: string, nonAnswer: NonAnswer, servedModel?: string): ModelError {\n return new ModelError(`${source}: ${nonAnswer.detail}`, {\n code: ErrorCode.MODEL_ERROR,\n context: {\n reason: nonAnswer.reason,\n ...(servedModel !== undefined ? { servedModel } : {}),\n ...(nonAnswer.reasoningTokens !== undefined\n ? { reasoningTokens: nonAnswer.reasoningTokens }\n : {}),\n },\n });\n}\n\n/**\n * Creates an OpenAIAdapter with the specified configuration.\n * Factory function for cleaner API.\n *\n * @param config - OpenAI adapter configuration\n * @returns A configured OpenAIAdapter instance\n *\n * @example\n * ```typescript\n * const adapter = createOpenAIAdapter({\n * modelId: 'gpt-4o',\n * apiKey: process.env.OPENAI_API_KEY!,\n * });\n * ```\n */\nexport function createOpenAIAdapter(config: OpenAIAdapterConfig): OpenAIAdapter {\n return new OpenAIAdapter(config);\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 {\n isRateLimitLikeError,\n resolveRetryAfterMs,\n RETRY_AFTER_CONTEXT_KEY,\n} from './rate-limit-detector.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 ?? 0,\n outputTokens: response.usage?.outputTokens ?? 0,\n totalTokens: response.usage?.totalTokens ?? 0,\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.\n // Only set for MODEL_PARAMETER_UNSUPPORTED — all other codes are unchanged.\n const param =\n errorCode === ErrorCode.MODEL_PARAMETER_UNSUPPORTED\n ? this.extractErrorParam(error)\n : undefined;\n\n // #4606: capture the provider's stated retry horizon HERE, while the\n // thrown SDK error — the last place the HTTP response is reachable — is\n // still in hand. Header first (RFC 9110 `Retry-After`), body prose second.\n // Only on a rate limit: a wait hint inside a 500 body is not a rate-limit\n // assertion, matching the subprocess path's `retryable ? parse : undefined`.\n // `resolveRetryAfterMs` returns a NUMBER; no header object travels inward.\n const retryAfterMs =\n errorCode === ErrorCode.MODEL_RATE_LIMITED\n ? resolveRetryAfterMs(error, errorMessage)\n : undefined;\n\n const modelError = this.createModelError(errorMessage, errorCode, error, param, retryAfterMs);\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 retryAfterMs?: number\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 // can read which param was rejected.\n if (param !== undefined) {\n context.param = param;\n }\n // #4606: the provider-stated retry horizon, in ms. Set only when a horizon\n // was actually read — absent means \"the provider said nothing\", which is\n // what `CapacityTracker.recordProviderQuotaExhaustion` needs to see rather\n // than a substituted 0.\n if (retryAfterMs !== undefined) {\n context[RETRY_AFTER_CONTEXT_KEY] = retryAfterMs;\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","/**\n * nexus-agents/adapters - OpenAI Type Helpers\n *\n * Type definitions and constants for the OpenAI direct-API SDK adapter.\n *\n * **Architectural boundary (#2200 Child 3):** these constants do NOT live\n * in `config/in-tree-data.ts`. The canonical registry's `cliName`\n * dimension targets CLI tools (`claude` / `gemini` / `codex` / `opencode`)\n * — there is no `openai` CLI binary. Adding `'openai'` to the CLI_NAMES\n * enum would force a fifth case in 4+ exhaustive switches across the\n * codebase, violating the semantic of \"CLI tool name.\"\n *\n * The OpenAI direct adapter is conceptually different from CLI adapters:\n * it talks to the OpenAI HTTPS API directly, not via a subprocess CLI.\n * Its model identifiers are OpenAI's own (`gpt-4o-2024-11-20`,\n * `gpt-3.5-turbo-0125`, etc.) — these are upstream API constants, not\n * versions WE chose. They drift only when OpenAI ships new dated releases.\n *\n * This file is the single source of truth for OpenAI direct-API model\n * identifiers. The model-string drift fitness-guard (#2199) treats it as\n * a documented architectural exception in the allowlist.\n */\n\nimport type { ILogger, ModelCapability } from '../core/index.js';\nimport { ModelCapability as MC } from '../core/index.js';\nimport { getCliModelName } from '../config/model-config-helpers.js';\n\n/**\n * Supported OpenAI direct-API model identifiers (OpenAI's own dated names).\n *\n * GPT_5_2_CODEX derives from the canonical registry (codex-5.2's cliModelName)\n * because it overlaps with the Codex CLI; the rest are pure-API constants.\n * Since #5091 that entry has been repointed to whatever slug codex serves\n * (`gpt-5.6-luna` as of 2026-09-23), so the key's name lags its value; renaming\n * the key is a public-API change and is tracked separately.\n */\nexport const OPENAI_MODELS = {\n GPT_5_2: 'gpt-5.2',\n GPT_5_2_INSTANT: 'gpt-5.2-chat-latest',\n GPT_5_2_PRO: 'gpt-5.2-pro',\n /**\n * Registry-derived: resolves to `codex-5.2`'s `cliModelName`, which since\n * 2026-09-23 is `gpt-5.6-luna`, not a \"5.2\" model. The key name lags its\n * value; renaming it is a public-API change tracked in #5489.\n */\n GPT_5_2_CODEX: getCliModelName('codex-5.2'),\n GPT_4O: 'gpt-4o-2024-11-20',\n GPT_4O_MINI: 'gpt-4o-mini-2024-07-18',\n GPT_4_TURBO: 'gpt-4-turbo-2024-04-09',\n GPT_35_TURBO: 'gpt-3.5-turbo-0125',\n} as const;\n\n/**\n * User-friendly OpenAI aliases → dated model identifiers.\n *\n * Identity-only mappings (e.g., `'gpt-5.2-pro' → 'gpt-5.2-pro'`) were\n * removed in #2200 Child 3 — `resolveModelId` already passes unknown ids\n * through unchanged via `?? modelId`. Only entries that translate a\n * shorthand into a dated version remain.\n */\nexport const OPENAI_MODEL_ALIASES: Record<string, string> = {\n 'gpt-5.2-instant': OPENAI_MODELS.GPT_5_2_INSTANT,\n 'gpt-4o': OPENAI_MODELS.GPT_4O,\n 'gpt-4o-mini': OPENAI_MODELS.GPT_4O_MINI,\n 'gpt-4-turbo': OPENAI_MODELS.GPT_4_TURBO,\n 'gpt-3.5-turbo': OPENAI_MODELS.GPT_35_TURBO,\n} as const;\n\n/**\n * Configuration specific to OpenAIAdapter.\n */\nexport interface OpenAIAdapterConfig {\n /** Model ID (e.g., 'gpt-4o' or full model identifier) */\n modelId: string;\n /** API key for OpenAI API (required) */\n apiKey: string;\n /** Base URL for API (optional, defaults to OpenAI's API) */\n baseUrl?: string;\n /** Gateway API surface; omitted uses Chat Completions. */\n apiSurface?: 'chat' | 'responses';\n /** Custom-openai compatibility: send a token cap only when explicitly requested. */\n omitDefaultTokenCap?: boolean;\n /** Fetch implementation, including the gateway's host guard. */\n fetch?: typeof fetch;\n /** Caller diagnostics, shared by direct and gateway adapter clients. */\n logger?: ILogger;\n /** Request timeout in milliseconds (optional) */\n timeout?: number;\n /** Maximum retries for failed requests (optional) */\n maxRetries?: number;\n /** Organization ID (optional) */\n organization?: string;\n /**\n * Send `modelId` exactly as given, skipping {@link OPENAI_MODEL_ALIASES}\n * (#6605). Set by the OpenAI-compatible gateway path, whose ids come from\n * the gateway's own listing: rewriting `gpt-4o` to a dated OpenAI snapshot\n * names a model that gateway may not serve. Default `false`.\n */\n verbatimModelId?: boolean;\n /**\n * Headers sent on every request; a `null` value removes a default header\n * (`Authorization: null` drops the bearer). Set by the OpenAI-compatible\n * gateway path for a custom auth header and extra static headers (#6608).\n */\n defaultHeaders?: Readonly<Record<string, string | null>>;\n /**\n * `fetch` options for every request — the gateway path sets a proxy\n * `dispatcher` here when `HTTPS_PROXY` / `HTTP_PROXY` applies (#6608).\n */\n fetchOptions?: Pick<RequestInit, 'dispatcher'>;\n}\n\n// Note: Token estimation moved to core/token-estimator.ts (unified TokenEstimator)\n\n/**\n * Default maximum tokens for OpenAI models.\n */\nexport const DEFAULT_MAX_TOKENS = 4096;\n\n/**\n * Tool call type for extracting function info.\n */\nexport interface FunctionToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\n/**\n * Type guard for function tool calls.\n * Note: typeof null === 'object' is true, so we need to check tc !== null\n */\nexport function isFunctionToolCall(toolCall: unknown): toolCall is FunctionToolCall {\n if (typeof toolCall !== 'object' || toolCall === null) {\n return false;\n }\n const tc = toolCall as Record<string, unknown>;\n return tc['type'] === 'function' && typeof tc['function'] === 'object' && tc['function'] !== null;\n}\n\n/**\n * Resolves model alias to full model identifier.\n */\nexport function resolveModelId(modelId: string): string {\n return OPENAI_MODEL_ALIASES[modelId] ?? modelId;\n}\n\n/**\n * Determines capabilities based on model ID.\n */\nexport function getModelCapabilities(modelId: string): readonly ModelCapability[] {\n const capabilities: ModelCapability[] = [MC.COMPLETION, MC.STREAMING, MC.TOOL_USE];\n\n const resolvedId = resolveModelId(modelId);\n\n // Vision is available on GPT-4o, GPT-4-turbo, and GPT-5.2 models\n if (\n resolvedId.includes('gpt-4o') ||\n resolvedId.includes('gpt-4-turbo') ||\n resolvedId.includes('gpt-5.2')\n ) {\n capabilities.push(MC.VISION);\n }\n\n // Extended thinking is available on GPT-5.2 models\n if (resolvedId.includes('gpt-5.2')) {\n capabilities.push(MC.EXTENDED_THINKING);\n }\n\n return capabilities;\n}\n","/**\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 // #6516 — GPT-5.6 Sol (former codex default, gpt-5.5 successor) carries the same registry encoding.\n { modelId: 'gpt-5.6-sol', param: 'temperature', issue: 6516 },\n { modelId: 'gpt-5.6-sol', maxTokensParam: 'max_completion_tokens', issue: 6516 },\n // #6842 — GPT-6.1 Sol carries gpt-5.6-sol parameter support; registry data covers GPT-6 without broadening the regex.\n { modelId: 'gpt-6.1-sol', param: 'temperature', issue: 6842 },\n { modelId: 'gpt-6.1-sol', maxTokensParam: 'max_completion_tokens', issue: 6842 },\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.6-terra,\n * codex-5.2→gpt-5.6-luna, codex-5.1-mini→gpt-6-luna (#5091, remapped\n * 2026-09-23), so gateway voters at the default 0.3 400 on all of them. The\n * regex fallback does not match `gpt-6-*`; those slugs, including the\n * gpt-6.1-sol default (#6842), use registry `unsupportedParameters` data\n * (gpt-6.1-sol's parameter support is carried over, not measured).\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 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/** 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}\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 dropped.push({\n param: 'temperature',\n reason: `model_rejects:${modelId}`,\n severity: parameterSeverity('temperature'),\n });\n }\n }\n return { ...(temperature !== undefined ? { temperature } : {}), dropped };\n}\n","/**\n * nexus-agents/adapters - OpenAI Message Mappers\n *\n * Functions for mapping between Nexus and OpenAI message formats.\n */\n\nimport type OpenAI from 'openai';\nimport type {\n ChatCompletionMessageParam,\n ChatCompletionTool,\n ChatCompletion,\n ChatCompletionChunk,\n} from 'openai/resources/chat/completions';\nimport type {\n ContentBlock,\n Message,\n ToolDefinition,\n TokenUsage,\n StopReason,\n StreamChunk,\n} from '../core/index.js';\nimport { isFunctionToolCall } from './openai-types.js';\n\n/**\n * Maps OpenAI finish reasons to our StopReason type.\n */\nexport function mapStopReason(openaiReason: string | null | undefined): StopReason {\n switch (openaiReason) {\n case 'stop':\n return 'end_turn';\n case 'length':\n return 'max_tokens';\n case 'tool_calls':\n case 'function_call':\n return 'tool_use';\n // `content_filter` is never mapped as a finish: the adapter turns it into an\n // error before a response is built (#6607, see detectNonAnswer), because\n // every consumer reads a mapped response as an answer.\n default:\n return 'end_turn';\n }\n}\n\n/** A reply blocked by the provider's content filter, streamed or not (#6607). */\nexport const CONTENT_FILTERED: NonAnswer = {\n reason: 'content_filter',\n detail: 'the reply was blocked by a content filter',\n};\n\n/** A completion that must surface as an error, never as an empty success (#6607). */\nexport interface NonAnswer {\n /** Why the completion carries no answer. */\n readonly reason: 'content_filter' | 'no_choices' | 'reasoning_truncated';\n readonly detail: string;\n /** Reasoning tokens the vendor reported, when it reported them. */\n readonly reasoningTokens?: number;\n}\n\n/**\n * Classify a completion choice that is not an answer (#6607). The third kind,\n * `no_choices` (an empty `choices` array, which some gateways return for a\n * blocked prompt), has no choice to classify and is raised by the adapter.\n *\n * - `content_filter`: the provider's safety layer blocked or cut the reply. Any\n * partial text is not an answer either.\n * - `reasoning_truncated`: a reasoning model hit the completion cap with no\n * visible output, so the whole budget went to reasoning. This is distinct\n * from an ordinary `length` truncation, which still carries partial text.\n * `reasoningFamily` comes from the model id; a reported non-zero\n * `reasoning_tokens` count is evidence on its own for ids the regex misses.\n *\n * Returns `undefined` for every other completion.\n */\nexport function detectNonAnswer(\n choice: ChatCompletion.Choice,\n usage: ChatCompletion['usage'],\n reasoningFamily: boolean\n): NonAnswer | undefined {\n if (choice.finish_reason === 'content_filter') return CONTENT_FILTERED;\n if (choice.finish_reason !== 'length' || hasVisibleOutput(choice)) return undefined;\n const reasoningTokens = usage?.completion_tokens_details?.reasoning_tokens;\n if (!reasoningFamily && !(reasoningTokens !== undefined && reasoningTokens > 0)) {\n return undefined;\n }\n return {\n reason: 'reasoning_truncated',\n detail:\n 'the completion budget was spent on reasoning before any output (empty reply, finish length)',\n ...(reasoningTokens !== undefined ? { reasoningTokens } : {}),\n };\n}\n\nfunction hasVisibleOutput(choice: ChatCompletion.Choice): boolean {\n const text = choice.message.content;\n if (text !== null && text !== '') return true;\n return (choice.message.tool_calls?.length ?? 0) > 0;\n}\n\n/**\n * Parse a tool call's JSON `arguments` string. Unparseable text is kept under\n * `_raw` rather than dropped, so the caller still sees what the model sent.\n */\nfunction parseToolArguments(args: string): unknown {\n try {\n return JSON.parse(args) as unknown;\n } catch {\n return { _raw: args };\n }\n}\n\n/**\n * Maps OpenAI choice to our ContentBlock array.\n */\nexport function mapChoiceToContentBlocks(choice: ChatCompletion.Choice): ContentBlock[] {\n const blocks: ContentBlock[] = [];\n const message = choice.message;\n\n // Add text content if present\n if (message.content !== null && message.content !== '') {\n blocks.push({ type: 'text', text: message.content });\n }\n\n // Add tool calls if present\n if (message.tool_calls !== undefined && message.tool_calls.length > 0) {\n for (const toolCall of message.tool_calls) {\n if (isFunctionToolCall(toolCall)) {\n blocks.push({\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.function.name,\n input: parseToolArguments(toolCall.function.arguments),\n });\n }\n }\n }\n\n // If no content at all, return empty text block\n if (blocks.length === 0) {\n blocks.push({ type: 'text', text: '' });\n }\n\n return blocks;\n}\n\n/**\n * Maps our Message format to OpenAI's ChatCompletionMessageParam format.\n *\n * Returns an ARRAY: one user message holding several `tool_result` blocks\n * becomes one `tool` message per result (#6607). OpenAI requires a tool message\n * for every `tool_call_id` the assistant issued; sending only the first made\n * strict gateways reject the request with a 400.\n */\nexport function mapMessage(message: Message): ChatCompletionMessageParam[] {\n if (message.role === 'system') {\n return [mapSystemMessage(message)];\n }\n if (message.role === 'user') {\n return mapUserMessage(message);\n }\n return [mapAssistantMessage(message)];\n}\n\n/**\n * Maps a system message.\n */\nfunction mapSystemMessage(message: Message): ChatCompletionMessageParam {\n const content =\n typeof message.content === 'string'\n ? message.content\n : message.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n return { role: 'system', content };\n}\n\n/**\n * Maps a user message.\n */\nfunction mapUserMessage(message: Message): ChatCompletionMessageParam[] {\n if (typeof message.content === 'string') {\n return [{ role: 'user', content: message.content }];\n }\n\n // Tool results become one `tool` message each, in order (#6607).\n const toolResults = message.content.filter(\n (b): b is { type: 'tool_result'; tool_use_id: string; content: string; is_error?: boolean } =>\n b.type === 'tool_result'\n );\n\n if (toolResults.length > 0) {\n return toolResults.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.tool_use_id,\n content: result.content,\n }));\n }\n\n // Map to user message with content array\n const content = message.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'image') {\n return {\n type: 'image_url' as const,\n image_url: {\n url: `data:${block.source.media_type};base64,${block.source.data}`,\n },\n };\n }\n // Fallback for other types\n return { type: 'text' as const, text: '' };\n });\n\n return [{ role: 'user', content }];\n}\n\n/**\n * Maps an assistant message.\n */\nfunction mapAssistantMessage(message: Message): ChatCompletionMessageParam {\n if (typeof message.content === 'string') {\n return { role: 'assistant', content: message.content };\n }\n\n // Check for tool uses in assistant message\n const toolUses = message.content.filter(\n (b): b is { type: 'tool_use'; id: string; name: string; input: unknown } =>\n b.type === 'tool_use'\n );\n\n const textContent = message.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('');\n\n if (toolUses.length > 0) {\n const assistantMessage: ChatCompletionMessageParam = {\n role: 'assistant',\n content: textContent !== '' ? textContent : null,\n tool_calls: toolUses.map((tool) => ({\n id: tool.id,\n type: 'function' as const,\n function: {\n name: tool.name,\n arguments: JSON.stringify(tool.input),\n },\n })),\n };\n return assistantMessage;\n }\n\n return { role: 'assistant', content: textContent };\n}\n\n/**\n * Maps our ToolDefinition to OpenAI's tool format.\n */\nexport function mapTool(tool: ToolDefinition): ChatCompletionTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema,\n },\n };\n}\n\n/**\n * Maps OpenAI API response to our CompletionResponse format.\n */\nexport function mapResponseUsage(response: ChatCompletion): TokenUsage | undefined {\n const u = response.usage;\n // #4439: `?? 0` here synthesised a measurement the vendor never sent. An\n // absent usage block must stay absent so the decision-cost rollup can tell\n // \"zero tokens\" from \"we do not know\".\n if (u === undefined) return undefined;\n const cached = u.prompt_tokens_details?.cached_tokens;\n return {\n inputTokens: u.prompt_tokens,\n outputTokens: u.completion_tokens,\n totalTokens: u.total_tokens,\n ...(cached !== undefined ? { cachedInputTokens: cached } : {}),\n };\n}\n\n/**\n * Maps content delta from stream chunk.\n */\nfunction mapContentDelta(\n delta: OpenAI.Chat.ChatCompletionChunk.Choice.Delta,\n currentIndex: number,\n hasStarted: boolean\n): StreamChunk[] {\n const chunks: StreamChunk[] = [];\n\n if (delta.content !== undefined && delta.content !== null && delta.content !== '') {\n // Start content block if this is the first content\n if (currentIndex === 0 && !hasStarted) {\n chunks.push({\n type: 'content_block_start',\n index: 0,\n contentBlock: { type: 'text', text: '' },\n });\n }\n\n chunks.push({\n type: 'content_block_delta',\n index: currentIndex,\n delta: { type: 'text_delta', text: delta.content },\n });\n }\n\n return chunks;\n}\n\n/**\n * Tool calls being assembled across a stream, keyed by the OpenAI tool index\n * (#6607). OpenAI sends the id and name in the first delta for a call and the\n * JSON `arguments` in fragments after it, so a call is only complete when the\n * choice finishes. Create one per stream with {@link createStreamToolCallState}.\n */\ninterface StreamToolCallState {\n readonly calls: Map<number, { id: string; name: string; args: string }>;\n}\n\n/** A fresh accumulator for one stream (#6607). */\nexport function createStreamToolCallState(): StreamToolCallState {\n return { calls: new Map() };\n}\n\n/**\n * Accumulates tool-call deltas. Emits nothing: the `tool_use` block is emitted\n * once, complete, at the finish chunk (see {@link flushToolCalls}). Emitting it\n * on the first delta, as this used to, fixed its `input` at `{}` (#6607).\n */\nfunction accumulateToolCallsDelta(\n delta: OpenAI.Chat.ChatCompletionChunk.Choice.Delta,\n state: StreamToolCallState\n): void {\n for (const toolCall of delta.tool_calls ?? []) {\n const entry = state.calls.get(toolCall.index) ?? { id: '', name: '', args: '' };\n if (toolCall.id !== undefined) entry.id = toolCall.id;\n if (toolCall.function?.name !== undefined) entry.name = toolCall.function.name;\n if (toolCall.function?.arguments !== undefined) entry.args += toolCall.function.arguments;\n state.calls.set(toolCall.index, entry);\n }\n}\n\n/** Emit each assembled tool call as one complete `tool_use` block, in index order. */\nfunction flushToolCalls(state: StreamToolCallState): StreamChunk[] {\n const chunks: StreamChunk[] = [...state.calls.entries()]\n .sort(([a], [b]) => a - b)\n .map(([index, call]) => ({\n type: 'content_block_start' as const,\n index,\n contentBlock: {\n type: 'tool_use' as const,\n id: call.id,\n name: call.name,\n input: call.args === '' ? {} : parseToolArguments(call.args),\n },\n }));\n state.calls.clear();\n return chunks;\n}\n\n/**\n * Maps finish reason from stream chunk.\n */\nfunction mapFinishChunks(\n choice: ChatCompletionChunk.Choice,\n chunk: ChatCompletionChunk,\n currentIndex: number,\n toolCalls: StreamToolCallState\n): StreamChunk[] {\n const chunks: StreamChunk[] = [];\n\n if (choice.finish_reason !== null) {\n chunks.push(...flushToolCalls(toolCalls));\n\n // End current content block\n chunks.push({\n type: 'content_block_stop',\n index: currentIndex,\n });\n\n // Emit message_delta with stop reason.\n //\n // NO `usage` on this path. OpenAI populates `chunk.usage` on a streaming\n // response only when the request sets `stream_options: { include_usage:\n // true }`, and nothing in this tree does — so both `??` fallbacks always\n // took the `0` branch and every stream emitted\n // `{inputTokens: 0, outputTokens: 0, totalTokens: 0}`: a usage block in\n // which nothing whatsoever was measured.\n //\n // `inputTokensMeasured: false` covered only the first of those three. Its\n // own contract is \"whether `inputTokens` is a measurement\", and there is no\n // `outputTokensMeasured`, so a consumer honouring the flag correctly\n // discounted `inputTokens` and then read `outputTokens: 0` as a measured\n // zero. That is the #4439 policy this violated, stated on the field itself:\n // \"Where NOTHING is known, prefer omitting `usage` entirely.\" The SDK\n // adapter's stream path already does exactly that (#4835), for the same\n // reason.\n chunks.push({\n type: 'message_delta',\n delta: { stop_reason: mapStopReason(choice.finish_reason) },\n // A stream whose usage IS reported keeps it — when `include_usage` is\n // wired, this is the branch that carries a real measurement.\n ...(chunk.usage !== undefined && chunk.usage !== null\n ? {\n usage: {\n // OpenAI still omits prompt_tokens on the final chunk (#4835).\n inputTokens: 0,\n inputTokensMeasured: false,\n outputTokens: chunk.usage.completion_tokens,\n totalTokens: chunk.usage.total_tokens,\n },\n }\n : {}),\n });\n\n // Emit message_stop\n chunks.push({ type: 'message_stop' });\n }\n\n return chunks;\n}\n\n/**\n * Maps OpenAI stream chunks to our StreamChunk format.\n */\nexport function mapStreamChunk(\n chunk: ChatCompletionChunk,\n currentIndex: number,\n hasStarted: boolean,\n toolCalls: StreamToolCallState\n): StreamChunk[] {\n const chunks: StreamChunk[] = [];\n const choice = chunk.choices[0];\n\n // Emit message_start on first chunk\n if (!hasStarted) {\n chunks.push({\n type: 'message_start',\n message: { model: chunk.model },\n });\n }\n\n if (choice === undefined) {\n return chunks;\n }\n\n const delta = choice.delta;\n\n // Map content delta\n chunks.push(...mapContentDelta(delta, currentIndex, hasStarted));\n\n // Accumulate tool calls; they are emitted whole at the finish chunk.\n accumulateToolCallsDelta(delta, toolCalls);\n\n // Map finish reason\n chunks.push(...mapFinishChunks(choice, chunk, currentIndex, toolCalls));\n\n return chunks;\n}\n","/** Wire translation for the gateway's opt-in Responses surface (#7150). */\nimport type {\n ChatCompletion,\n ChatCompletionMessageParam,\n ChatCompletionContentPart,\n ChatCompletionCreateParamsNonStreaming,\n} from 'openai/resources/chat/completions';\nimport type {\n Response,\n ResponseCreateParamsNonStreaming,\n ResponseInputItem,\n ResponseInputContent,\n ResponseUsage,\n} from 'openai/resources/responses/responses';\nimport { ErrorCode, ModelError } from '../core/index.js';\nimport type OpenAI from 'openai';\nimport type { DroppedParam } from './optional-params.js';\n\ninterface ResponsesCompletionPlan {\n readonly params: ChatCompletionCreateParamsNonStreaming;\n readonly dropped: readonly DroppedParam[];\n}\n\n/** Send Responses input and report requested parameters this surface cannot send. */\nexport async function completeResponses(\n client: OpenAI,\n plan: ResponsesCompletionPlan,\n signal?: AbortSignal\n): Promise<{ response: ChatCompletion; dropped: readonly DroppedParam[] }> {\n const response = await client.responses.create(buildResponsesParams(plan.params), {\n signal,\n });\n const dropped: readonly DroppedParam[] =\n plan.params.stop === undefined\n ? plan.dropped\n : [\n ...plan.dropped,\n {\n param: 'stop',\n reason: 'The Responses API does not support stop sequences; omitted.',\n severity: 'behavioral',\n },\n ];\n return { response: responsesToChatCompletion(response), dropped };\n}\n\n/** Build Responses parameters from the same model/optional-parameter plan as chat. */\nexport function buildResponsesParams(\n chat: ChatCompletionCreateParamsNonStreaming\n): ResponseCreateParamsNonStreaming {\n const params: ResponseCreateParamsNonStreaming = {\n model: chat.model,\n input: chat.messages.flatMap(mapInputMessage),\n ...(chat.max_completion_tokens !== undefined && {\n max_output_tokens: chat.max_completion_tokens,\n }),\n ...(chat.temperature !== undefined && { temperature: chat.temperature }),\n };\n if (chat.tools !== undefined) {\n params.tools = chat.tools.flatMap((tool) =>\n tool.type === 'function'\n ? [\n {\n type: 'function' as const,\n name: tool.function.name,\n parameters: tool.function.parameters ?? {},\n strict: tool.function.strict ?? false,\n ...(tool.function.description !== undefined && {\n description: tool.function.description,\n }),\n },\n ]\n : []\n );\n }\n if (chat.response_format?.type === 'json_object') {\n params.text = { format: { type: 'json_object' } };\n } else if (chat.response_format?.type === 'json_schema') {\n params.text = {\n format: {\n type: 'json_schema',\n name: chat.response_format.json_schema.name,\n schema: chat.response_format.json_schema.schema ?? {},\n ...(chat.response_format.json_schema.strict !== undefined && {\n strict: chat.response_format.json_schema.strict,\n }),\n },\n };\n }\n return params;\n}\n\nfunction mapInputMessage(message: ChatCompletionMessageParam): ResponseInputItem[] {\n if (message.role === 'tool')\n return [\n {\n type: 'function_call_output',\n call_id: message.tool_call_id,\n output:\n typeof message.content === 'string' ? message.content : JSON.stringify(message.content),\n },\n ];\n if (message.role === 'function') return [];\n const items: ResponseInputItem[] = [];\n if (message.content !== null && message.content !== undefined) {\n items.push({\n role: message.role,\n content:\n typeof message.content === 'string'\n ? [{ type: 'input_text', text: message.content }]\n : message.content.flatMap(mapInputContent),\n });\n }\n items.push(...mapInputToolCalls(message));\n return items;\n}\n\nfunction mapInputToolCalls(message: ChatCompletionMessageParam): ResponseInputItem[] {\n if (message.role !== 'assistant') return [];\n return (message.tool_calls ?? []).flatMap((call) =>\n call.type === 'function'\n ? [\n {\n type: 'function_call',\n call_id: call.id,\n name: call.function.name,\n arguments: call.function.arguments,\n },\n ]\n : []\n );\n}\n\nfunction mapInputContent(\n part: ChatCompletionContentPart | { type: 'refusal'; refusal: string }\n): ResponseInputContent[] {\n if (part.type === 'text') return [{ type: 'input_text', text: part.text }];\n if (part.type === 'image_url')\n return [\n {\n type: 'input_image',\n image_url: part.image_url.url,\n detail: part.image_url.detail ?? 'auto',\n },\n ];\n return [];\n}\n\n/** Reuse chat's answer validation, tool parsing, token accounting and stop reasons. */\nexport function responsesToChatCompletion(response: Response): ChatCompletion {\n if (response.status === 'failed' || response.status === 'cancelled') {\n throw new ModelError(response.error?.message ?? `Responses request ${response.status}`, {\n code: ErrorCode.MODEL_ERROR,\n context: { reason: response.status },\n });\n }\n const usage = responseUsage(response.usage);\n return {\n id: response.id,\n model: response.model,\n object: 'chat.completion',\n created: response.created_at,\n choices: responseChoices(response),\n ...(usage !== undefined && { usage }),\n };\n}\n\nfunction responseText(response: Response): string {\n return response.output\n .flatMap((item) =>\n item.type === 'message'\n ? item.content.filter((part) => part.type === 'output_text').map((part) => part.text)\n : []\n )\n .join('');\n}\n\nfunction responseToolCalls(\n response: Response\n): NonNullable<ChatCompletion.Choice['message']['tool_calls']> {\n return response.output.flatMap((item) =>\n item.type === 'function_call'\n ? [\n {\n id: item.call_id,\n type: 'function' as const,\n function: { name: item.name, arguments: item.arguments },\n },\n ]\n : []\n );\n}\n\nfunction responseChoices(response: Response): ChatCompletion.Choice[] {\n const text = responseText(response);\n const calls = responseToolCalls(response);\n const refused = responseRefused(response);\n const finishReason = refused\n ? 'content_filter'\n : response.status === 'incomplete'\n ? 'length'\n : calls.length > 0\n ? 'tool_calls'\n : 'stop';\n // No output is unmeasured, never a successful answer. Keep a length choice\n // for the shared reasoning-budget exhaustion classifier.\n if (text === '' && calls.length === 0 && !refused && finishReason !== 'length') return [];\n return [\n {\n index: 0,\n finish_reason: finishReason,\n logprobs: null,\n message: {\n role: 'assistant',\n content: text,\n refusal: null,\n ...(calls.length > 0 && { tool_calls: calls }),\n },\n },\n ];\n}\n\nfunction responseRefused(response: Response): boolean {\n return (\n response.incomplete_details?.reason === 'content_filter' ||\n response.output.some(\n (item) => item.type === 'message' && item.content.some((part) => part.type === 'refusal')\n )\n );\n}\n\nfunction responseUsage(usage: Partial<ResponseUsage> | null | undefined): ChatCompletion['usage'] {\n if (\n usage === undefined ||\n usage === null ||\n typeof usage.input_tokens !== 'number' ||\n typeof usage.output_tokens !== 'number' ||\n typeof usage.total_tokens !== 'number'\n )\n return undefined;\n return {\n prompt_tokens: usage.input_tokens,\n completion_tokens: usage.output_tokens,\n total_tokens: usage.total_tokens,\n ...(usage.input_tokens_details !== undefined && {\n prompt_tokens_details: { cached_tokens: usage.input_tokens_details.cached_tokens },\n }),\n ...(usage.output_tokens_details !== undefined && {\n completion_tokens_details: { reasoning_tokens: usage.output_tokens_details.reasoning_tokens },\n }),\n };\n}\n","/** Map Responses SSE events to the existing adapter streaming contract. */\nimport type { Response, ResponseStreamEvent } from 'openai/resources/responses/responses';\nimport type { CompletionResponse, StreamChunk } from '../core/index.js';\nimport { ErrorCode, ModelError } from '../core/index.js';\n\n/** Tool argument fragments are emitted as a completed tool block, as in chat. */\nexport async function* mapResponsesStream(\n events: AsyncIterable<ResponseStreamEvent>,\n mapResponse: (response: Response) => CompletionResponse\n): AsyncIterable<StreamChunk> {\n const blocks = new Map<string, number>();\n let completed = false;\n for await (const event of events) {\n assertStreamEvent(event);\n if (event.type === 'response.completed' || event.type === 'response.incomplete') {\n const response = mapResponse(event.response);\n yield {\n type: 'message_delta',\n delta: { stop_reason: response.stopReason },\n ...(response.usage !== undefined && { usage: response.usage }),\n };\n yield { type: 'message_stop' };\n completed = true;\n } else {\n yield* mapContentEvent(event, blocks);\n }\n }\n if (!completed)\n throw new ModelError('Responses stream ended without a terminal response', {\n code: ErrorCode.MODEL_ERROR,\n });\n}\n\nfunction assertStreamEvent(event: ResponseStreamEvent): void {\n if (event.type === 'response.failed')\n throw new ModelError(event.response.error?.message ?? 'Responses stream failed', {\n code: ErrorCode.MODEL_ERROR,\n });\n if (event.type === 'error') throw new ModelError(event.message, { code: ErrorCode.MODEL_ERROR });\n if (event.type === 'response.refusal.delta' || event.type === 'response.refusal.done') {\n throw new ModelError('Responses reply was refused', { code: ErrorCode.MODEL_ERROR });\n }\n}\n\nfunction mapContentEvent(event: ResponseStreamEvent, blocks: Map<string, number>): StreamChunk[] {\n switch (event.type) {\n case 'response.created':\n return [{ type: 'message_start', message: { model: event.response.model } }];\n case 'response.output_text.delta':\n return textDeltaChunks(event, blocks);\n case 'response.output_text.done': {\n const index = blocks.get(textBlockKey(event));\n return index === undefined ? [] : [{ type: 'content_block_stop', index }];\n }\n case 'response.output_item.done': {\n if (event.item.type !== 'function_call') return [];\n const index = blocks.size;\n blocks.set(`tool:${String(event.output_index)}`, index);\n return [\n {\n type: 'content_block_start',\n index,\n contentBlock: {\n type: 'tool_use',\n id: event.item.call_id,\n name: event.item.name,\n input: parseArguments(event.item.arguments),\n },\n },\n { type: 'content_block_stop', index },\n ];\n }\n default:\n // Metadata, reasoning, and tool-argument fragments carry no public chunk.\n return [];\n }\n}\n\nfunction textBlockKey(event: { output_index: number; content_index: number }): string {\n return `${String(event.output_index)}:${String(event.content_index)}`;\n}\n\nfunction textDeltaChunks(\n event: Extract<ResponseStreamEvent, { type: 'response.output_text.delta' }>,\n blocks: Map<string, number>\n): StreamChunk[] {\n const key = textBlockKey(event);\n const chunks: StreamChunk[] = [];\n let index = blocks.get(key);\n if (index === undefined) {\n index = blocks.size;\n blocks.set(key, index);\n chunks.push({ type: 'content_block_start', index, contentBlock: { type: 'text', text: '' } });\n }\n chunks.push({\n type: 'content_block_delta',\n index,\n delta: { type: 'text_delta', text: event.delta },\n });\n return chunks;\n}\n\nfunction parseArguments(argumentsText: string): unknown {\n try {\n return JSON.parse(argumentsText) as unknown;\n } catch {\n return { _raw: argumentsText };\n }\n}\n","/**\n * Per-call gateway usage recording shared by discovered and fallback models.\n * Verification belongs to this adapter's selection, including during failover.\n * @module adapters/gateway-usage-recording\n */\nimport type {\n IModelAdapter,\n CompletionRequest,\n CompletionResponse,\n ModelError,\n ModelMetadata,\n Result,\n} from '../core/index.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type { EndpointArmId } from '../cli-adapters/types-core.js';\nimport { gatewayCostDetail } from '../cli-adapters/budget-arm-cost.js';\nimport { recordUsageEvent } from '../learning/usage-log.js';\n\n/** Recording wrappers are replaceable views, never nested writers. */\nconst recordingSources = new WeakMap<IModelAdapter, IModelAdapter>();\n\ntype UsageRecordingAdapter = IModelAdapter & { readonly gatewayArm: EndpointArmId };\n\n/**\n * Wrap a gateway model adapter so that successful + failed `complete()`\n * calls append a UsageEvent to the on-disk usage log. Stream calls aren't\n * yet instrumented (a future PR can add streaming-aware recording).\n *\n * The returned object preserves the IModelAdapter contract identically;\n * downstream code can't tell the difference except that one extra JSONL\n * line gets written per call. The line is priced by `gatewayArm`'s\n * `NEXUS_GATEWAY_COST` declaration ({@link gatewayCostDetail}, #4392 step 4):\n * an undeclared gateway records `priced: false`, never the model id's vendor\n * list price. Verification is captured at selection time: true only for a\n * discovery match, false after failed discovery, absent when unmeasured.\n * Shared by discovered models and the custom-openai compatibility alias.\n */\nexport function withGatewayUsageRecording(\n inner: IModelAdapter,\n gatewayArm: EndpointArmId,\n modelVerified?: boolean,\n providerId?: string\n): UsageRecordingAdapter {\n inner = recordingSources.get(inner) ?? inner;\n const recordedProviderId = providerId ?? inner.providerId;\n const wrapped: UsageRecordingAdapter = {\n gatewayArm,\n providerId: recordedProviderId,\n modelId: inner.modelId,\n capabilities: inner.capabilities,\n countTokens: (text) => inner.countTokens(text),\n validateConfig: () => inner.validateConfig(),\n stream: (request) => inner.stream(request),\n async complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>> {\n const start = getTimeProvider().now();\n const result = await inner.complete(request);\n const latencyMs = getTimeProvider().now() - start;\n try {\n if (result.ok) {\n const u = result.value.usage;\n // No vendor usage ⇒ nothing to record. Zero-filling here would write\n // a fabricated measurement into the usage log, which is the defect\n // #4439 exists to remove — a lost latency datapoint is the cheaper\n // loss than a false token count.\n if (u === undefined) return result;\n // Declaration-first pricing with provenance (#4165, #4392 step 4):\n // `priced: false` marks the $0 as UNPRICED (unmeasured), not a real $0.\n const cost = gatewayCostDetail(gatewayArm, inner.modelId, u.inputTokens, u.outputTokens);\n recordUsageEvent({\n timestamp: new Date().toISOString(),\n modelId: inner.modelId,\n providerId: recordedProviderId,\n inputTokens: u.inputTokens,\n outputTokens: u.outputTokens,\n usdCost: cost.costUsd,\n latencyMs,\n success: true,\n priced: cost.priced,\n ...(modelVerified !== undefined && { modelVerified }),\n ...(cost.priced ? { priceSource: cost.resolvedId } : {}),\n });\n } else {\n recordFailedCall(inner, latencyMs, result.error.code, modelVerified, recordedProviderId);\n }\n } catch {\n // Telemetry must not break user calls.\n }\n return result;\n },\n };\n recordingSources.set(wrapped, inner);\n attachListModels(wrapped, inner);\n return wrapped;\n}\n\n/** The usage line for a failed call: no tokens, no cost — the error code is the datum. */\nfunction recordFailedCall(\n inner: IModelAdapter,\n latencyMs: number,\n errorCode: string,\n modelVerified: boolean | undefined,\n providerId: string\n): void {\n recordUsageEvent({\n timestamp: new Date().toISOString(),\n modelId: inner.modelId,\n providerId,\n inputTokens: 0,\n outputTokens: 0,\n usdCost: 0,\n latencyMs,\n success: false,\n errorCode,\n ...(modelVerified !== undefined && { modelVerified }),\n });\n}\n\n/**\n * (#2540) Forward `listModels` through the wrapper when the inner adapter\n * exposes one. Only attach when defined so the wrapper's `listModels?:`\n * hint stays accurate for the resolver. The inner reference is captured\n * by closure so the forwarded call binds `this` to the inner adapter.\n */\nfunction attachListModels(wrapped: IModelAdapter, inner: IModelAdapter): void {\n const list = inner.listModels?.bind(inner);\n if (list === undefined) return;\n wrapped.listModels = (): Promise<readonly ModelMetadata[]> => list();\n}\n","/**\n * opencode.json gateway-config bridge (#2503, child 3 of epic #2500).\n *\n * When nexus-agents runs as an MCP loaded by OpenCode (typically inside a\n * Docker sandbox), OpenCode's `opencode.json` already declares the\n * OpenAI-compatible gateway the harness uses. Reading it from there saves\n * the operator from re-declaring the same `baseURL` + `apiKey` as\n * NEXUS_OPENAI_COMPAT_* env vars.\n *\n * Scope (per direction discussion 2026-05-09):\n * - **Only** reads `providers.openai-compat.options.{baseURL, apiKey}`.\n * Does NOT read OpenCode's MCP config, model list, logging, or other\n * settings. nexus-agents' own behaviour stays driven by\n * `nexus-agents.yaml` + `NEXUS_*` env vars.\n * - Resolves OpenCode's `{env:VAR}` interpolation in the apiKey field.\n * - Returns `null` on any failure path (missing file, parse error,\n * missing fields, unset interpolated env var) — caller falls back to\n * env-var precedence; we don't throw.\n *\n * Precedence (applied in `openai-compat-adapter.ts`):\n * 1. `NEXUS_OPENAI_COMPAT_URL` + `NEXUS_OPENAI_COMPAT_KEY` env vars (if both set)\n * 2. `NEXUS_OPENCODE_CONFIG` → `opencode.json` → `providers.openai-compat`\n * 3. Unconfigured → `null`, no adapter registered\n *\n * Sanitised logging (#4392 increment 3 tightened it): never log the resolved\n * apiKey, never log file contents — Node's JSON parse error embeds a source\n * snippet, so only the error NAME is logged — and log the gateway's hostname\n * rather than the baseURL, which can carry userinfo.\n *\n * @module config/opencode-bridge\n */\n\nimport { readFileSync } from 'node:fs';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { hostnameOf } from '../adapters/sdk/gateway-env.js';\n\nconst defaultLogger = createLogger({ component: 'opencode-bridge' });\n\nexport interface OpencodeGatewayConfig {\n readonly baseURL: string;\n readonly apiKey: string;\n}\n\n/**\n * Read `providers.openai-compat.options.{baseURL, apiKey}` from the given\n * opencode.json path. Returns `null` on any failure — the caller falls\n * back to env-var precedence.\n */\nexport function readOpencodeGateway(\n path: string,\n logger: ILogger = defaultLogger\n): OpencodeGatewayConfig | null {\n const raw = readFileOrNull(path, logger);\n if (raw === null) return null;\n\n const parsed = parseJsonOrNull(raw, path, logger);\n if (parsed === null) return null;\n\n const options = extractOpenAICompatOptions(parsed);\n if (options === null) {\n logger.debug('opencode.json has no providers.openai-compat.options block', { path });\n return null;\n }\n\n const baseURL = typeof options.baseURL === 'string' ? options.baseURL.trim() : '';\n const apiKeyRaw = typeof options.apiKey === 'string' ? options.apiKey.trim() : '';\n if (baseURL === '' || apiKeyRaw === '') {\n logger.warn('opencode.json providers.openai-compat missing baseURL or apiKey', { path });\n return null;\n }\n\n const apiKey = resolveEnvInterpolation(apiKeyRaw);\n if (apiKey === null) {\n logger.warn(\n 'opencode.json apiKey references an env var that is not set; gateway not configured',\n { path }\n );\n return null;\n }\n\n logger.info('Gateway config sourced from opencode.json', { host: hostnameOf(baseURL), path });\n return { baseURL, apiKey };\n}\n\nfunction readFileOrNull(path: string, logger: ILogger): string | null {\n try {\n return readFileSync(path, 'utf8');\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.debug('Could not read opencode.json', { path, error: msg });\n return null;\n }\n}\n\n/**\n * Logs the error NAME only. On Node 22 a `SyntaxError` from `JSON.parse`\n * quotes the offending source (`... \"{\"apiKey\": sk-...\" is not valid JSON`),\n * so the message is a channel for the file's contents (#4392 increment 3).\n */\nfunction parseJsonOrNull(raw: string, path: string, logger: ILogger): unknown {\n try {\n return JSON.parse(raw);\n } catch (err: unknown) {\n const name = err instanceof Error ? err.name : 'unknown error';\n logger.warn('opencode.json is not valid JSON; ignoring', { path, error: name });\n return null;\n }\n}\n\n/**\n * Pull `providers.openai-compat.options` out of the parsed JSON without\n * coupling to a Zod schema. OpenCode's config has many keys we don't\n * care about; we only navigate to the one we need.\n */\nfunction extractOpenAICompatOptions(\n parsed: unknown\n): { baseURL?: unknown; apiKey?: unknown } | null {\n if (typeof parsed !== 'object' || parsed === null) return null;\n const root = parsed as { providers?: unknown };\n const providers = root.providers;\n if (typeof providers !== 'object' || providers === null) return null;\n const provider = (providers as Record<string, unknown>)['openai-compat'];\n if (typeof provider !== 'object' || provider === null) return null;\n const options = (provider as { options?: unknown }).options;\n if (typeof options !== 'object' || options === null) return null;\n return options;\n}\n\n/**\n * Resolve OpenCode's `{env:VAR}` interpolation. Only the literal pattern\n * is supported (no shell expansion, no defaults). Returns the string as-is\n * when no interpolation is present; returns `null` when the referenced\n * env var is not set.\n */\nfunction resolveEnvInterpolation(value: string): string | null {\n const match = /^\\{env:([A-Z0-9_]+)\\}$/.exec(value);\n if (match === null) return value;\n const envName = match[1];\n if (envName === undefined) return null;\n const resolved = process.env[envName];\n if (resolved === undefined || resolved === '') return null;\n return resolved;\n}\n","/** Canonical validation and bounded host guard for per-model gateway clients. */\nimport { ConfigError } from '../core/index.js';\nimport { validateCustomApiBaseUrl } from './sdk/custom-api-validation.js';\nimport {\n checkGatewayHost,\n GatewayHostRefusedError,\n GATEWAY_HOST_LOOKUP_TIMED_OUT,\n} from './gateway-host-status.js';\n\n/** Validate before construction, without exposing URL credentials in errors. */\nexport function validateOpenAICompatBaseUrl(baseUrl: string | undefined): string {\n const validated = validateCustomApiBaseUrl(baseUrl);\n if (!validated.ok) throw validated.error;\n return validated.value.toString();\n}\n\n/** Cache an allowed host check; refusals remain retryable and never send HTTP. */\nexport function guardedGatewayFetch(baseUrl: string): typeof fetch {\n let allowed: Promise<void> | undefined;\n const check = async (): Promise<void> => {\n const status = await checkGatewayHost(baseUrl);\n if (status.state === 'refused_private_host') throw new GatewayHostRefusedError(status);\n if (status.state === 'lookup_timed_out') {\n throw new ConfigError(`${GATEWAY_HOST_LOOKUP_TIMED_OUT} (host ${status.host})`);\n }\n };\n return async (input, init) => {\n allowed ??= check();\n try {\n await allowed;\n } catch (error: unknown) {\n allowed = undefined;\n throw error;\n }\n return fetch(input, init);\n };\n}\n","/**\n * Corporate-network transport for in-process OpenAI-compatible gateway calls\n * (#6608): which header carries the key, extra static headers, and the proxy.\n *\n * Applies to the gateway path — model discovery and every per-model\n * completion built by `openai-compat-adapter.ts` — including the\n * `custom-openai` alias, which uses the same client path (#7150).\n * Other in-process SDK clients (the direct vendor adapters) are untouched.\n *\n * **Proxy — measured, not assumed.** On Node 22.22.3, neither the global\n * `fetch` nor the `openai` SDK (which calls it) honours `HTTP_PROXY` /\n * `HTTPS_PROXY` / `NO_PROXY` unless the process was STARTED with\n * `NODE_USE_ENV_PROXY=1` (a loopback proxy saw no request without it, and\n * CONNECT tunnels with it). The engines floor is 22.5, which predates that\n * variable, so the gateway gets an explicit undici `ProxyAgent` instead,\n * selected here from the standard variables.\n *\n * **Secrets.** The key, header values and the proxy URL (which can carry\n * `user:password@`) never reach a log line: warnings name the variable and\n * the reason only.\n *\n * @module adapters/gateway-http\n */\n\nimport { BlockList, isIP } from 'node:net';\n\nimport { ProxyAgent } from 'undici';\nimport type { ILogger } from '../core/index.js';\nimport type { OpenAIAdapterConfig } from './openai-types.js';\n\n/** Header that carries the gateway key instead of `Authorization: Bearer`. */\nconst OPENAI_COMPAT_AUTH_HEADER_ENV = 'NEXUS_OPENAI_COMPAT_AUTH_HEADER';\n/** Extra static headers sent on every gateway request: `Name=value,Name2=value2`. */\nconst OPENAI_COMPAT_EXTRA_HEADERS_ENV = 'NEXUS_OPENAI_COMPAT_EXTRA_HEADERS';\n\n/** RFC 9110 `token`: the only legal header-name characters. */\nconst HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\n/** Control characters (CR/LF included) are never legal in a header value. */\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/;\n\n/** Transport options resolved from the environment for one gateway base URL. */\nexport interface GatewayTransport {\n /** Explicit API surface; the custom-openai alias resolves its own env setting. */\n readonly apiSurface?: 'chat' | 'responses';\n /** Header carrying the key; absent means the SDK default, `Authorization: Bearer`. */\n readonly authHeader?: string;\n /** Static headers added to every request; absent means none. */\n readonly extraHeaders?: Readonly<Record<string, string>>;\n /** Proxy for the gateway's scheme, after `NO_PROXY`; absent means direct. */\n readonly proxyUrl?: string;\n}\n\nexport type ExtraHeadersParse =\n | { readonly ok: true; readonly headers: Readonly<Record<string, string>> }\n | { readonly ok: false; readonly reason: string };\n\n/**\n * Parse `Name=value,Name2=value2`. Whitespace around names, values and\n * entries is trimmed; an empty entry (a trailing comma) is skipped. The whole\n * value is refused — not partially applied — on a newline or other control\n * character, an entry without `=`, an illegal or duplicate name, or an\n * `Authorization` entry (the key has exactly one place: the auth header\n * option). Reasons never quote a value.\n */\nexport function parseGatewayExtraHeaders(raw: string | undefined): ExtraHeadersParse {\n const headers: Record<string, string> = {};\n // Unset or blank is the named empty case: no extra headers, not an error.\n if (raw === undefined || raw.trim() === '') return { ok: true, headers };\n if (/[\\r\\n]/.test(raw)) return { ok: false, reason: 'contains a newline' };\n const seen = new Set<string>();\n for (const [index, entry] of raw.split(',').entries()) {\n if (entry.trim() === '') continue;\n const at = `entry ${String(index + 1)}`;\n const parsed = parseHeaderEntry(entry, at);\n if ('reason' in parsed) return { ok: false, reason: parsed.reason };\n const key = parsed.name.toLowerCase();\n if (seen.has(key)) return { ok: false, reason: `${at} is a duplicate header name` };\n seen.add(key);\n headers[parsed.name] = parsed.value;\n }\n return { ok: true, headers };\n}\n\n/** One `Name=value` entry, or why it is refused (`at` locates it, never quoting it). */\nfunction parseHeaderEntry(\n entry: string,\n at: string\n): { readonly name: string; readonly value: string } | { readonly reason: string } {\n const eq = entry.indexOf('=');\n if (eq < 0) return { reason: `${at} has no '='` };\n const name = entry.slice(0, eq).trim();\n const value = entry.slice(eq + 1).trim();\n if (!HEADER_NAME.test(name)) return { reason: `${at} has an illegal header name` };\n if (CONTROL_CHARS.test(value)) return { reason: `${at} value contains a control character` };\n if (name.toLowerCase() === 'authorization') {\n return { reason: `${at} sets Authorization; use ${OPENAI_COMPAT_AUTH_HEADER_ENV}` };\n }\n return { name, value };\n}\n\n/**\n * The reason `raw` cannot name the auth header, or `undefined` when it can.\n * `Authorization` itself is legal and means the default bearer scheme.\n */\nfunction authHeaderRejection(raw: string): string | undefined {\n return HEADER_NAME.test(raw) ? undefined : 'not a legal header name';\n}\n\n/** First non-empty value among `names`, trimmed. */\nfunction firstSet(env: NodeJS.ProcessEnv, names: readonly string[]): string | undefined {\n for (const name of names) {\n const value = env[name]?.trim();\n if (value !== undefined && value !== '') return value;\n }\n return undefined;\n}\n\n/** Split a `NO_PROXY` entry into host and optional port (`[v6]:port` aware). */\nfunction splitNoProxyEntry(entry: string): { host: string; port: string | undefined } {\n const bracketed = /^\\[([^\\]]+)\\](?::(\\d+))?$/.exec(entry);\n if (bracketed !== null) return { host: bracketed[1] ?? '', port: bracketed[2] };\n const parts = entry.split(':');\n if (parts.length === 2 && /^\\d+$/.test(parts[1] ?? '')) {\n return { host: parts[0] ?? '', port: parts[1] };\n }\n return { host: entry, port: undefined };\n}\n\n/**\n * `NO_PROXY` match. `*` matches everything. A host-name entry matches the host\n * itself and its subdomains (a leading `.` or `*.` is optional). An IP host is\n * matched only by an IP entry of its own family, as a literal or a CIDR range\n * (`10.0.0.0/8`, `fd00::/8`), never as a domain suffix, so `2.3` does not\n * exempt `10.1.2.3`. A host name is not resolved to match an IP entry. Any\n * entry may carry a `:port` (IPv6 bracketed: `[fd00::1]:8443`), and then\n * matches that port only.\n */\nfunction matchesNoProxy(url: URL, noProxy: string): boolean {\n const host = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n const port = url.port !== '' ? url.port : url.protocol === 'https:' ? '443' : '80';\n // No entries exempt nothing: an empty list means \"proxy everything\".\n return noProxy\n .split(/[\\s,]+/)\n .some((raw) => noProxyEntryMatches(raw.trim().toLowerCase(), host, port));\n}\n\n/** One lowercased `NO_PROXY` entry against a host and its effective port. */\nfunction noProxyEntryMatches(entry: string, host: string, port: string): boolean {\n if (entry === '') return false;\n if (entry === '*') return true;\n const parsed = splitNoProxyEntry(entry);\n if (parsed.port !== undefined && parsed.port !== port) return false;\n const hostFamily = isIP(host);\n if (hostFamily === 4 || hostFamily === 6) {\n return ipEntryMatches(parsed.host, host, hostFamily);\n }\n const suffix = parsed.host.replace(/^\\*?\\./, '');\n return suffix !== '' && (host === suffix || host.endsWith(`.${suffix}`));\n}\n\n/**\n * An IP-literal or CIDR entry against an IP host of `family`. An entry of the\n * other family, a malformed address, or a prefix outside the family's width\n * matches nothing.\n */\nfunction ipEntryMatches(entry: string, host: string, family: 4 | 6): boolean {\n const type = family === 4 ? 'ipv4' : 'ipv6';\n const slash = entry.indexOf('/');\n const address = slash === -1 ? entry : entry.slice(0, slash);\n if (isIP(address) !== family) return false;\n const range = new BlockList();\n if (slash === -1) {\n range.addAddress(address, type);\n return range.check(host, type);\n }\n const prefixText = entry.slice(slash + 1);\n const prefix = Number(prefixText);\n if (!/^\\d{1,3}$/.test(prefixText) || prefix > (family === 4 ? 32 : 128)) return false;\n range.addSubnet(address, prefix, type);\n return range.check(host, type);\n}\n\n/**\n * The proxy URL a request to `baseUrl` should use, or `undefined` for direct.\n * `https:` reads `https_proxy` then `HTTPS_PROXY`; `http:` reads `http_proxy`\n * then `HTTP_PROXY` (undici's order); `no_proxy` / `NO_PROXY` exempt a host.\n * Not validated here — {@link readGatewayTransport} does that.\n */\nexport function gatewayProxyUrl(baseUrl: string, env: NodeJS.ProcessEnv): string | undefined {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch {\n return undefined;\n }\n const names =\n url.protocol === 'https:'\n ? ['https_proxy', 'HTTPS_PROXY']\n : url.protocol === 'http:'\n ? ['http_proxy', 'HTTP_PROXY']\n : [];\n const proxy = firstSet(env, names);\n if (proxy === undefined) return undefined;\n const noProxy = firstSet(env, ['no_proxy', 'NO_PROXY']);\n return noProxy !== undefined && matchesNoProxy(url, noProxy) ? undefined : proxy;\n}\n\n/** Why `proxy` cannot be used, or `undefined` when it can. */\nfunction proxyRejection(proxy: string): string | undefined {\n try {\n const { protocol } = new URL(proxy);\n return protocol === 'http:' || protocol === 'https:'\n ? undefined\n : 'only http:// and https:// proxies are supported';\n } catch {\n return 'not a valid URL';\n }\n}\n\n/** The auth header option, validated; `undefined` means the bearer default. */\nfunction readAuthHeader(env: NodeJS.ProcessEnv, logger: ILogger): string | undefined {\n const raw = env[OPENAI_COMPAT_AUTH_HEADER_ENV]?.trim();\n if (raw === undefined || raw === '') return undefined;\n const reason = authHeaderRejection(raw);\n if (reason !== undefined) {\n logger.warn(\n `${OPENAI_COMPAT_AUTH_HEADER_ENV} ignored (${reason}); the key is sent as a bearer token`,\n {\n env: OPENAI_COMPAT_AUTH_HEADER_ENV,\n reason,\n }\n );\n return undefined;\n }\n return raw.toLowerCase() === 'authorization' ? undefined : raw;\n}\n\n/** The extra headers, validated against the auth header too; `undefined` means none. */\nfunction readExtraHeaders(\n env: NodeJS.ProcessEnv,\n authHeader: string | undefined,\n logger: ILogger\n): Readonly<Record<string, string>> | undefined {\n const parsed = parseGatewayExtraHeaders(env[OPENAI_COMPAT_EXTRA_HEADERS_ENV]);\n let reason = parsed.ok ? undefined : parsed.reason;\n if (parsed.ok && authHeader !== undefined) {\n const clash = Object.keys(parsed.headers).some(\n (name) => name.toLowerCase() === authHeader.toLowerCase()\n );\n if (clash) reason = `sets ${OPENAI_COMPAT_AUTH_HEADER_ENV}'s header, which carries the key`;\n }\n if (reason !== undefined) {\n logger.warn(\n `${OPENAI_COMPAT_EXTRA_HEADERS_ENV} ignored (${reason}); no extra headers are sent`,\n {\n env: OPENAI_COMPAT_EXTRA_HEADERS_ENV,\n reason,\n }\n );\n return undefined;\n }\n return parsed.ok && Object.keys(parsed.headers).length > 0 ? parsed.headers : undefined;\n}\n\n/** The proxy for `baseUrl`, validated; `undefined` means direct. */\nfunction readProxy(baseUrl: string, env: NodeJS.ProcessEnv, logger: ILogger): string | undefined {\n const proxy = gatewayProxyUrl(baseUrl, env);\n if (proxy === undefined) return undefined;\n const reason = proxyRejection(proxy);\n if (reason === undefined) return proxy;\n const variable = baseUrl.startsWith('https:') ? 'HTTPS_PROXY' : 'HTTP_PROXY';\n logger.warn(`${variable} ignored for the gateway (${reason}); gateway calls go direct`, {\n env: variable,\n reason,\n });\n return undefined;\n}\n\n/**\n * Resolve the gateway's transport options from `env`. Every invalid input is\n * warned (variable + reason, never the value) and dropped, so the gateway\n * falls back to the default for that one option.\n */\nexport function readGatewayTransport(\n baseUrl: string,\n env: NodeJS.ProcessEnv,\n logger: ILogger\n): GatewayTransport {\n const authHeader = readAuthHeader(env, logger);\n const extraHeaders = readExtraHeaders(env, authHeader, logger);\n const proxyUrl = readProxy(baseUrl, env, logger);\n return {\n ...(authHeader !== undefined && { authHeader }),\n ...(extraHeaders !== undefined && { extraHeaders }),\n ...(proxyUrl !== undefined && { proxyUrl }),\n };\n}\n\n/** One agent per proxy URL: a gateway builds an adapter per model. */\nconst proxyAgents = new Map<string, ProxyAgent>();\n\n/**\n * The runtime's `RequestInit.dispatcher`, as `@types/node` declares it. The\n * agent comes from the `undici` package (major 6, the one Node 22 bundles),\n * whose types differ from the `undici-types` major that `@types/node` pins\n * only in optional-property spelling; the object is the dispatcher `fetch`\n * accepts at runtime, which the gateway proxy test exercises end to end.\n */\ntype FetchDispatcher = NonNullable<RequestInit['dispatcher']>;\n\nfunction proxyAgentFor(proxyUrl: string): FetchDispatcher {\n const existing = proxyAgents.get(proxyUrl);\n const agent = existing ?? new ProxyAgent(proxyUrl);\n if (existing === undefined) proxyAgents.set(proxyUrl, agent);\n return agent as unknown as FetchDispatcher;\n}\n\n/** The `openai` client options a gateway transport contributes. */\nexport type GatewayClientOptions = Pick<\n OpenAIAdapterConfig,\n 'defaultHeaders' | 'fetchOptions' | 'apiSurface'\n>;\n\n/**\n * Client options for one gateway call site (discovery or a model adapter).\n * With an auth header, the SDK's bearer is removed (`Authorization: null` is\n * the SDK's documented removal) and the key goes in that header instead.\n * Returns only the keys that apply, so a default transport adds nothing.\n */\nexport function gatewayClientOptions(\n transport: GatewayTransport & { readonly apiKey: string }\n): GatewayClientOptions {\n const headers = gatewayHeaders(transport);\n return {\n ...(transport.apiSurface !== undefined && { apiSurface: transport.apiSurface }),\n ...(Object.keys(headers).length > 0 && { defaultHeaders: headers }),\n ...(transport.proxyUrl !== undefined && {\n fetchOptions: { dispatcher: proxyAgentFor(transport.proxyUrl) },\n }),\n };\n}\n\n/**\n * The headers a transport adds: the extra headers, and with an auth header,\n * the key in that header and `Authorization: null` (both clients drop a\n * null-valued header, which removes their default bearer).\n */\nfunction gatewayHeaders(\n transport: GatewayTransport & { readonly apiKey: string }\n): Record<string, string | null> {\n const headers: Record<string, string | null> = { ...transport.extraHeaders };\n if (transport.authHeader !== undefined) {\n headers['Authorization'] = null;\n headers[transport.authHeader] = transport.apiKey;\n }\n return headers;\n}\n\n/** The AI-SDK `createOpenAI` settings a gateway transport contributes. */\ninterface GatewayAiSdkOptions {\n readonly headers?: Readonly<Record<string, string | undefined>>;\n readonly fetch?: typeof fetch;\n}\n\n/**\n * The same transport as {@link gatewayClientOptions}, shaped for consumers\n * of the AI-SDK `createOpenAI` factory (retained compatibility surface):\n * `headers` (a removed header is `undefined`, the AI SDK's spelling) and a\n * `fetch` that carries the proxy dispatcher. Only the keys that apply.\n */\nexport function gatewayAiSdkOptions(\n transport: GatewayTransport & { readonly apiKey: string }\n): GatewayAiSdkOptions {\n const headers = Object.fromEntries(\n Object.entries(gatewayHeaders(transport)).map(([name, value]) => [name, value ?? undefined])\n );\n const proxyUrl = transport.proxyUrl;\n return {\n ...(Object.keys(headers).length > 0 && { headers }),\n ...(proxyUrl !== undefined && {\n fetch: (input: string | URL | Request, init?: RequestInit) =>\n fetch(input, { ...init, dispatcher: proxyAgentFor(proxyUrl) }),\n }),\n };\n}\n"],"mappings":"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","names":["OpenAI","err","stream","logger","err","logger","logger","OpenAI"]}
@@ -5,14 +5,14 @@ import {
5
5
  getCurrentRequestContext,
6
6
  runWithRequestContext,
7
7
  serverCallerInfo
8
- } from "./chunk-AMK4BTAV.js";
8
+ } from "./chunk-WD4DENPC.js";
9
9
  import {
10
10
  DEFAULT_EXECUTION_MODE
11
11
  } from "./chunk-TYLE7Z2S.js";
12
12
  import {
13
13
  sanitizeErrorDetails,
14
14
  sanitizeStringLeaves
15
- } from "./chunk-IRFKJ2KR.js";
15
+ } from "./chunk-QM5W3T3O.js";
16
16
  import {
17
17
  SecurityError,
18
18
  TOOL_MANIFEST,
@@ -26,7 +26,7 @@ import {
26
26
  getTimeProvider,
27
27
  ok,
28
28
  resolveInsideRoot
29
- } from "./chunk-WI73OZAU.js";
29
+ } from "./chunk-WKFPKPEM.js";
30
30
  import {
31
31
  getNexusDataDir,
32
32
  parseBoolValue
@@ -2343,4 +2343,4 @@ export {
2343
2343
  DEFAULT_CONSENSUS_CONFIG,
2344
2344
  ConsensusMetricsSchema
2345
2345
  };
2346
- //# sourceMappingURL=chunk-HQWQ7MR5.js.map
2346
+ //# sourceMappingURL=chunk-LP5ISXKM.js.map
@@ -7,7 +7,7 @@ import {
7
7
  logGatewaySlotMapping,
8
8
  resolveOwnerCli,
9
9
  setGatewaySlotCatalog
10
- } from "./chunk-WI73OZAU.js";
10
+ } from "./chunk-WKFPKPEM.js";
11
11
 
12
12
  // src/config/model-availability.ts
13
13
  var DEFAULT_TTL_MS = 6e4;
@@ -139,7 +139,7 @@ function discoverGatewayOnce(logger = defaultLogger) {
139
139
  }
140
140
  async function runProbe(logger) {
141
141
  try {
142
- const { buildOpenAICompatAdapters: build } = await import("./openai-compat-adapter-GSDOJ7TQ.js");
142
+ const { buildOpenAICompatAdapters: build } = await import("./openai-compat-adapter-GPZDIR3D.js");
143
143
  return await build(logger);
144
144
  } catch (error) {
145
145
  return err(new ConfigError(`Gateway discovery threw: ${getErrorMessage(error)}`));
@@ -269,4 +269,4 @@ export {
269
269
  setGatewayRediscovery,
270
270
  ensureGatewayDiscovered
271
271
  };
272
- //# sourceMappingURL=chunk-QPU7QKPT.js.map
272
+ //# sourceMappingURL=chunk-LXYT2P2Y.js.map