nexus-agents 11.4.0 → 11.4.2

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 (133) hide show
  1. package/dist/{ast-rule-runner-725WWM62.js → ast-rule-runner-UZS3CBHO.js} +5 -5
  2. package/dist/{child-mcp-config-XILEOWB5.js → child-mcp-config-353PE3ID.js} +4 -4
  3. package/dist/{chunk-XXNSAOCH.js → chunk-2FY4QM42.js} +3 -3
  4. package/dist/{chunk-3JF47YAU.js → chunk-2PN4CAL2.js} +4 -4
  5. package/dist/{chunk-EL4XXJM6.js → chunk-54UNI6GV.js} +4 -4
  6. package/dist/{chunk-VIJSBKRY.js → chunk-5CSM473L.js} +3 -3
  7. package/dist/{chunk-PPH3CAMR.js → chunk-6RP53JXS.js} +4 -4
  8. package/dist/{chunk-I34P7L4Z.js → chunk-6U3GRS6B.js} +36 -27
  9. package/dist/chunk-6U3GRS6B.js.map +1 -0
  10. package/dist/{chunk-HHOSB6LL.js → chunk-7LW3PMQS.js} +37 -37
  11. package/dist/{chunk-R4ZN6AQO.js → chunk-BPO2LQ67.js} +4 -4
  12. package/dist/{chunk-M44B64SR.js → chunk-CVOE6Q56.js} +2 -2
  13. package/dist/{chunk-XAEGIDWX.js → chunk-CVT26QN5.js} +8 -8
  14. package/dist/{chunk-G6KGFOCE.js → chunk-DS6X6MFM.js} +2 -2
  15. package/dist/{chunk-RGTJML3H.js → chunk-EOIUMPFK.js} +2 -2
  16. package/dist/{chunk-WRNLFRB5.js → chunk-J7UDMLPP.js} +2 -2
  17. package/dist/{chunk-NUEO6DH6.js → chunk-JDL5WJDM.js} +2 -2
  18. package/dist/{chunk-SN5FNPUR.js → chunk-JQ4JJVH2.js} +2 -2
  19. package/dist/{chunk-QDCUEJQW.js → chunk-KCESFTXP.js} +2 -2
  20. package/dist/{chunk-T3SLFKSX.js → chunk-KSGJB4AF.js} +2 -2
  21. package/dist/{chunk-ORYATV3T.js → chunk-M7JXKUFB.js} +7 -7
  22. package/dist/{chunk-3WOPUDGR.js → chunk-ME7LKSBK.js} +4 -4
  23. package/dist/{chunk-HF36DB2G.js → chunk-MOILTUAB.js} +13 -13
  24. package/dist/{chunk-YGD52X37.js → chunk-MPYHD4EV.js} +2 -2
  25. package/dist/{chunk-24CFATEC.js → chunk-NSELDEAX.js} +2 -2
  26. package/dist/{chunk-3W65DEPM.js → chunk-P3ZQVHQA.js} +2 -2
  27. package/dist/{chunk-CVHLQFUX.js → chunk-PAYKBSXM.js} +13 -13
  28. package/dist/{chunk-QBZZGFWK.js → chunk-RGDZIWGS.js} +6 -6
  29. package/dist/{chunk-JYZLBQ7M.js → chunk-RYSLBVMQ.js} +3 -3
  30. package/dist/{chunk-YEWHPFMD.js → chunk-UMLKKXBD.js} +3 -3
  31. package/dist/{chunk-C4ZXUDDS.js → chunk-V552SY6A.js} +2 -2
  32. package/dist/{chunk-RWZIF3UK.js → chunk-VKK7ZGSY.js} +4 -4
  33. package/dist/{chunk-RDUMFICX.js → chunk-WTZULRPO.js} +2 -2
  34. package/dist/{chunk-JEESPQIQ.js → chunk-Y5YOOAXF.js} +2 -2
  35. package/dist/{chunk-5LBCX3I4.js → chunk-YZXCE5BB.js} +5 -5
  36. package/dist/{chunk-SRAMHULV.js → chunk-ZSPGTD4X.js} +7 -7
  37. package/dist/{cli-circuit-breaker-UO6DRFZD.js → cli-circuit-breaker-4SM3OLUD.js} +5 -5
  38. package/dist/{cli-readiness-XPZNJLCW.js → cli-readiness-JJVQULXD.js} +8 -8
  39. package/dist/{cli-server-gateway-AWEOQD4E.js → cli-server-gateway-TYVCEQBQ.js} +12 -12
  40. package/dist/cli.js +43 -43
  41. package/dist/{composite-router-S4ZOD4GS.js → composite-router-56G2NJCH.js} +4 -4
  42. package/dist/{consensus-vote-36TUM35R.js → consensus-vote-CE7X66SQ.js} +16 -16
  43. package/dist/{context-retriever-ZKIAEF43.js → context-retriever-AUOD3LIJ.js} +10 -10
  44. package/dist/{doctor-deep-FCSBGTAN.js → doctor-deep-KMMW2MTJ.js} +5 -5
  45. package/dist/{doctor-gateway-report-2QH7JMEO.js → doctor-gateway-report-AOH2I4UJ.js} +7 -7
  46. package/dist/{doctor-live-PMYIFAWV.js → doctor-live-2IVCCWSN.js} +12 -12
  47. package/dist/{expert-bridge-S6WYRFOU.js → expert-bridge-PREN4ZL3.js} +6 -6
  48. package/dist/{factory-55RVYW75.js → factory-3YILRPOA.js} +11 -11
  49. package/dist/{factory-CKEO6H4B.js → factory-KPCJR5RB.js} +7 -7
  50. package/dist/{improvement-review-NHXRFXMD.js → improvement-review-MZMOSJM2.js} +7 -7
  51. package/dist/index.d.ts +1 -1
  52. package/dist/index.js +29 -29
  53. package/dist/{init-opencode-IL32T2AA.js → init-opencode-V4G5WYRL.js} +6 -6
  54. package/dist/{issue-triage-6BEBWXMY.js → issue-triage-WZZTRX4K.js} +7 -7
  55. package/dist/{model-config-helpers-A32ALQ5R.js → model-config-helpers-BC4JYVUU.js} +3 -3
  56. package/dist/{openai-compat-adapter-WK3Q5GR7.js → openai-compat-adapter-7NPALXRG.js} +6 -6
  57. package/dist/{pr-reviewer-helpers-BB3QNAWD.js → pr-reviewer-helpers-O6URR7XX.js} +5 -5
  58. package/dist/{registry-command-JYPM6LXE.js → registry-command-T3NTED3I.js} +2 -2
  59. package/dist/{repo-security-plan-56ZPEFGG.js → repo-security-plan-BACXPNX3.js} +4 -4
  60. package/dist/{research-helpers-synthesize-B4KYVM4T.js → research-helpers-synthesize-IWS2XZQN.js} +6 -6
  61. package/dist/{routing-memory-KVLCI3TU.js → routing-memory-EO7VG7R3.js} +4 -4
  62. package/dist/{session-memory-SYCL2GCL.js → session-memory-4GX3WTEB.js} +5 -5
  63. package/dist/{setup-config-OWLLNO6I.js → setup-config-JYHG3SGD.js} +5 -5
  64. package/dist/{setup-custom-api-TI6REX7V.js → setup-custom-api-GF66FJBO.js} +5 -5
  65. package/dist/{setup-data-dir-UQOVBXCR.js → setup-data-dir-ZJMIJWQ2.js} +15 -15
  66. package/dist/{tool-memory-Z3M7LGS4.js → tool-memory-IS2S7SYW.js} +7 -7
  67. package/dist/{unified-registry-I54IDLWC.js → unified-registry-IZ46TOAY.js} +11 -11
  68. package/dist/{weather-report-3MRZJISW.js → weather-report-MLERG4SM.js} +4 -4
  69. package/package.json +4 -4
  70. package/dist/chunk-I34P7L4Z.js.map +0 -1
  71. /package/dist/{ast-rule-runner-725WWM62.js.map → ast-rule-runner-UZS3CBHO.js.map} +0 -0
  72. /package/dist/{child-mcp-config-XILEOWB5.js.map → child-mcp-config-353PE3ID.js.map} +0 -0
  73. /package/dist/{chunk-XXNSAOCH.js.map → chunk-2FY4QM42.js.map} +0 -0
  74. /package/dist/{chunk-3JF47YAU.js.map → chunk-2PN4CAL2.js.map} +0 -0
  75. /package/dist/{chunk-EL4XXJM6.js.map → chunk-54UNI6GV.js.map} +0 -0
  76. /package/dist/{chunk-VIJSBKRY.js.map → chunk-5CSM473L.js.map} +0 -0
  77. /package/dist/{chunk-PPH3CAMR.js.map → chunk-6RP53JXS.js.map} +0 -0
  78. /package/dist/{chunk-HHOSB6LL.js.map → chunk-7LW3PMQS.js.map} +0 -0
  79. /package/dist/{chunk-R4ZN6AQO.js.map → chunk-BPO2LQ67.js.map} +0 -0
  80. /package/dist/{chunk-M44B64SR.js.map → chunk-CVOE6Q56.js.map} +0 -0
  81. /package/dist/{chunk-XAEGIDWX.js.map → chunk-CVT26QN5.js.map} +0 -0
  82. /package/dist/{chunk-G6KGFOCE.js.map → chunk-DS6X6MFM.js.map} +0 -0
  83. /package/dist/{chunk-RGTJML3H.js.map → chunk-EOIUMPFK.js.map} +0 -0
  84. /package/dist/{chunk-WRNLFRB5.js.map → chunk-J7UDMLPP.js.map} +0 -0
  85. /package/dist/{chunk-NUEO6DH6.js.map → chunk-JDL5WJDM.js.map} +0 -0
  86. /package/dist/{chunk-SN5FNPUR.js.map → chunk-JQ4JJVH2.js.map} +0 -0
  87. /package/dist/{chunk-QDCUEJQW.js.map → chunk-KCESFTXP.js.map} +0 -0
  88. /package/dist/{chunk-T3SLFKSX.js.map → chunk-KSGJB4AF.js.map} +0 -0
  89. /package/dist/{chunk-ORYATV3T.js.map → chunk-M7JXKUFB.js.map} +0 -0
  90. /package/dist/{chunk-3WOPUDGR.js.map → chunk-ME7LKSBK.js.map} +0 -0
  91. /package/dist/{chunk-HF36DB2G.js.map → chunk-MOILTUAB.js.map} +0 -0
  92. /package/dist/{chunk-YGD52X37.js.map → chunk-MPYHD4EV.js.map} +0 -0
  93. /package/dist/{chunk-24CFATEC.js.map → chunk-NSELDEAX.js.map} +0 -0
  94. /package/dist/{chunk-3W65DEPM.js.map → chunk-P3ZQVHQA.js.map} +0 -0
  95. /package/dist/{chunk-CVHLQFUX.js.map → chunk-PAYKBSXM.js.map} +0 -0
  96. /package/dist/{chunk-QBZZGFWK.js.map → chunk-RGDZIWGS.js.map} +0 -0
  97. /package/dist/{chunk-JYZLBQ7M.js.map → chunk-RYSLBVMQ.js.map} +0 -0
  98. /package/dist/{chunk-YEWHPFMD.js.map → chunk-UMLKKXBD.js.map} +0 -0
  99. /package/dist/{chunk-C4ZXUDDS.js.map → chunk-V552SY6A.js.map} +0 -0
  100. /package/dist/{chunk-RWZIF3UK.js.map → chunk-VKK7ZGSY.js.map} +0 -0
  101. /package/dist/{chunk-RDUMFICX.js.map → chunk-WTZULRPO.js.map} +0 -0
  102. /package/dist/{chunk-JEESPQIQ.js.map → chunk-Y5YOOAXF.js.map} +0 -0
  103. /package/dist/{chunk-5LBCX3I4.js.map → chunk-YZXCE5BB.js.map} +0 -0
  104. /package/dist/{chunk-SRAMHULV.js.map → chunk-ZSPGTD4X.js.map} +0 -0
  105. /package/dist/{cli-circuit-breaker-UO6DRFZD.js.map → cli-circuit-breaker-4SM3OLUD.js.map} +0 -0
  106. /package/dist/{cli-readiness-XPZNJLCW.js.map → cli-readiness-JJVQULXD.js.map} +0 -0
  107. /package/dist/{cli-server-gateway-AWEOQD4E.js.map → cli-server-gateway-TYVCEQBQ.js.map} +0 -0
  108. /package/dist/{composite-router-S4ZOD4GS.js.map → composite-router-56G2NJCH.js.map} +0 -0
  109. /package/dist/{consensus-vote-36TUM35R.js.map → consensus-vote-CE7X66SQ.js.map} +0 -0
  110. /package/dist/{context-retriever-ZKIAEF43.js.map → context-retriever-AUOD3LIJ.js.map} +0 -0
  111. /package/dist/{doctor-deep-FCSBGTAN.js.map → doctor-deep-KMMW2MTJ.js.map} +0 -0
  112. /package/dist/{doctor-gateway-report-2QH7JMEO.js.map → doctor-gateway-report-AOH2I4UJ.js.map} +0 -0
  113. /package/dist/{doctor-live-PMYIFAWV.js.map → doctor-live-2IVCCWSN.js.map} +0 -0
  114. /package/dist/{expert-bridge-S6WYRFOU.js.map → expert-bridge-PREN4ZL3.js.map} +0 -0
  115. /package/dist/{factory-55RVYW75.js.map → factory-3YILRPOA.js.map} +0 -0
  116. /package/dist/{factory-CKEO6H4B.js.map → factory-KPCJR5RB.js.map} +0 -0
  117. /package/dist/{improvement-review-NHXRFXMD.js.map → improvement-review-MZMOSJM2.js.map} +0 -0
  118. /package/dist/{init-opencode-IL32T2AA.js.map → init-opencode-V4G5WYRL.js.map} +0 -0
  119. /package/dist/{issue-triage-6BEBWXMY.js.map → issue-triage-WZZTRX4K.js.map} +0 -0
  120. /package/dist/{model-config-helpers-A32ALQ5R.js.map → model-config-helpers-BC4JYVUU.js.map} +0 -0
  121. /package/dist/{openai-compat-adapter-WK3Q5GR7.js.map → openai-compat-adapter-7NPALXRG.js.map} +0 -0
  122. /package/dist/{pr-reviewer-helpers-BB3QNAWD.js.map → pr-reviewer-helpers-O6URR7XX.js.map} +0 -0
  123. /package/dist/{registry-command-JYPM6LXE.js.map → registry-command-T3NTED3I.js.map} +0 -0
  124. /package/dist/{repo-security-plan-56ZPEFGG.js.map → repo-security-plan-BACXPNX3.js.map} +0 -0
  125. /package/dist/{research-helpers-synthesize-B4KYVM4T.js.map → research-helpers-synthesize-IWS2XZQN.js.map} +0 -0
  126. /package/dist/{routing-memory-KVLCI3TU.js.map → routing-memory-EO7VG7R3.js.map} +0 -0
  127. /package/dist/{session-memory-SYCL2GCL.js.map → session-memory-4GX3WTEB.js.map} +0 -0
  128. /package/dist/{setup-config-OWLLNO6I.js.map → setup-config-JYHG3SGD.js.map} +0 -0
  129. /package/dist/{setup-custom-api-TI6REX7V.js.map → setup-custom-api-GF66FJBO.js.map} +0 -0
  130. /package/dist/{setup-data-dir-UQOVBXCR.js.map → setup-data-dir-ZJMIJWQ2.js.map} +0 -0
  131. /package/dist/{tool-memory-Z3M7LGS4.js.map → tool-memory-IS2S7SYW.js.map} +0 -0
  132. /package/dist/{unified-registry-I54IDLWC.js.map → unified-registry-IZ46TOAY.js.map} +0 -0
  133. /package/dist/{weather-report-3MRZJISW.js.map → weather-report-MLERG4SM.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli-adapters/cli-to-model-adapter.ts","../src/adapters/claude-adapter.ts","../src/adapters/claude-adapter-types.ts","../src/adapters/claude-adapter-helpers.ts","../src/adapters/prompt-utils.ts","../src/adapters/sdk/sdk-adapter.ts","../src/cli-adapters/cli-detection-cache.ts","../src/adapters/auto-adapter-gateway.ts","../src/adapters/auto-adapter.ts","../src/agents/collaboration/event-bus-helpers.ts","../src/agents/collaboration/event-bus.ts","../src/agents/collaboration/event-bus-topics.ts","../src/adapters/resilient-adapter.ts","../src/adapters/model-bound-adapter.ts","../src/adapters/unified-registry.ts","../src/cli-adapters/parsers/agy-parser.ts","../src/config/agy-model-map.ts","../src/cli-adapters/adapters/gemini-adapter-helpers.ts","../src/cli-adapters/adapters/agy-invocation.ts","../src/cli-adapters/adapters/gemini-adapter.ts","../src/cli-adapters/adapters/codex-adapter.ts","../src/cli-adapters/codex-sandbox-preflight.ts","../src/cli/voter-unverifiable.ts","../src/cli-adapters/adapters/codex-adapter-helpers.ts","../src/cli-adapters/parsers/codex-parser.ts","../src/cli-adapters/codex-mcp-isolation.ts","../src/cli-adapters/codex-cloud-config-auth.ts","../src/cli-adapters/mcp-config-scan.ts","../src/cli-adapters/adapters/codex-mcp-adapter.ts","../src/cli-adapters/adapters/codex-mcp-adapter-helpers.ts","../src/cli-adapters/adapters/opencode-adapter.ts","../src/cli-adapters/parsers/opencode-parser.ts","../src/cli-adapters/codex-mcp-server-probe.ts","../src/cli-adapters/factory.ts"],"sourcesContent":["import { isCliName } from './types.js';\n/**\n * CLI-to-Model Adapter Bridge\n *\n * Wraps an ICliAdapter to implement IModelAdapter, enabling CLI tools\n * (claude, gemini, codex) to be used where model adapters are expected.\n *\n * @module cli-adapters/cli-to-model-adapter\n */\n\nimport type {\n Result,\n IModelAdapter,\n CompletionRequest,\n CompletionResponse,\n ModelCapability,\n} from '../core/index.js';\nimport {\n ModelCapability as MC,\n ok,\n err,\n ModelError,\n ConfigError,\n ErrorCode,\n createLogger,\n} from '../core/index.js';\nimport { estimateTokens } from '../core/token-estimator.js';\nimport type { ICliAdapter, CliTask, CliResponse, CliError, ExecutionOptions } from './types.js';\nimport { unenforcedAccessModeRefusal } from './access-mode.js';\nimport type { StreamChunk } from '../core/types/model.js';\nimport { toModelTokenUsage } from './token-usage-bridge.js';\nimport { isCallerInputCliError, isHostUnavailableCliError } from './cli-error-helpers.js';\nimport { findCanonicalModel } from '../config/model-config-helpers.js';\nimport { CLI_NAMES } from '../config/model-capabilities-types.js';\n\nconst logger = createLogger({ component: 'cli-to-model-adapter' });\n\n/** Configuration for CliToModelAdapter. */\nexport interface CliToModelAdapterConfig {\n /** Default timeout for CLI calls (ms). Overrides auto-detection. */\n readonly defaultTimeoutMs?: number;\n}\n\n/**\n * Bridge adapter that wraps ICliAdapter to implement IModelAdapter.\n *\n * This enables using CLI tools (claude, gemini, codex) in contexts\n * that expect IModelAdapter.\n *\n * @example\n * ```typescript\n * const cliAdapter = createCliAdapter({ cli: 'claude' });\n * const modelAdapter = new CliToModelAdapter(cliAdapter);\n *\n * // Now use modelAdapter where IModelAdapter is expected\n * const result = await modelAdapter.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * });\n * ```\n */\nexport class CliToModelAdapter implements IModelAdapter {\n readonly providerId: string;\n readonly modelId: string;\n readonly capabilities: readonly ModelCapability[];\n\n private readonly cliAdapter: ICliAdapter;\n private readonly defaultTimeoutMs: number | undefined;\n\n /**\n * Creates a bridge from CLI adapter to model adapter.\n *\n * @param cliAdapter - The CLI adapter to wrap\n * @param config - Optional configuration (e.g. timeout override)\n */\n constructor(cliAdapter: ICliAdapter, config?: CliToModelAdapterConfig) {\n this.cliAdapter = cliAdapter;\n this.defaultTimeoutMs = config?.defaultTimeoutMs;\n this.providerId = `cli-${cliAdapter.name}`;\n this.modelId = cliAdapter.getModelInfo().id;\n this.capabilities = this.deriveCapabilities();\n }\n\n /**\n * Derives ModelCapability from CLI capabilities.\n */\n private deriveCapabilities(): readonly ModelCapability[] {\n const caps: ModelCapability[] = [MC.COMPLETION, MC.TOOL_USE];\n\n // Claude CLI has extended thinking capability\n if (this.cliAdapter.name === 'claude') {\n caps.push(MC.EXTENDED_THINKING);\n }\n\n return caps;\n }\n\n /**\n * Converts CompletionRequest to CliTask.\n */\n private toCliTask(request: CompletionRequest): CliTask {\n // Build content from messages\n const content = request.messages\n .map((msg) => {\n const text =\n typeof msg.content === 'string'\n ? msg.content\n : msg.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n return `[${msg.role}]: ${text}`;\n })\n .join('\\n\\n');\n\n // Build task with conditional optional properties\n const task: CliTask = {\n content,\n ...(request.workDir !== undefined ? { options: { workDir: request.workDir } } : {}),\n ...(request.accessMode !== undefined ? { accessMode: request.accessMode } : {}),\n };\n\n if (request.systemPrompt !== undefined) {\n (task as { systemPrompt: string }).systemPrompt = request.systemPrompt;\n }\n if (request.maxTokens !== undefined) {\n (task as { maxTokens: number }).maxTokens = request.maxTokens;\n }\n const model = this.forwardableModel(request.model);\n if (model !== undefined) {\n (task as { model: string }).model = model;\n }\n\n return task;\n }\n\n /**\n * The requested model, when this CLI may be handed it (#6599). A registry\n * model that belongs ONLY to other CLIs is withheld: a failover can land a\n * model-bound request on a different CLI, which cannot run it and then runs\n * its own default — logged, and the response reports the model that ran.\n * A name the registry does not know is forwarded; the CLI adapter resolves\n * it or returns an error.\n */\n private forwardableModel(model: string | undefined): string | undefined {\n if (model === undefined) return undefined;\n const owners = CLI_NAMES.filter((cli) => findCanonicalModel(cli, model) !== undefined);\n if (owners.length === 0 || (owners as readonly string[]).includes(this.cliAdapter.name)) {\n return model;\n }\n logger.warn('Requested model belongs to another CLI; this CLI runs its default', {\n model,\n cli: this.cliAdapter.name,\n owners,\n });\n return undefined;\n }\n\n /**\n * Converts CliResponse to CompletionResponse.\n */\n private toCompletionResponse(response: CliResponse, forwarded?: string): CompletionResponse {\n const u = response.usage;\n return {\n content: [{ type: 'text', text: response.text }],\n // #4439: this used to be `response.usage?.x ?? 0`, which turned \"the CLI\n // reported nothing\" into a present 0/0/0 — indistinguishable downstream\n // from a real zero-token call. That single coercion defeated the\n // measured-voter gate (#4436) on every live vote and dropped the cache\n // fields (#4438) that #4435 needs. Absence stays absent; a present\n // usage crosses the type boundary through the one conversion (#4440).\n ...(u !== undefined ? { usage: toModelTokenUsage(u) } : {}),\n stopReason: 'end_turn',\n // #6599: no CLI parser reports the model, so a forwarded model is the\n // one that ran — report its canonical id, or cost and outcomes are\n // attributed to the CLI default.\n model: response.model ?? this.reportedForwardedModel(forwarded) ?? this.modelId,\n // #6094: carry the transport's captured stderr up to the model boundary\n // so the voter path can read the structured \"could not read\" signal.\n // Absent stays absent; an empty string is not a signal.\n ...(response.stderr !== undefined && response.stderr !== ''\n ? { cliStderr: response.stderr }\n : {}),\n // #6120/#6115: an in-family model substitution rides up the same way, so\n // the seat can say which alias it asked for and which one answered.\n ...(response.fallbackFrom !== undefined ? { fallbackFrom: response.fallbackFrom } : {}),\n };\n }\n\n /**\n * Converts CliError to ModelError.\n */\n private toModelError(cliError: CliError): ModelError {\n const options = cliError.cause !== undefined ? { cause: cliError.cause } : {};\n // #6599: caller input (e.g. an unresolvable requested model) keeps its\n // identity across the bridge, so the breaker can decline to count it.\n const code = isCallerInputCliError(cliError) ? { code: ErrorCode.INVALID_INPUT } : {};\n // #6846: only a host refusal overrides the caller's retry policy. The\n // code-derived CLI boolean also marks ordinary execution failures false.\n const retryability = isHostUnavailableCliError(cliError) ? { retryable: false } : {};\n return new ModelError(cliError.message, { ...options, ...code, ...retryability });\n }\n\n /**\n * The canonical registry id of a model forwarded to this CLI, when the\n * registry lists it under this CLI. A name the registry does not know is not\n * claimed: the CLI may have substituted its default (agy does), so the\n * adapter default stays the honest report.\n */\n private reportedForwardedModel(forwarded: string | undefined): string | undefined {\n // Endpoint model IDs are discovered, never looked up as CLI models.\n if (forwarded === undefined || !isCliName(this.cliAdapter.name)) return undefined;\n return findCanonicalModel(this.cliAdapter.name, forwarded)?.id;\n }\n\n /**\n * Send a completion request via CLI.\n */\n async complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>> {\n const task = this.toCliTask(request);\n // #6754/#6792: fail closed for an adapter that does not declare the task's\n // access mode, whatever its own execute would have done with the field.\n const refusal = unenforcedAccessModeRefusal(this.cliAdapter, task);\n if (refusal !== undefined) return err(this.toModelError(refusal));\n // Per-request timeout (#3304) takes precedence over the construction-time\n // default, so a long-budget caller (e.g. a consensus vote) isn't cut off by\n // the adapter's shorter standard CLI timeout.\n const effectiveTimeoutMs = request.timeoutMs ?? this.defaultTimeoutMs;\n // #6680: the caller's signal reaches the CLI adapter, which kills its\n // subprocess on abort. It used to stop here, so neither a watchdog timeout\n // nor `cancel_job` could end a running CLI call.\n const opts: ExecutionOptions | undefined =\n effectiveTimeoutMs !== undefined || request.signal !== undefined\n ? {\n ...(effectiveTimeoutMs !== undefined ? { timeoutMs: effectiveTimeoutMs } : {}),\n ...(request.signal !== undefined ? { signal: request.signal } : {}),\n }\n : undefined;\n const result = await this.cliAdapter.execute(task, opts);\n\n if (!result.ok) {\n return err(this.toModelError(result.error));\n }\n\n return ok(this.toCompletionResponse(result.value, task.model));\n }\n\n /**\n * Streaming is not supported via CLI adapters.\n * Falls back to non-streaming and yields single chunk.\n */\n async *stream(request: CompletionRequest): AsyncIterable<StreamChunk> {\n const result = await this.complete(request);\n\n if (!result.ok) {\n throw result.error;\n }\n\n const response = result.value;\n\n yield { type: 'message_start', message: { model: response.model } };\n\n yield {\n type: 'content_block_start',\n index: 0,\n contentBlock: response.content[0] ?? { type: 'text', text: '' },\n };\n\n const firstBlock = response.content[0];\n const text = firstBlock?.type === 'text' ? firstBlock.text : '';\n yield { type: 'content_block_delta', index: 0, delta: { type: 'text_delta', text } };\n\n yield { type: 'content_block_stop', index: 0 };\n\n yield {\n type: 'message_delta',\n delta: { stop_reason: response.stopReason },\n // exactOptionalPropertyTypes: omit the key entirely when unknown rather\n // than passing an explicit undefined (#4439).\n ...(response.usage !== undefined ? { usage: response.usage } : {}),\n };\n\n yield { type: 'message_stop' };\n }\n\n /**\n * Token count via canonical estimator (DRY consolidation Issue #1596).\n */\n countTokens(text: string): Promise<number> {\n return Promise.resolve(estimateTokens(text));\n }\n\n /**\n * Validate configuration by running health check.\n */\n validateConfig(): Result<void, ConfigError> {\n // CLI adapters validate via health check\n return ok(undefined);\n }\n\n /**\n * Initialize the underlying CLI adapter.\n */\n async initialize(): Promise<void> {\n await this.cliAdapter.initialize();\n }\n\n /**\n * Dispose the underlying CLI adapter.\n */\n async dispose(): Promise<void> {\n await this.cliAdapter.dispose();\n }\n}\n\n/**\n * Creates a model adapter from a CLI adapter.\n *\n * @param cliAdapter - The CLI adapter to wrap\n * @returns IModelAdapter implementation\n */\nexport function createCliToModelAdapter(\n cliAdapter: ICliAdapter,\n config?: CliToModelAdapterConfig\n): CliToModelAdapter {\n return new CliToModelAdapter(cliAdapter, config);\n}\n","/**\n * nexus-agents/adapters - Claude/Anthropic Model Adapter\n *\n * Adapter for Anthropic's Claude models (claude-opus-4, claude-sonnet-4, claude-haiku-3).\n * Implements the IModelAdapter interface with streaming support, rate limiting,\n * and proper error handling.\n *\n * Verified 2026-01-03: @anthropic-ai/sdk@0.71.2 is current stable\n * (Source: npm registry)\n */\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type { MessageStreamEvent } from '@anthropic-ai/sdk/resources/messages';\nimport type {\n Result,\n CompletionRequest,\n CompletionResponse,\n ModelMetadata,\n StreamChunk,\n ContentBlock,\n TokenUsage,\n} from '../core/index.js';\nimport { ok, err, ModelError, ConfigError, getTokenEstimator } from '../core/index.js';\nimport {\n BaseAdapter,\n type BaseAdapterConfig,\n requireApiKey,\n validateApiKeyPresence,\n} from './base-adapter.js';\nimport { createStream } from './streaming.js';\nimport type { ClaudeAdapterConfig } from './claude-adapter-types.js';\nimport { DEFAULT_MAX_TOKENS } from './claude-adapter-types.js';\nimport {\n mapStopReason,\n mapContentBlock,\n mapMessage,\n mapTool,\n resolveModelId,\n getModelCapabilities,\n forcesResponseTool,\n buildRespondTool,\n mapResponseWithRespondTool,\n RESPOND_TOOL_NAME,\n} from './claude-adapter-helpers.js';\nimport { extractRequestSystemPrompt } from './prompt-utils.js';\nimport { planOptionalParams, type DroppedParam } from './optional-params.js';\n\n// Re-export types and constants for backward compatibility\nexport type { ClaudeAdapterConfig } from './claude-adapter-types.js';\nexport { CLAUDE_MODELS, CLAUDE_MODEL_ALIASES } from './claude-adapter-types.js';\n\n/**\n * Claude/Anthropic model adapter.\n *\n * Provides a unified interface for interacting with Anthropic's Claude models.\n * Supports completion, streaming, tool use, and vision capabilities.\n *\n * @example\n * ```typescript\n * const adapter = new ClaudeAdapter({\n * modelId: 'claude-sonnet-4',\n * apiKey: process.env.ANTHROPIC_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 */\nexport class ClaudeAdapter extends BaseAdapter {\n private readonly client: Anthropic;\n private readonly resolvedModelId: string;\n\n /**\n * Creates a new ClaudeAdapter instance.\n *\n * @param config - Claude adapter configuration\n * @throws {ConfigError} If API key is missing\n */\n constructor(config: ClaudeAdapterConfig) {\n const resolvedModelId = resolveModelId(config.modelId);\n\n // Build baseConfig conditionally to satisfy exactOptionalPropertyTypes\n const baseConfig: BaseAdapterConfig = {\n providerId: 'anthropic',\n modelId: resolvedModelId,\n capabilities: getModelCapabilities(config.modelId),\n apiKey: config.apiKey,\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.resolvedModelId = resolvedModelId;\n\n // Validate API key presence\n requireApiKey(config.apiKey, 'Anthropic', config.modelId);\n\n // Create Anthropic client\n this.client = new Anthropic({\n apiKey: config.apiKey,\n baseURL: config.baseUrl,\n timeout: config.timeout,\n maxRetries: config.maxRetries ?? 2,\n });\n }\n\n /**\n * Validates adapter configuration.\n * Extends base validation with Claude-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 Claude.\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 * Stream a completion request from Claude.\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 Claude-specific estimation.\n *\n * Claude uses a custom tokenizer. This provides a more accurate estimate\n * than the base adapter's generic calculation.\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 Claude-specific ratio (~3.5 chars/token)\n return Promise.resolve(getTokenEstimator().estimateText(text, 'claude'));\n }\n\n /**\n * Executes the completion request against the Anthropic API.\n */\n private async executeCompletion(request: CompletionRequest): Promise<CompletionResponse> {\n const { params, dropped } = this.buildRequestParams(request);\n // #3036: forward AbortSignal into the SDK so withWatchdog timeouts\n // actually cancel the in-flight HTTP request instead of leaking it\n // past the Promise.race boundary. Branch on signal presence — vitest\n // 4 `toHaveBeenCalledWith(params)` treats `(params, undefined)` as\n // a distinct call shape from `(params)`, so passing the second arg\n // unconditionally would break every callsite-shape assertion.\n const response =\n request.signal !== undefined\n ? await this.client.messages.create(params, { signal: request.signal })\n : await this.client.messages.create(params);\n\n // #3433: when we forced a `respond` tool to satisfy a non-text\n // responseFormat, surface its structured input as a text block so the\n // caller's JSON parser keeps working unchanged.\n // #4069: surface params dropped by the seam (e.g. temperature) as warnings.\n return this.mapResponse(response, forcesResponseTool(request), 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 const stream = this.client.messages.stream(params);\n\n for await (const event of stream) {\n const chunk = this.mapStreamEvent(event);\n if (chunk) {\n controller.push(chunk);\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 Anthropic API request parameters from our CompletionRequest.\n */\n private buildRequestParams(request: CompletionRequest): {\n params: Anthropic.MessageCreateParamsNonStreaming;\n dropped: readonly DroppedParam[];\n } {\n // Filter out system messages and map the rest\n const messages = request.messages.filter((m) => m.role !== 'system').map(mapMessage);\n\n const params: Anthropic.MessageCreateParamsNonStreaming = {\n model: this.resolvedModelId,\n messages,\n max_tokens: request.maxTokens ?? DEFAULT_MAX_TOKENS,\n };\n\n // Add system prompt if provided\n const systemPrompt = extractRequestSystemPrompt(request);\n if (systemPrompt !== undefined) {\n params.system = systemPrompt;\n }\n\n // Apply optional parameters; the seam reports any params it dropped (#4069).\n const dropped = this.applyOptionalParams(params, request);\n\n return { params, dropped };\n }\n\n /**\n * Applies optional parameters to the request params.\n *\n * @returns the params the seam dropped (#4069) — surfaced as response warnings.\n */\n private applyOptionalParams(\n params: Anthropic.MessageCreateParamsNonStreaming,\n request: CompletionRequest\n ): readonly DroppedParam[] {\n // #4068: the temperature drop-decision (#4061: Claude after Opus 4.6 rejects\n // any non-1.0 temperature with a 400; omit it — 1.0 is the API default, so\n // omitting is equivalent) is centralized in the shared planOptionalParams seam.\n const plan = planOptionalParams(request, this.resolvedModelId);\n if (plan.temperature !== undefined) {\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- still valid for older Anthropic models (≤ Opus 4.6) and value 1.0; the seam gates on temperatureUnsupportedForModel\n params.temperature = plan.temperature;\n }\n\n if (request.stop !== undefined && request.stop.length > 0) {\n params.stop_sequences = request.stop;\n }\n\n if (request.tools !== undefined && request.tools.length > 0) {\n params.tools = request.tools.map(mapTool);\n }\n\n // #3433: honor responseFormat via a forced `respond` tool_use. Anthropic\n // has no native JSON mode, so we register a synthetic tool whose\n // input_schema is the requested schema and force the model to call it.\n // The caller-supplied tools (above) are preserved — `respond` is merged\n // in, never clobbered. We only set tool_choice when the caller didn't\n // already specify their own tool usage intent.\n if (forcesResponseTool(request)) {\n const respondTool = buildRespondTool(request.responseFormat);\n params.tools = [...(params.tools ?? []), respondTool];\n params.tool_choice = { type: 'tool', name: RESPOND_TOOL_NAME };\n }\n\n return plan.dropped;\n }\n\n /**\n * Maps Anthropic API response to our CompletionResponse format.\n */\n private mapResponse(\n response: Anthropic.Message,\n surfaceRespondTool = false,\n dropped: readonly DroppedParam[] = []\n ): CompletionResponse {\n const content: ContentBlock[] = surfaceRespondTool\n ? mapResponseWithRespondTool(response.content)\n : response.content.map(mapContentBlock);\n\n // Cache figures come through in full (#4440). The CLI-side\n // `parsers/claude-parser.ts` has extracted these since #4435 — a panel's\n // FIRST call is the one that writes the cache, so dropping them loses its\n // largest input measurement — but this direct-API path was never updated,\n // the same one-arm-fixed shape as #4602.\n //\n // The SDK types both as `number | null` — never undefined, which is why a\n // null check alone suffices here. Null stays absent rather than\n // becoming 0: a fabricated 0 reads as \"no cache write happened\", which is\n // a claim the API did not make. `totalTokens` deliberately remains\n // uncached input + output, matching the CLI parser — folding the cache\n // figures in would change semantics for every existing consumer.\n const cachedInputTokens = response.usage.cache_read_input_tokens;\n const cacheCreationInputTokens = response.usage.cache_creation_input_tokens;\n const usage: TokenUsage = {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n ...(cachedInputTokens !== null && { cachedInputTokens }),\n ...(cacheCreationInputTokens !== null && { cacheCreationInputTokens }),\n };\n\n return {\n content,\n usage,\n stopReason: mapStopReason(response.stop_reason),\n model: response.model,\n // #4069: surface dropped params (e.g. an omitted temperature) so the caller\n // can see a behavioral param had no effect. Omitted entirely when nothing\n // was dropped (exactOptionalPropertyTypes).\n ...(dropped.length > 0 ? { warnings: dropped } : {}),\n };\n }\n\n /** Usage for a `message_start` chunk, omitted when the vendor sent none (#4835). */\n private static usageFrom(raw: { input_tokens?: number; output_tokens?: number } | undefined): {\n usage?: TokenUsage;\n } {\n const inputTokens = raw?.input_tokens;\n if (typeof inputTokens !== 'number') return {};\n const outputTokens = typeof raw?.output_tokens === 'number' ? raw.output_tokens : 0;\n return {\n usage: { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens },\n };\n }\n\n /**\n * Maps Anthropic stream events to our StreamChunk format.\n */\n private mapStreamEvent(event: MessageStreamEvent): StreamChunk | null {\n switch (event.type) {\n case 'message_start':\n // #4835: the prompt count arrives HERE, not on message_delta — the\n // Anthropic protocol puts it on `message.usage`. The delta comment\n // (\"Not available in delta\") was correct about the wrong event, and\n // the value was being dropped rather than being unavailable.\n //\n // Read defensively and OMIT when absent rather than zero-fill: the\n // SDK types it as required, but an Anthropic-compatible proxy may not\n // send it, and crashing a stream over a telemetry field would be a\n // worse failure than the one being fixed.\n return {\n type: 'message_start',\n message: { model: event.message.model },\n ...ClaudeAdapter.usageFrom(event.message.usage),\n };\n\n case 'content_block_start':\n return {\n type: 'content_block_start',\n index: event.index,\n contentBlock: mapContentBlock(event.content_block),\n };\n\n case 'content_block_delta':\n if (event.delta.type === 'text_delta') {\n return {\n type: 'content_block_delta',\n index: event.index,\n delta: { type: 'text_delta', text: event.delta.text },\n };\n }\n return null;\n\n case 'content_block_stop':\n return {\n type: 'content_block_stop',\n index: event.index,\n };\n\n case 'message_delta':\n return {\n type: 'message_delta',\n delta: { stop_reason: mapStopReason(event.delta.stop_reason ?? null) },\n usage: {\n // Genuinely absent on this event; the real count was emitted on\n // message_start above. Flagged so `totalTokens` reads as the\n // lower bound it is rather than as a total (#4835).\n inputTokens: 0,\n inputTokensMeasured: false,\n outputTokens: event.usage.output_tokens,\n totalTokens: event.usage.output_tokens,\n },\n };\n\n case 'message_stop':\n return { type: 'message_stop' };\n\n default:\n return null;\n }\n }\n\n /**\n * (#2540) List models the Anthropic API currently exposes.\n * Wraps `client.models.list()`. Cached for 5 min, in-flight promise\n * shared across concurrent callers, throws on non-2xx so the\n * harness-side identity resolver knows to fall back.\n */\n async listModels(): Promise<readonly ModelMetadata[]> {\n const now = Date.now();\n if (this.modelsCache !== null && now - this.modelsCache.fetchedAt < CLAUDE_LIST_MODELS_TTL_MS) {\n return this.modelsCache.value;\n }\n if (this.modelsInFlight !== null) return this.modelsInFlight;\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 const out: ModelMetadata[] = [];\n for (const m of list.data) {\n const entry: ModelMetadata = { id: m.id };\n if (typeof m.created_at === 'string') {\n const ts = Date.parse(m.created_at);\n if (!Number.isNaN(ts)) {\n out.push({ ...entry, ownedBy: 'anthropic', createdAt: Math.floor(ts / 1000) });\n continue;\n }\n }\n out.push({ ...entry, ownedBy: 'anthropic' });\n }\n return out;\n }\n}\n\nconst CLAUDE_LIST_MODELS_TTL_MS = 5 * 60 * 1000;\n\n/**\n * Creates a ClaudeAdapter with the specified configuration.\n * Factory function for cleaner API.\n *\n * @param config - Claude adapter configuration\n * @returns A configured ClaudeAdapter instance\n *\n * @example\n * ```typescript\n * const adapter = createClaudeAdapter({\n * modelId: 'claude-sonnet-4',\n * apiKey: process.env.ANTHROPIC_API_KEY!,\n * });\n * ```\n */\nexport function createClaudeAdapter(config: ClaudeAdapterConfig): ClaudeAdapter {\n return new ClaudeAdapter(config);\n}\n","/**\n * nexus-agents/adapters - Claude Adapter Types\n *\n * Type definitions and constants for the Claude/Anthropic adapter.\n *\n * @module adapters/claude-adapter-types\n */\n\nimport { getCliModelName } from '../config/model-config-helpers.js';\n\n/**\n * Supported Claude model identifiers.\n *\n * Derived from `config/in-tree-data.ts` via `getCliModelName()` (which reads\n * the ModelRegistry — see `config/model-registry.ts`). Do not hardcode\n * model-version strings here; update the registry.\n */\nexport const CLAUDE_MODELS = {\n OPUS_4: getCliModelName('claude-opus'),\n SONNET_4: getCliModelName('claude-sonnet'),\n HAIKU_4: getCliModelName('claude-haiku'),\n} as const;\n\n/**\n * Legacy version-suffix aliases mapped to the current registry cliModelName.\n *\n * Values come from `CLAUDE_MODELS` so they stay in sync with the canonical\n * registry. Add legacy entries here, never the version strings themselves.\n */\nexport const CLAUDE_MODEL_ALIASES: Record<string, string> = {\n 'claude-opus-4': CLAUDE_MODELS.OPUS_4,\n 'claude-sonnet-4': CLAUDE_MODELS.SONNET_4,\n 'claude-haiku-4': CLAUDE_MODELS.HAIKU_4,\n // Legacy alias — pre-4.x users routed to the current haiku.\n 'claude-haiku-3': CLAUDE_MODELS.HAIKU_4,\n} as const;\n\n/**\n * Configuration specific to ClaudeAdapter.\n */\nexport interface ClaudeAdapterConfig {\n /** Model ID (e.g., 'claude-sonnet-4' or full model identifier) */\n modelId: string;\n /** API key for Anthropic API (required) */\n apiKey: string;\n /** Base URL for API (optional, defaults to Anthropic's API) */\n baseUrl?: string;\n /** Request timeout in milliseconds (optional) */\n timeout?: number;\n /** Maximum retries for failed requests (optional) */\n maxRetries?: number;\n}\n\n// Note: Token estimation moved to core/token-estimator.ts (unified TokenEstimator)\n\n/**\n * Default maximum tokens for Claude models.\n */\nexport const DEFAULT_MAX_TOKENS = 4096;\n","/**\n * nexus-agents/adapters - Claude Adapter Helpers\n *\n * Helper functions for mapping between nexus-agents types and Anthropic SDK types.\n *\n * @module adapters/claude-adapter-helpers\n */\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type {\n MessageParam,\n ContentBlock as AnthropicContentBlock,\n} from '@anthropic-ai/sdk/resources/messages';\nimport type {\n ContentBlock,\n Message,\n ToolDefinition,\n StopReason,\n CompletionRequest,\n ResponseFormat,\n} from '../core/index.js';\nimport { ModelCapability } from '../core/index.js';\nimport { getCliModelName, resolveCliAlias } from '../config/model-config-helpers.js';\n\n/**\n * Name of the synthetic tool the adapter forces when a caller requests a\n * structured `responseFormat` (#3433). Anthropic has no native JSON mode, so\n * we model structured output as a forced `tool_use`.\n */\nexport const RESPOND_TOOL_NAME = 'respond';\n\n/**\n * Maps Anthropic stop reasons to our StopReason type.\n */\nexport function mapStopReason(anthropicReason: string | null): StopReason {\n switch (anthropicReason) {\n case 'end_turn':\n return 'end_turn';\n case 'max_tokens':\n return 'max_tokens';\n case 'stop_sequence':\n return 'stop_sequence';\n case 'tool_use':\n return 'tool_use';\n default:\n return 'end_turn';\n }\n}\n\n/**\n * Maps Anthropic content blocks to our ContentBlock type.\n */\nexport function mapContentBlock(block: AnthropicContentBlock): ContentBlock {\n if (block.type === 'text') {\n return { type: 'text', text: block.text };\n }\n if (block.type === 'tool_use') {\n const toolBlock = block;\n return {\n type: 'tool_use',\n id: toolBlock.id,\n name: toolBlock.name,\n input: toolBlock.input,\n };\n }\n // Handle unexpected block types gracefully\n return { type: 'text', text: '' };\n}\n\n/**\n * Maps our Message format to Anthropic's MessageParam format.\n */\nexport function mapMessage(message: Message): MessageParam {\n const role = message.role === 'user' ? 'user' : 'assistant';\n\n if (typeof message.content === 'string') {\n return { role, content: message.content };\n }\n\n // Map content blocks\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 === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n if (block.type === 'tool_result') {\n const toolResult: {\n type: 'tool_result';\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n } = {\n type: 'tool_result' as const,\n tool_use_id: block.tool_use_id,\n content: block.content,\n };\n // Only set is_error if explicitly defined (exactOptionalPropertyTypes)\n if (block.is_error !== undefined) {\n toolResult.is_error = block.is_error;\n }\n return toolResult;\n }\n // Image type is the remaining possibility\n // Cast source to match Anthropic's expected type\n return {\n type: 'image' as const,\n source: block.source as Anthropic.ImageBlockParam['source'],\n };\n });\n\n return { role, content };\n}\n\n/**\n * Maps our ToolDefinition to Anthropic's tool format.\n */\nexport function mapTool(tool: ToolDefinition): Anthropic.Tool {\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema as Anthropic.Tool.InputSchema,\n };\n}\n\n/**\n * Whether this request asks the Claude adapter to produce structured output\n * via a forced `respond` tool_use (#3433). True only when `responseFormat` is\n * present and not the plain `text` form.\n */\nexport function forcesResponseTool(request: CompletionRequest): boolean {\n return request.responseFormat !== undefined && request.responseFormat.type !== 'text';\n}\n\n/**\n * Builds the synthetic `respond` tool for a non-text responseFormat (#3433).\n * For `json_schema` the caller's schema becomes the tool `input_schema`; for\n * `json_object` we use a permissive `{ type: 'object' }` schema.\n */\nexport function buildRespondTool(format: ResponseFormat | undefined): Anthropic.Tool {\n const inputSchema: Record<string, unknown> =\n format?.type === 'json_schema' ? format.schema : { type: 'object' };\n return mapTool({\n name: RESPOND_TOOL_NAME,\n description:\n 'Return the structured response for this request. Call this tool exactly once with the full answer as its arguments.',\n inputSchema,\n });\n}\n\n/**\n * Maps an Anthropic response body when a forced `respond` tool was requested\n * (#3433). If the model emitted a `respond` tool_use block, its `.input` is\n * surfaced as a single JSON `text` block so existing text/JSON parsers keep\n * working unchanged. Otherwise falls back to the standard block mapping.\n */\nexport function mapResponseWithRespondTool(\n blocks: readonly AnthropicContentBlock[]\n): ContentBlock[] {\n const respondBlock = blocks.find(\n (block) => block.type === 'tool_use' && block.name === RESPOND_TOOL_NAME\n );\n if (respondBlock?.type === 'tool_use') {\n return [{ type: 'text', text: JSON.stringify(respondBlock.input) }];\n }\n return blocks.map(mapContentBlock);\n}\n\n/**\n * Resolves a Claude model alias to the full identifier the SDK expects.\n *\n * `resolveCliAlias` consults the canonical registry — both the cliAlias /\n * id columns AND the `aliases` array (#2199 Child 5 migration). Unknown\n * ids pass through (e.g., custom Bedrock identifiers).\n *\n * The canonical model strings live in `config/in-tree-data.ts` and are\n * resolved through the ModelRegistry; this function never holds them\n * directly (issue #2186 Child 1).\n */\nexport function resolveModelId(modelId: string): string {\n const registryId = resolveCliAlias(modelId);\n if (registryId !== undefined) return getCliModelName(registryId);\n return modelId;\n}\n\n/**\n * Determines capabilities based on model ID.\n */\nexport function getModelCapabilities(modelId: string): readonly ModelCapability[] {\n const capabilities: ModelCapability[] = [\n ModelCapability.COMPLETION,\n ModelCapability.STREAMING,\n ModelCapability.TOOL_USE,\n ModelCapability.VISION,\n ];\n\n // Extended thinking is available on Opus and Sonnet 4\n const resolvedId = resolveModelId(modelId);\n if (resolvedId.includes('opus') || resolvedId.includes('sonnet-4')) {\n capabilities.push(ModelCapability.EXTENDED_THINKING);\n }\n\n return capabilities;\n}\n","/**\n * Shared prompt extraction utilities for model adapters.\n *\n * Consolidates the duplicated extractSystemPrompt logic from\n * claude-adapter, gemini-adapter, and ollama-adapter into a single\n * implementation.\n *\n * @module adapters/prompt-utils\n * (Source: Issue #1596 — DRY adapter standardization)\n */\n\nimport type { CompletionRequest } from '../core/index.js';\nimport { extractSystemPrompt } from '../context/token-counter-helpers.js';\n\n/**\n * Extracts the system prompt from a CompletionRequest.\n *\n * Checks the explicit `systemPrompt` field first, then falls back to\n * searching the messages array for a system-role message.\n */\nexport function extractRequestSystemPrompt(request: CompletionRequest): string | undefined {\n if (request.systemPrompt !== undefined && request.systemPrompt !== '') {\n return request.systemPrompt;\n }\n return extractSystemPrompt(request.messages);\n}\n","/* eslint max-lines: [\"error\", { \"max\": 500, \"skipBlankLines\": true, \"skipComments\": true }] */\n// AI SDK model lifecycle, response mapping, and error fidelity remain cohesive\n// under the file's governance allowance (#6618).\n/**\n * nexus-agents/adapters/sdk - Base SDK Adapter\n *\n * Implements IModelAdapter using the Vercel AI SDK's generateText/streamText\n * APIs. Provides a unified adapter for any AI SDK-supported provider.\n *\n * @module adapters/sdk/sdk-adapter\n * (Source: Issue #1123 — AI SDK provider layer)\n */\n\nimport type {\n CompletionRequest,\n CompletionResponse,\n ContentBlock,\n ResponseFormat,\n StreamChunk,\n Result,\n ILogger,\n TokenUsage,\n IModelAdapter,\n} from '../../core/index.js';\nimport { ModelError, ModelCapability, createLogger, getErrorMessage } from '../../core/index.js';\nimport { BaseAdapter, AdapterModelError } from '../base-adapter.js';\nimport { ErrorCode, ok } from '../../core/index.js';\nimport {\n isRateLimitLikeError,\n resolveRetryAfterMs,\n RETRY_AFTER_CONTEXT_KEY,\n} from '../rate-limit-detector.js';\nimport { sanitizeOutput } from '../../security/output-sanitizer.js';\nimport { PROVIDER_ENV_KEYS, type SdkAdapterConfig, type SdkProviderId } from './types.js';\nimport {\n readCustomApiSurface,\n readDirectOpenAiSurface,\n readGatewayEnv,\n redactApiKey,\n} from './gateway-env.js';\nimport { readGatewayTransport } from '../gateway-http.js';\nimport {\n createOpenAICompatClient,\n validateOpenAICompatBaseUrl,\n type OpenAICompatConfig,\n} from '../openai-compat-adapter.js';\nimport { planOptionalParams, type DroppedParam } from '../optional-params.js';\n\n/** Minimal AI SDK model interface (duck-typed for optional dependency). */\ninterface AiSdkModel {\n readonly modelId: string;\n}\n\n/** AI SDK generateText result shape (duck-typed). */\ninterface GenerateTextResult {\n text: string;\n finishReason: string;\n usage: {\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n totalTokens: number | undefined;\n };\n response: { modelId: string };\n}\n\n/** AI SDK streamText result shape (duck-typed). */\ninterface StreamTextResult {\n textStream: AsyncIterable<string>;\n finishReason?: Promise<string> | string | undefined;\n}\n\n/** AI SDK generateObject result shape (duck-typed). */\ninterface GenerateObjectResult {\n object: unknown;\n finishReason: string;\n usage: {\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n totalTokens: number | undefined;\n };\n response: { modelId: string };\n}\n\n/** Maps SDK counters without presenting a partial component sum as a total. */\nfunction mapSdkUsage(usage: GenerateTextResult['usage']): TokenUsage | undefined {\n const { inputTokens, outputTokens, totalTokens } = usage;\n if (totalTokens !== undefined) {\n return { inputTokens: inputTokens ?? 0, outputTokens: outputTokens ?? 0, totalTokens };\n }\n if (inputTokens === undefined || outputTokens === undefined) return undefined;\n return { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens };\n}\n\n/** Opaque schema handle returned by the AI SDK `jsonSchema` helper. */\ntype AiSdkSchema = unknown;\n\n/** Function signatures for AI SDK entry points (loaded dynamically). */\ninterface AiSdkFunctions {\n generateText: (options: Record<string, unknown>) => Promise<GenerateTextResult>;\n streamText: (options: Record<string, unknown>) => StreamTextResult;\n generateObject: (options: Record<string, unknown>) => Promise<GenerateObjectResult>;\n jsonSchema: (schema: Record<string, unknown>) => AiSdkSchema;\n}\n\n/** AI SDK provider factory: creates a provider instance that is callable as a model factory. */\ntype ProviderFactory = (opts: Record<string, unknown>) => ProviderInstance;\n\n/**\n * AI SDK provider instance: callable to create a model on the provider's\n * default surface. `@ai-sdk/openai` also exposes `.chat` and `.responses`\n * (#6645); they are optional here because other providers lack them.\n */\ntype ProviderInstance = ((id: string) => AiSdkModel) & {\n readonly chat?: (id: string) => AiSdkModel;\n readonly responses?: (id: string) => AiSdkModel;\n};\n\n/** Build an OpenAI-provider model on the chosen API surface (#6645, #6654). */\nfunction modelOnSurface(\n provider: ProviderInstance,\n surface: ReturnType<typeof readCustomApiSurface>,\n modelId: string\n): AiSdkModel {\n const build = surface === 'chat' ? provider.chat : provider.responses;\n if (typeof build !== 'function') {\n throw new Error(`AI SDK OpenAI provider has no '${surface}' model factory`);\n }\n return build(modelId);\n}\n\n/** The API surface an adapter's provider is pinned to, read once at construction. */\nfunction apiSurfaceFor(\n providerId: SdkProviderId\n): ReturnType<typeof readCustomApiSurface> | undefined {\n if (providerId === 'openai') return readDirectOpenAiSurface();\n return undefined;\n}\n\n/**\n * Extracts a named provider factory from a dynamically-imported AI SDK module.\n *\n * AI SDK provider modules export factory functions (e.g., createAnthropic, createOpenAI)\n * that return callable provider instances. Since these are optional peer dependencies\n * loaded via dynamic import, we validate the shape at runtime rather than relying on\n * compile-time types.\n */\nfunction extractProviderFactory(\n mod: Record<string, unknown>,\n factoryName: string\n): ProviderFactory {\n const factory = mod[factoryName];\n if (typeof factory !== 'function') {\n throw new Error(`AI SDK module missing expected export: ${factoryName}`);\n }\n return factory as ProviderFactory;\n}\n\n/**\n * Validates a dynamically-imported AI SDK module has the expected generateText/streamText exports.\n *\n * The 'ai' package is an optional peer dependency loaded via dynamic import.\n * We validate the shape at runtime to avoid unsafe casts.\n */\n/**\n * Validate that a dynamically-imported `ai` module exposes the functions this\n * adapter needs; throw a clear, per-export error otherwise. Exported for direct\n * unit testing (#3449) so the \"missing export\" cases don't need a global module\n * mock (`vi.doMock`/`resetModules`), whose state leaked across parallel tests.\n */\nexport function extractAiSdkFunctions(mod: Record<string, unknown>): AiSdkFunctions {\n const generateText = mod['generateText'];\n const streamText = mod['streamText'];\n const generateObject = mod['generateObject'];\n const jsonSchema = mod['jsonSchema'];\n if (typeof generateText !== 'function') {\n throw new Error(\"AI SDK module missing expected export: 'generateText'\");\n }\n if (typeof streamText !== 'function') {\n throw new Error(\"AI SDK module missing expected export: 'streamText'\");\n }\n // #3433: structured output routes through generateObject + jsonSchema.\n if (typeof generateObject !== 'function') {\n throw new Error(\"AI SDK module missing expected export: 'generateObject'\");\n }\n if (typeof jsonSchema !== 'function') {\n throw new Error(\"AI SDK module missing expected export: 'jsonSchema'\");\n }\n return {\n generateText: generateText as AiSdkFunctions['generateText'],\n streamText: streamText as AiSdkFunctions['streamText'],\n generateObject: generateObject as AiSdkFunctions['generateObject'],\n jsonSchema: jsonSchema as AiSdkFunctions['jsonSchema'],\n };\n}\n\n/**\n * Runtime-validates the duck-typed `generateObject` result shape (#3433).\n *\n * `generateObject` comes from the optional `ai` peer dependency, so its\n * result is `unknown` to us. We narrow it here rather than casting, so a\n * shape change in the SDK surfaces as a clear error instead of a silent\n * `undefined` downstream.\n */\nfunction isGenerateObjectResult(value: unknown): value is GenerateObjectResult {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Record<string, unknown>;\n if (!('object' in record)) return false;\n if (typeof record['finishReason'] !== 'string') return false;\n const usage = record['usage'];\n if (typeof usage !== 'object' || usage === null) return false;\n const response = record['response'];\n if (typeof response !== 'object' || response === null) return false;\n if (typeof (response as Record<string, unknown>)['modelId'] !== 'string') return false;\n return true;\n}\n\n/**\n * Resolves the API key for a given provider.\n * Priority: explicit config > environment variable. The `custom-openai`\n * key goes through the canonical gateway-env resolver.\n */\nfunction resolveApiKey(providerId: SdkProviderId, configKey?: string): string | undefined {\n if (configKey !== undefined) return configKey;\n if (providerId === 'custom-openai') return readGatewayEnv().apiKey;\n return process.env[PROVIDER_ENV_KEYS[providerId]];\n}\n\n/** Resolve the custom alias through the gateway's canonical validation and transport. */\nfunction gatewayConfigFor(\n config: SdkAdapterConfig,\n apiKey: string | undefined,\n logger: ILogger\n): OpenAICompatConfig | undefined {\n if (config.providerId !== 'custom-openai') return undefined;\n const baseUrl = validateOpenAICompatBaseUrl(config.baseUrl ?? readGatewayEnv().baseUrl);\n return {\n baseUrl,\n apiKey: apiKey ?? '',\n logger,\n omitDefaultTokenCap: true,\n ...readGatewayTransport(baseUrl, process.env, logger),\n apiSurface: readCustomApiSurface(),\n ...(config.timeout !== undefined && { timeout: config.timeout }),\n ...(config.maxRetries !== undefined && { maxRetries: config.maxRetries }),\n };\n}\n\n/**\n * Maps AI SDK finish reasons to our StopReason type.\n */\nfunction mapFinishReason(reason: string): CompletionResponse['stopReason'] {\n switch (reason) {\n case 'stop':\n case 'end-turn':\n return 'end_turn';\n case 'length':\n return 'max_tokens';\n case 'tool-calls':\n return 'tool_use';\n // #6618: 'content-filter' is never mapped as a finish: the adapter turns it into\n // an error before a response is built (see assertValidCompletion), because\n // every consumer reads a mapped response as an answer.\n default:\n return 'end_turn';\n }\n}\n\n/** A completion that must surface as an error, never as an empty success (#6607, #6618). */\ninterface NonAnswer {\n /** Why the completion carries no answer. */\n readonly reason: 'content_filter' | 'reasoning_truncated';\n readonly detail: string;\n readonly reasoningTokens?: number;\n}\n\nconst CONTENT_FILTERED: NonAnswer = {\n reason: 'content_filter',\n detail: 'the reply was blocked by a content filter',\n};\n\nconst REASONING_TRUNCATED: NonAnswer = {\n reason: 'reasoning_truncated',\n detail:\n 'the completion budget was spent on reasoning before any output (empty reply, finish length)',\n};\n\n/**\n * A non-answer as a non-retryable `MODEL_ERROR` (#6607, #6618). `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 */\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 * Classifies whether a completion result is a non-answer and throws a `ModelError` if so (#6618).\n */\nfunction assertValidCompletion(\n source: string,\n finishReason: string,\n hasContent: boolean,\n servedModel?: string\n): void {\n if (finishReason === 'content-filter') {\n throw nonAnswerError(source, CONTENT_FILTERED, servedModel);\n }\n if (finishReason === 'length' && !hasContent) {\n throw nonAnswerError(source, REASONING_TRUNCATED, servedModel);\n }\n}\n\n/**\n * Awaits and validates the stream finish reason (#6618).\n */\nasync function assertValidStreamFinish(\n source: string,\n result: StreamTextResult,\n totalText: string\n): Promise<void> {\n if (result.finishReason === undefined) return;\n const finishReason = await result.finishReason;\n assertValidCompletion(source, finishReason, totalText !== '');\n}\n\n/**\n * Categorizes an error into an ErrorCode for the circuit breaker.\n */\nfunction categorizeError(error: unknown): ErrorCode {\n if (isRateLimitLikeError(error)) {\n return ErrorCode.MODEL_RATE_LIMITED;\n }\n const message = getErrorMessage(error).toLowerCase();\n if (message.includes('timeout') || message.includes('timed out')) {\n return ErrorCode.MODEL_TIMEOUT;\n }\n if (message.includes('401') || message.includes('unauthorized') || message.includes('api key')) {\n return ErrorCode.CONFIG_INVALID;\n }\n return ErrorCode.MODEL_ERROR;\n}\n\n/**\n * AI SDK adapter implementing IModelAdapter.\n *\n * Uses Vercel AI SDK (npm: ai) for model interaction instead of\n * CLI subprocess spawning. Built-in providers use their `@ai-sdk/*` package;\n * the public custom-openai identifier delegates to the gateway HTTP adapter.\n */\nexport class SdkAdapter extends BaseAdapter {\n private readonly sdkProviderId: SdkProviderId;\n private model: AiSdkModel | undefined;\n private sdkFunctions: AiSdkFunctions | undefined;\n private readonly sdkConfig: SdkAdapterConfig;\n /** Compatibility-only custom provider delegates to the canonical gateway client. */\n private readonly gatewayConfig: OpenAICompatConfig | undefined;\n private gatewayAdapter: IModelAdapter | undefined;\n /**\n * OpenAI API surface: for the direct `openai` provider only when `OPENAI_BASE_URL` names a non-OpenAI host\n * (#6654). `undefined` keeps the provider's default surface.\n */\n private readonly apiSurface: ReturnType<typeof readCustomApiSurface> | undefined;\n /** Inflight init promise for coalescing concurrent calls (Issue #1438). */\n private initPromise: Promise<void> | undefined;\n constructor(config: SdkAdapterConfig, logger?: ILogger) {\n const apiKey = resolveApiKey(config.providerId, config.apiKey);\n super({\n providerId: `sdk-${config.providerId}`,\n modelId: config.modelId,\n capabilities: [ModelCapability.COMPLETION, ModelCapability.STREAMING],\n logger: logger ?? createLogger({ adapter: `sdk-${config.providerId}` }),\n ...(apiKey !== undefined ? { apiKey } : {}),\n ...(config.timeout !== undefined ? { timeout: config.timeout } : {}),\n ...(config.maxRetries !== undefined ? { maxRetries: config.maxRetries } : {}),\n });\n this.sdkProviderId = config.providerId;\n this.sdkConfig = config;\n this.gatewayConfig = gatewayConfigFor(config, apiKey, this.logger);\n this.apiSurface = apiSurfaceFor(config.providerId);\n }\n\n /** Lazily acquire the B client, preserving missing-key failure at first use. */\n private resolveGatewayAdapter(): IModelAdapter | undefined {\n if (this.gatewayConfig === undefined) return undefined;\n if (this.gatewayAdapter !== undefined) return this.gatewayAdapter;\n const apiKey = resolveApiKey(this.sdkConfig.providerId, this.sdkConfig.apiKey);\n if (apiKey === undefined) {\n throw new AdapterModelError(`No API key for ${this.sdkConfig.providerId}`, {\n code: ErrorCode.CONFIG_INVALID,\n });\n }\n this.gatewayAdapter = createOpenAICompatClient(this.modelId, { ...this.gatewayConfig, apiKey });\n return this.gatewayAdapter;\n }\n\n /**\n * Lazily initialize the AI SDK model and functions.\n * This allows the adapter to be created without the AI SDK installed,\n * failing only when actually used.\n */\n private async ensureInitialized(): Promise<void> {\n if (this.model !== undefined) return;\n // Coalesce concurrent init calls into a single load (Issue #1438)\n if (this.initPromise !== undefined) {\n await this.initPromise;\n return;\n }\n this.initPromise = this.doInitialize();\n try {\n await this.initPromise;\n } finally {\n this.initPromise = undefined;\n }\n }\n\n private async doInitialize(): Promise<void> {\n const apiKey = resolveApiKey(this.sdkConfig.providerId, this.sdkConfig.apiKey);\n if (apiKey === undefined) {\n throw new AdapterModelError(`No API key for ${this.sdkProviderId}`, {\n code: ErrorCode.CONFIG_INVALID,\n });\n }\n\n // Dynamic import — AI SDK is an optional peer dependency\n const providerModule = await this.loadProvider(apiKey);\n this.model = providerModule.model;\n\n // AI SDK is an optional peer dependency — validate shape at runtime\n const aiModule = await import('ai');\n this.sdkFunctions = extractAiSdkFunctions(aiModule);\n }\n\n /**\n * Loads the provider-specific AI SDK module.\n *\n * Each @ai-sdk/* package exports a factory function (e.g., createAnthropic)\n * that returns a callable provider instance. We use extractProviderFactory()\n * to validate the export exists at runtime, since these are optional peer deps.\n */\n private async loadProvider(apiKey: string): Promise<{ model: AiSdkModel }> {\n switch (this.sdkProviderId) {\n case 'custom-openai':\n throw new AdapterModelError('custom-openai must use the gateway HTTP adapter', {\n code: ErrorCode.CONFIG_INVALID,\n });\n case 'anthropic': {\n const mod = await import('@ai-sdk/anthropic');\n const factory = extractProviderFactory(mod, 'createAnthropic');\n const provider = factory({ apiKey });\n return { model: provider(this.modelId) };\n }\n case 'openai': {\n const mod = await import('@ai-sdk/openai');\n const factory = extractProviderFactory(mod, 'createOpenAI');\n const provider = factory({ apiKey });\n // The provider reads OPENAI_BASE_URL itself; a gateway there gets chat\n // completions unless NEXUS_CUSTOM_API_SURFACE=responses (#6654).\n if (this.apiSurface === undefined) return { model: provider(this.modelId) };\n return { model: modelOnSurface(provider, this.apiSurface, this.modelId) };\n }\n case 'google': {\n const mod = await import('@ai-sdk/google');\n const factory = extractProviderFactory(mod, 'createGoogleGenerativeAI');\n const provider = factory({ apiKey });\n return { model: provider(this.modelId) };\n }\n }\n }\n\n /**\n * Maps our CompletionRequest to AI SDK generateText options.\n */\n private buildSdkOptions(request: CompletionRequest): {\n options: Record<string, unknown>;\n dropped: readonly DroppedParam[];\n } {\n const options: Record<string, unknown> = {\n model: this.model,\n messages: request.messages.map((m) => ({\n role: m.role === 'system' ? 'system' : m.role,\n content:\n typeof m.content === 'string'\n ? m.content\n : m.content.map((c: ContentBlock) => {\n if (c.type === 'text') return { type: 'text' as const, text: c.text };\n return c;\n }),\n })),\n };\n\n if (request.systemPrompt !== undefined) {\n options['system'] = request.systemPrompt;\n }\n // #4068: the temperature drop-decision (#4061/#4062: Claude after Opus 4.6 and\n // OpenAI reasoning models reject a non-1.0 temperature with a 400; the AI-SDK\n // path routes to both, so omit the param for those models — 1.0 is the API\n // default, equivalent) is centralized in the shared planOptionalParams seam.\n const plan = planOptionalParams(request, this.modelId);\n if (plan.temperature !== undefined) {\n options['temperature'] = plan.temperature;\n }\n if (request.maxTokens !== undefined) {\n options['maxTokens'] = request.maxTokens;\n }\n if (request.stop !== undefined) {\n options['stopSequences'] = request.stop;\n }\n\n // #4069: report dropped params so complete() can surface them as warnings.\n return { options, dropped: plan.dropped };\n }\n\n /**\n * generateText path (text / absent responseFormat) — unchanged behavior.\n */\n private async completeText(\n sdk: AiSdkFunctions,\n options: Record<string, unknown>\n ): Promise<CompletionResponse> {\n const result = await sdk.generateText(options);\n assertValidCompletion(\n `${this.providerId}/${this.modelId}`,\n result.finishReason,\n result.text !== '' && result.text.trim() !== '',\n result.response.modelId\n );\n const usage = mapSdkUsage(result.usage);\n return {\n content: [{ type: 'text', text: result.text }],\n ...(usage !== undefined ? { usage } : {}),\n stopReason: mapFinishReason(result.finishReason),\n model: result.response.modelId,\n };\n }\n\n /**\n * generateObject path (#3433) — json_object / json_schema responseFormat.\n *\n * Uses the AI SDK `jsonSchema` helper to build the schema handle\n * (permissive `{ type: 'object' }` for json_object), then stringifies the\n * returned object into a text content block so downstream parsers /\n * extractTextFromResponse keep working unchanged.\n */\n private async completeStructured(\n sdk: AiSdkFunctions,\n options: Record<string, unknown>,\n responseFormat: Exclude<ResponseFormat, { type: 'text' }>\n ): Promise<CompletionResponse> {\n const rawSchema: Record<string, unknown> =\n responseFormat.type === 'json_schema' ? responseFormat.schema : { type: 'object' };\n const schema = sdk.jsonSchema(rawSchema);\n const result: unknown = await sdk.generateObject({ ...options, schema });\n if (!isGenerateObjectResult(result)) {\n throw new Error(\n 'AI SDK generateObject returned an unexpected result shape ' +\n '(missing object/usage/finishReason/response.modelId)'\n );\n }\n assertValidCompletion(\n `${this.providerId}/${this.modelId}`,\n result.finishReason,\n result.object !== null && result.object !== undefined,\n result.response.modelId\n );\n const usage = mapSdkUsage(result.usage);\n return {\n content: [{ type: 'text', text: JSON.stringify(result.object) }],\n ...(usage !== undefined ? { usage } : {}),\n stopReason: mapFinishReason(result.finishReason),\n model: result.response.modelId,\n };\n }\n\n async complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>> {\n try {\n const gateway = this.resolveGatewayAdapter();\n if (gateway !== undefined) return await gateway.complete(request);\n await this.ensureInitialized();\n this.logRequest(request);\n\n const sdk = this.sdkFunctions;\n if (sdk === undefined) {\n throw new Error(\n `SDK not initialized for model '${this.sdkConfig.modelId}' (provider: ${this.sdkProviderId}). ` +\n 'Ensure ensureInitialized() completes before calling complete().'\n );\n }\n const { options, dropped } = this.buildSdkOptions(request);\n\n // #3433: native structured output. json_object/json_schema route\n // through generateObject; everything else keeps the generateText path\n // unchanged.\n const responseFormat = request.responseFormat;\n const base =\n responseFormat !== undefined && responseFormat.type !== 'text'\n ? await this.completeStructured(sdk, options, responseFormat)\n : await this.completeText(sdk, options);\n\n // #4069: surface params dropped by the seam (e.g. temperature) as warnings.\n // Omitted entirely when nothing was dropped (exactOptionalPropertyTypes).\n const response: CompletionResponse =\n dropped.length > 0 ? { ...base, warnings: dropped } : base;\n\n this.logResponse(response);\n return ok(response);\n } catch (error: unknown) {\n const code = categorizeError(error);\n return this.toErrorResult(error, code);\n }\n }\n\n async *stream(request: CompletionRequest): AsyncIterable<StreamChunk> {\n const gateway = this.resolveGatewayAdapter();\n if (gateway !== undefined) {\n yield* gateway.stream(request);\n return;\n }\n // Ensure initialization and SDK readiness before entering the generator body.\n // Errors thrown before the first yield in an async generator bypass for-await-of\n // try/catch in callers, so we validate eagerly and wrap the body in try/catch.\n await this.ensureInitialized();\n this.logRequest(request);\n\n const sdk = this.sdkFunctions;\n if (sdk === undefined) {\n throw new AdapterModelError('SDK not initialized after ensureInitialized()', {\n code: ErrorCode.CONFIG_INVALID,\n });\n }\n\n const { options } = this.buildSdkOptions(request);\n\n // First yield establishes the generator — errors after this point are\n // properly caught by callers using for-await-of with try/catch.\n yield { type: 'message_start', message: { model: this.modelId } };\n\n const result = sdk.streamText(options);\n let index = 0;\n yield { type: 'content_block_start', index, contentBlock: { type: 'text', text: '' } };\n\n let totalText = '';\n for await (const text of result.textStream) {\n // #3317 finding #8: skip empty-string deltas — the SDK can emit zero-length\n // chunks (keepalives/segment boundaries); a `text_delta` with `text: ''` is\n // noise that downstream re-assemblers must otherwise special-case.\n if (text === '') continue;\n totalText += text;\n yield {\n type: 'content_block_delta',\n index,\n delta: { type: 'text_delta', text },\n };\n }\n\n await assertValidStreamFinish(`${this.providerId}/${this.modelId}`, result, totalText);\n\n yield { type: 'content_block_stop', index };\n index++;\n yield {\n type: 'message_delta',\n delta: { stop_reason: 'end_turn' },\n // #4835: no usage is reported on this path, so none is emitted —\n // zero-filling all three made an unmeasured stream indistinguishable\n // from one that consumed nothing. `usage` is optional on the chunk.\n };\n yield { type: 'message_stop' };\n }\n\n /**\n * Converts a caught error into a Result error with categorized ErrorCode.\n */\n private toErrorResult(error: unknown, code: ErrorCode): Result<CompletionResponse, ModelError> {\n if (error instanceof ModelError) {\n this.logger.error(`SDK adapter error (${this.sdkConfig.providerId})`, error);\n return { ok: false, error };\n }\n\n // Scrub API keys + bearer tokens out of upstream SDK error messages\n // before they hit logs or the surfaced ModelError. Parity with the\n // subprocess-adapter path. Audit #2824. The RESOLVED key is redacted by\n // exact match first (#4392 inc 3): a gateway key has no vendor shape the\n // pattern sanitizer knows, and a 401 body may echo the key it rejected.\n const apiKey = resolveApiKey(this.sdkConfig.providerId, this.sdkConfig.apiKey);\n const safeMessage = sanitizeOutput(redactApiKey(getErrorMessage(error), apiKey));\n // Never the original object: its message AND its stack's first line carry\n // the raw text. The name is kept so the log still says what was thrown.\n const errorObj = new Error(safeMessage);\n if (error instanceof Error) errorObj.name = error.name;\n this.logger.error(`SDK adapter error (${this.sdkConfig.providerId})`, errorObj);\n // #4606: this path builds the ModelError itself rather than going through\n // `BaseAdapter.transformError`, so it has to capture the horizon too. The\n // AI SDK's `APICallError` carries `responseHeaders` as a plain record;\n // `resolveRetryAfterMs` reads only `retry-after` out of it and returns a\n // number, so no header bag reaches the error or the logs. Parsed off the\n // SANITIZED message, so a scrubbed credential can't be re-read from it.\n const retryAfterMs =\n code === ErrorCode.MODEL_RATE_LIMITED ? resolveRetryAfterMs(error, safeMessage) : undefined;\n // AdapterModelError extends ModelError — no cast needed\n const modelError = new AdapterModelError(\n `${this.sdkConfig.providerId} SDK error: ${safeMessage}`,\n {\n code,\n ...(retryAfterMs !== undefined\n ? { context: { [RETRY_AFTER_CONTEXT_KEY]: retryAfterMs } }\n : {}),\n }\n );\n return { ok: false, error: modelError };\n }\n}\n","/**\n * nexus-agents/cli-adapters - CLI Detection Cache\n *\n * Caches CLI health check results to avoid repeated subprocess calls.\n * Invalidates on circuit breaker trips or manual invalidation.\n *\n * @module cli-adapters/cli-detection-cache\n * (Source: Issue #165, Proposal adapter-architecture-review.md)\n */\n\nimport { z } from 'zod';\nimport { createLogger } from '../core/logger.js';\nimport type { ILogger } from '../core/index.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type { CliName, HealthStatus, VersionStatus } from './types.js';\n\n/**\n * Cached health result for a CLI.\n */\nexport interface CliHealthResult {\n /** Whether the CLI is healthy and available */\n readonly healthy: boolean;\n /** CLI version detected */\n readonly version: string;\n /** Version compatibility status */\n readonly versionStatus: VersionStatus;\n /** When this result was captured */\n readonly checkedAt: Date;\n /** Optional status message */\n readonly message?: string | undefined;\n}\n\n/**\n * Configuration for the CLI detection cache.\n */\nexport interface CliDetectionCacheConfig {\n /** Base time-to-live in milliseconds (default: 5 minutes) */\n readonly ttlMs: number;\n /** Enable adaptive TTL based on health history (default: true) */\n readonly adaptiveTtl?: boolean | undefined;\n /** Logger instance */\n readonly logger?: ILogger | undefined;\n}\n\n/**\n * Zod schema for cache configuration validation.\n */\nexport const CliDetectionCacheConfigSchema = z.object({\n ttlMs: z.number().min(1000).max(3600_000).default(300_000),\n});\n\n/**\n * Default cache configuration.\n */\nexport const DEFAULT_CACHE_CONFIG: CliDetectionCacheConfig = {\n ttlMs: 300_000, // 5 minutes\n adaptiveTtl: true,\n};\n\n/** Adaptive TTL multipliers. Healthy CLIs are polled less often; unhealthy more often. */\nconst ADAPTIVE_MULTIPLIER_HEALTHY = 2.0;\nconst ADAPTIVE_MULTIPLIER_UNHEALTHY = 0.25;\n/** Number of consecutive same-status results before the multiplier kicks in. */\nconst ADAPTIVE_STREAK_THRESHOLD = 2;\n\n/**\n * Interface for CLI detection cache.\n * Allows dependency injection for testing.\n */\nexport interface ICliDetectionCache {\n /** Get cached health result for a CLI */\n get(cli: CliName): CliHealthResult | undefined;\n\n /** Set health result for a CLI */\n set(cli: CliName, result: CliHealthResult): void;\n\n /** Check if cache entry is stale */\n isStale(cli: CliName): boolean;\n\n /** Invalidate cache for a specific CLI or all CLIs */\n invalidate(cli?: CliName): void;\n\n /** Get all cached results */\n getAll(): ReadonlyMap<CliName, CliHealthResult>;\n\n /** Get cache statistics */\n getStats(): CacheStats;\n\n /** Get effective TTL for a CLI (accounts for adaptive adjustments) */\n getEffectiveTtl(cli: CliName): number;\n}\n\n/**\n * Cache statistics for observability.\n */\nexport interface CacheStats {\n /** Number of cached entries */\n readonly size: number;\n /** Cache hits since last reset */\n readonly hits: number;\n /** Cache misses since last reset */\n readonly misses: number;\n /** Hit rate (0-1) */\n readonly hitRate: number;\n /** When stats were last reset */\n readonly lastReset: Date;\n}\n\n/**\n * CLI detection cache implementation.\n * Thread-safe for Node.js single-threaded execution.\n */\nexport class CliDetectionCache implements ICliDetectionCache {\n private readonly config: CliDetectionCacheConfig;\n private readonly logger: ILogger;\n private readonly cache: Map<CliName, CliHealthResult> = new Map();\n /** Consecutive same-health-status count per CLI (for adaptive TTL). */\n private readonly streaks: Map<CliName, { healthy: boolean; count: number }> = new Map();\n private hits = 0;\n private misses = 0;\n private lastReset: Date = new Date(getTimeProvider().now());\n\n constructor(config?: Partial<CliDetectionCacheConfig>) {\n const validated = CliDetectionCacheConfigSchema.parse({\n ttlMs: config?.ttlMs ?? DEFAULT_CACHE_CONFIG.ttlMs,\n });\n this.config = {\n ...validated,\n adaptiveTtl: config?.adaptiveTtl ?? DEFAULT_CACHE_CONFIG.adaptiveTtl,\n logger: config?.logger,\n };\n this.logger = config?.logger ?? createLogger({ component: 'CliDetectionCache' });\n\n this.logger.debug('CliDetectionCache initialized', { ttlMs: this.config.ttlMs });\n }\n\n get(cli: CliName): CliHealthResult | undefined {\n const result = this.cache.get(cli);\n\n if (result === undefined) {\n this.misses++;\n this.logger.debug('Cache miss', { cli });\n return undefined;\n }\n\n if (this.isStale(cli)) {\n this.misses++;\n this.logger.debug('Cache stale', { cli, checkedAt: result.checkedAt });\n return undefined;\n }\n\n this.hits++;\n this.logger.debug('Cache hit', { cli, healthy: result.healthy });\n return result;\n }\n\n set(cli: CliName, result: CliHealthResult): void {\n this.cache.set(cli, result);\n this.updateStreak(cli, result.healthy);\n this.logger.debug('Cache updated', {\n cli,\n healthy: result.healthy,\n version: result.version,\n });\n }\n\n isStale(cli: CliName): boolean {\n const result = this.cache.get(cli);\n if (result === undefined) return true;\n\n const age = getTimeProvider().now() - result.checkedAt.getTime();\n return age > this.getEffectiveTtl(cli);\n }\n\n /** Returns the effective TTL for a CLI, applying adaptive multiplier if enabled. */\n getEffectiveTtl(cli: CliName): number {\n if (this.config.adaptiveTtl === false) return this.config.ttlMs;\n const streak = this.streaks.get(cli);\n if (streak === undefined || streak.count < ADAPTIVE_STREAK_THRESHOLD) {\n return this.config.ttlMs;\n }\n const multiplier = streak.healthy ? ADAPTIVE_MULTIPLIER_HEALTHY : ADAPTIVE_MULTIPLIER_UNHEALTHY;\n return this.config.ttlMs * multiplier;\n }\n\n private updateStreak(cli: CliName, healthy: boolean): void {\n const prev = this.streaks.get(cli);\n if (prev?.healthy === healthy) {\n this.streaks.set(cli, { healthy, count: prev.count + 1 });\n } else {\n this.streaks.set(cli, { healthy, count: 1 });\n }\n }\n\n invalidate(cli?: CliName): void {\n if (cli !== undefined) {\n this.cache.delete(cli);\n this.streaks.delete(cli);\n this.logger.info('Cache invalidated', { cli });\n } else {\n this.cache.clear();\n this.streaks.clear();\n this.logger.info('Cache cleared');\n }\n }\n\n getAll(): ReadonlyMap<CliName, CliHealthResult> {\n return this.cache;\n }\n\n getStats(): CacheStats {\n const total = this.hits + this.misses;\n return {\n size: this.cache.size,\n hits: this.hits,\n misses: this.misses,\n hitRate: total > 0 ? this.hits / total : 0,\n lastReset: this.lastReset,\n };\n }\n\n /**\n * Resets cache statistics.\n */\n resetStats(): void {\n this.hits = 0;\n this.misses = 0;\n this.lastReset = new Date(getTimeProvider().now());\n this.logger.debug('Cache stats reset');\n }\n\n /**\n * Converts HealthStatus to CliHealthResult for caching.\n */\n static fromHealthStatus(status: HealthStatus): CliHealthResult {\n return {\n healthy: status.healthy,\n version: status.version,\n versionStatus: status.versionStatus,\n checkedAt: status.lastChecked,\n message: status.message,\n };\n }\n}\n\n/**\n * Creates a CLI detection cache instance.\n *\n * @param config - Optional cache configuration\n * @returns CLI detection cache\n *\n * @example\n * ```typescript\n * const cache = createCliDetectionCache({ ttlMs: 60_000 }); // 1 minute TTL\n * const result = cache.get('claude');\n * if (!result) {\n * const health = await adapter.healthCheck();\n * cache.set('claude', CliDetectionCache.fromHealthStatus(health));\n * }\n * ```\n */\nexport function createCliDetectionCache(\n config?: Partial<CliDetectionCacheConfig>\n): ICliDetectionCache {\n return new CliDetectionCache(config);\n}\n","/**\n * Compatibility gateway alias selection and its discovery provenance.\n * @module adapters/auto-adapter-gateway\n */\nimport type { ILogger, IModelAdapter } from '../core/index.js';\nimport type { AdapterSelection } from './auto-adapter.js';\nimport { createOpenAICompatClient, readOpenAICompatEnv } from './openai-compat-adapter.js';\nimport { hostnameOf, readCustomApiSurface, readGatewayEnv } from './sdk/gateway-env.js';\nimport { CUSTOM_API_DEFAULT_MODEL } from '../config/defaults.js';\nimport { resolveGatewayDefault } from './gateway-family-slots.js';\nimport { gatewayDiscoveryStatus } from './gateway-discovery.js';\nimport { withGatewayUsageRecording } from './gateway-usage-recording.js';\n\n/**\n * Keep the historical custom-openai arm over the canonical gateway client.\n * Catalogue selection reuses its resolved model id; the alias retains its\n * own API surface and token-cap policy. Only the hostname reaches the log.\n */\nexport function tryCustomOpenAiAdapter(logger: ILogger): AdapterSelection | null {\n const { baseUrl: customBaseUrl, apiKey: customKey } = readGatewayEnv();\n if (customKey === undefined || customBaseUrl === undefined) return null;\n const choice = customModelChoice(logger);\n if (choice === null) return null;\n const { adapter, note } = choice;\n const customModelId = adapter.modelId;\n const modelVerified = choice.modelVerified;\n const host = hostnameOf(customBaseUrl);\n logger.info('Using custom-openai gateway alias', { model: customModelId, host });\n return {\n // Snapshot the selection on the call's adapter, rather than reading the\n // resilient proxy's mutable health after a refresh/failover (#6862).\n // Always wrapped, so pricing never depends on whether discovery measured\n // the choice: every custom-openai call is priced by the gateway declaration.\n adapter: withGatewayUsageRecording(\n adapter,\n 'api:custom-openai',\n modelVerified,\n 'sdk-custom-openai'\n ),\n source: 'api',\n name: 'custom-openai',\n reason: `Using custom OpenAI-compatible gateway at ${host} (model: ${customModelId}${note})`,\n ...(modelVerified !== undefined && { modelVerified }),\n };\n}\n\n/**\n * The model the custom-openai adapter sends. With no gateway catalogue it is\n * `NEXUS_CUSTOM_MODEL` or the built-in default, exactly as before #6626. In\n * gateway mode it is a matched catalogue model (`resolveGatewayDefault`);\n * after failed discovery the configured id is explicitly unverified.\n * Null when the catalogue holds no chat model. Absence of verification means\n * no discovery measured this choice.\n */\nfunction customModelChoice(\n logger: ILogger\n): { adapter: IModelAdapter; note: string; modelVerified?: boolean } | null {\n const d = resolveGatewayDefault(process.env, logger);\n if (d.kind === 'unavailable') {\n logger.warn('Gateway catalogue has no chat model; the custom-openai default is unavailable');\n return null;\n }\n const config = readOpenAICompatEnv();\n if (config === null) return null;\n const modelId =\n d.kind === 'resolved'\n ? d.adapter.modelId\n : (process.env['NEXUS_CUSTOM_MODEL'] ?? CUSTOM_API_DEFAULT_MODEL);\n const adapter = createOpenAICompatClient(modelId, {\n ...config,\n logger,\n apiSurface: readCustomApiSurface(),\n omitDefaultTokenCap: true,\n });\n if (d.kind === 'resolved')\n return {\n adapter,\n note: `; gateway default by ${d.via}`,\n modelVerified: true,\n };\n if (gatewayDiscoveryStatus() !== 'failed') return { adapter, note: '' };\n // #4392: failed discovery leaves this configured model explicitly unverified.\n logger.warn(\n `Gateway discovery failed, so the custom-openai model '${modelId}' is sent unverified; ` +\n 'set NEXUS_CUSTOM_MODEL to a model the gateway serves, or run `nexus-agents doctor --gateway`',\n { model: modelId }\n );\n return { adapter, note: '; unverified: gateway discovery failed', modelVerified: false };\n}\n","/**\n * Auto-Selecting Model Adapter Factory\n *\n * Automatically selects the best available adapter:\n * 1. CLI adapters (claude/gemini/codex) - OAuth, no API keys needed\n * The CLIs handle model selection internally.\n * 2. API adapters (Anthropic/OpenAI) - requires API keys (fallback)\n *\n * Supports optional caching to avoid repeated CLI health checks.\n *\n * @module adapters/auto-adapter\n * (Source: Issue #165 - CLI detection cache)\n */\n\nimport type { IModelAdapter, ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { createCliAdapter, isCliAvailable, getAvailableClis } from '../cli-adapters/factory.js';\nimport { isCliDisabled } from '../cli-adapters/disabled-clis.js';\nimport {\n createGatewaySlotAdapter,\n hasGatewaySlotCatalog,\n resolveGatewaySlot,\n} from './gateway-family-slots.js';\nimport { createCliToModelAdapter } from '../cli-adapters/cli-to-model-adapter.js';\nimport { createModelToCliAdapter } from '../cli-adapters/model-to-cli-adapter.js';\nimport { createClaudeAdapter } from './claude-adapter.js';\nimport { SdkAdapter } from './sdk/index.js';\nimport { warnIfGatewayCostUndeclared } from './sdk/gateway-cost.js';\nimport type { CliName, ICliAdapter, ApiVendor, ApiArmId } from '../cli-adapters/types.js';\nimport { apiArmId } from '../cli-adapters/types.js';\nimport { buildCliCapabilityProfiles } from '../config/model-config-helpers.js';\nimport type { ICliDetectionCache } from '../cli-adapters/cli-detection-cache.js';\nimport { createCliDetectionCache } from '../cli-adapters/cli-detection-cache.js';\nimport { ensureGatewayDiscovered } from './gateway-rediscovery.js';\nimport { tryCustomOpenAiAdapter } from './auto-adapter-gateway.js';\nimport { getCliModelName, getDefaultModelForCli } from '../config/model-config-helpers.js';\n\n/**\n * Adapter selection priority.\n */\nexport type AdapterPriority = 'cli-first' | 'api-first' | 'cli-only' | 'api-only';\n\n/**\n * Configuration for auto-selecting adapters.\n */\nexport interface AutoAdapterConfig {\n /** Selection priority (default: 'cli-first') */\n readonly priority?: AdapterPriority;\n /** Preferred CLI if multiple available (optional) */\n readonly preferredCli?: CliName;\n /** API key for Anthropic (optional, for fallback) */\n readonly anthropicApiKey?: string;\n /** API key for OpenAI (optional, for fallback via AI SDK) */\n readonly openaiApiKey?: string;\n /** API key for Google AI (optional, for fallback via AI SDK) */\n readonly googleApiKey?: string;\n /** Logger instance */\n readonly logger?: ILogger;\n /** CLI detection cache (optional, creates new if not provided) */\n readonly cache?: ICliDetectionCache;\n /** Whether to create and use cache if not provided (default: true) */\n readonly enableCache?: boolean;\n /** Default timeout for CLI subprocess calls (ms). Overrides auto-detection. */\n readonly defaultCliTimeoutMs?: number;\n}\n\n/**\n * Result of adapter selection.\n */\nexport interface AdapterSelection {\n /** The selected adapter */\n readonly adapter: IModelAdapter;\n /** Source of the adapter */\n readonly source: 'cli' | 'api';\n /** Which CLI or API was selected */\n readonly name: string;\n /** Why this adapter was selected */\n readonly reason: string;\n /** Gateway catalogue matched the selected model. False on failed discovery; absent = unmeasured. */\n readonly modelVerified?: boolean;\n /** The cache used for CLI detection (for reuse) */\n readonly cache?: ICliDetectionCache | undefined;\n}\n\nconst defaultLogger = createLogger({ component: 'auto-adapter' });\n\n/**\n * Resolves the cache to use based on configuration.\n */\nfunction resolveCache(config: AutoAdapterConfig, logger: ILogger): ICliDetectionCache | undefined {\n if (config.cache !== undefined) {\n return config.cache;\n }\n const enableCache = config.enableCache ?? true;\n return enableCache ? createCliDetectionCache({ logger }) : undefined;\n}\n\n/** The CLI bridge's timeout config, when the caller set one. */\nfunction cliBridgeConfig(config: AutoAdapterConfig): { defaultTimeoutMs: number } | undefined {\n return config.defaultCliTimeoutMs !== undefined\n ? { defaultTimeoutMs: config.defaultCliTimeoutMs }\n : undefined;\n}\n\n/**\n * Attempts to create a CLI-based model adapter.\n * The CLI tools (claude, gemini, codex) handle their own model selection.\n * Uses cache to avoid repeated health checks.\n */\nasync function tryCliAdapter(\n config: AutoAdapterConfig,\n logger: ILogger,\n cache?: ICliDetectionCache\n): Promise<AdapterSelection | null> {\n const preferredCli = config.preferredCli;\n const bridgeConfig = cliBridgeConfig(config);\n\n // #6590: a preferred CLI disabled by NEXUS_DISABLED_CLIS is skipped, not\n // probed. The registry pins every per-CLI adapter through this field.\n if (preferredCli !== undefined && isCliDisabled(preferredCli)) {\n logger.info('Preferred CLI is disabled by NEXUS_DISABLED_CLIS', { cli: preferredCli });\n }\n\n // If preferred CLI specified, try that first\n const preferred = await tryPreferredCli(config, logger, cache);\n if (preferred !== null) return preferred;\n\n // #6604: in gateway mode a pinned slot with no CLI is served by its\n // family's gateway model, or is unavailable — never another CLI's family.\n const gatewaySlot = tryGatewaySlot(config, logger);\n if (gatewaySlot !== undefined) return gatewaySlot;\n\n // Otherwise, get all available CLIs and use the first one found\n const availableClis = await getAvailableClis(cache);\n\n if (availableClis.length === 0) {\n logger.info('No CLI adapters available');\n return null;\n }\n\n // Use first available CLI - each CLI handles its own model selection\n const selectedCli = availableClis[0];\n\n if (selectedCli === undefined) {\n return null;\n }\n\n logger.info('Auto-selected CLI', { cli: selectedCli, available: availableClis });\n const cliAdapter = createCliAdapter({ cli: selectedCli, logger });\n await cliAdapter.initialize();\n\n return {\n adapter: createCliToModelAdapter(cliAdapter, bridgeConfig),\n source: 'cli',\n name: selectedCli,\n reason: `Using '${selectedCli}' CLI (model selection handled by CLI)`,\n cache,\n };\n}\n\n/** The pinned CLI's own adapter when it is enabled and available, else null. */\nasync function tryPreferredCli(\n config: AutoAdapterConfig,\n logger: ILogger,\n cache?: ICliDetectionCache\n): Promise<AdapterSelection | null> {\n const preferredCli = config.preferredCli;\n if (\n preferredCli === undefined ||\n isCliDisabled(preferredCli) ||\n !(await isCliAvailable(preferredCli, cache))\n ) {\n return null;\n }\n logger.info('Using preferred CLI', { cli: preferredCli });\n const cliAdapter = createCliAdapter({ cli: preferredCli, logger });\n await cliAdapter.initialize();\n return {\n adapter: createCliToModelAdapter(cliAdapter, cliBridgeConfig(config)),\n source: 'cli',\n name: preferredCli,\n reason: `Preferred CLI '${preferredCli}' is available (model selection handled by CLI)`,\n cache,\n };\n}\n\n/**\n * The gateway selection for a pinned slot whose CLI is not available (#6604).\n * A CLI disabled by `NEXUS_DISABLED_CLIS` counts as not available (#6720:\n * the variable is transport-scoped), so its family's gateway model serves\n * the slot. `undefined` keeps the pre-#6604 path: no pinned slot, or no\n * gateway catalogue. A slot whose family the gateway does not serve is served\n * by a direct API key of the SAME family when one is set (#6604 review, item\n * 4: before the gateway existed that key served it) — unless its CLI is\n * disabled, which never falls back to an API key (#6720); otherwise it THROWS, so\n * the resilient adapter reports it unavailable instead of substituting the\n * first installed CLI, another family's key or `NEXUS_CUSTOM_MODEL`.\n */\nfunction tryGatewaySlot(config: AutoAdapterConfig, logger: ILogger): AdapterSelection | undefined {\n const preferredCli = config.preferredCli;\n if (preferredCli === undefined) return undefined;\n if (preferredCli === 'opencode' && hasGatewaySlotCatalog()) {\n // #6626: opencode is multi-vendor, not a family. Serving it with the\n // gateway default would record the default's outcomes under the opencode\n // slot, and its registry ids (`opencode-custom-opus`) are not gateway ids.\n throw new Error(\n \"The 'opencode' slot is unavailable: its CLI is not available, and in gateway mode it is not substituted (opencode has no model family; the unpinned default serves any-model requests)\"\n );\n }\n const slot = resolveGatewaySlot(preferredCli, process.env, logger);\n if (slot.kind === 'inactive') return undefined;\n if (slot.kind === 'unavailable') {\n // #6720 review: a DISABLED CLI's slot is served by the gateway family model\n // only. A same-family API key would be new API spend the operator did not\n // ask for, and doctor and the fallback chain both call this slot unavailable.\n if (isCliDisabled(preferredCli)) {\n throw new Error(\n `The '${preferredCli}' slot is unavailable: its CLI is disabled by NEXUS_DISABLED_CLIS and the gateway serves no ${slot.family} model`\n );\n }\n const sameFamily = buildApiSelectionForVendor(slot.family, logger, config);\n if (sameFamily !== null) {\n return sameFamily;\n }\n throw new Error(\n `The '${preferredCli}' slot is unavailable: its CLI is not available, the gateway serves no ${slot.family} model, and no ${slot.family} API key is set`\n );\n }\n const modelId = slot.adapter.modelId;\n logger.info('Using gateway family model for CLI slot', { cli: preferredCli, model: modelId });\n return {\n adapter: createGatewaySlotAdapter(preferredCli, slot.adapter),\n source: 'api',\n name: preferredCli,\n reason: `CLI '${preferredCli}' is not available; gateway ${slot.family} model '${modelId}' serves the slot (${slot.via})`,\n modelVerified: true,\n };\n}\n\n/**\n * Resolves an API key from config or environment variable.\n */\nfunction resolveApiKeyFromEnv(configKey: string | undefined, envVar: string): string | undefined {\n const key = configKey ?? process.env[envVar];\n return key !== undefined && key.length > 0 ? key : undefined;\n}\n\n/**\n * Attempts to create an API-based model adapter.\n * Tries providers in order: Anthropic (native), OpenAI (SDK), Google (SDK).\n * This is a fallback when no CLIs are available.\n */\nfunction tryApiAdapter(config: AutoAdapterConfig, logger: ILogger): AdapterSelection | null {\n // Derive default model IDs from canonical registry instead of hardcoding\n const claudeModelId = getCliModelName(getDefaultModelForCli('claude'));\n const codexModelId = getCliModelName(getDefaultModelForCli('codex'));\n const geminiModelId = getCliModelName(getDefaultModelForCli('gemini'));\n\n // 1. Anthropic — use native ClaudeAdapter (battle-tested)\n const anthropicKey = resolveApiKeyFromEnv(config.anthropicApiKey, 'ANTHROPIC_API_KEY');\n if (anthropicKey !== undefined) {\n logger.info('Using Anthropic API adapter', { model: claudeModelId });\n return {\n adapter: createClaudeAdapter({ modelId: claudeModelId, apiKey: anthropicKey }),\n source: 'api',\n name: 'anthropic',\n reason: `Using Anthropic API (native adapter, model: ${claudeModelId})`,\n };\n }\n\n // 2. OpenAI — use AI SDK adapter\n const openaiKey = resolveApiKeyFromEnv(config.openaiApiKey, 'OPENAI_API_KEY');\n if (openaiKey !== undefined) {\n logger.info('Using OpenAI API adapter (AI SDK)', { model: codexModelId });\n return {\n adapter: new SdkAdapter({ providerId: 'openai', modelId: codexModelId, apiKey: openaiKey }),\n source: 'api',\n name: 'openai',\n reason: `Using OpenAI API via AI SDK (model: ${codexModelId})`,\n };\n }\n\n // 3. Google — use AI SDK adapter\n const googleKey = resolveApiKeyFromEnv(config.googleApiKey, 'GOOGLE_AI_API_KEY');\n if (googleKey !== undefined) {\n logger.info('Using Google AI API adapter (AI SDK)', { model: geminiModelId });\n return {\n adapter: new SdkAdapter({\n providerId: 'google',\n modelId: geminiModelId,\n apiKey: googleKey,\n }),\n source: 'api',\n name: 'google',\n reason: `Using Google AI API via AI SDK (model: ${geminiModelId})`,\n };\n }\n\n // 4. Custom OpenAI-compatible gateway (multi-vendor proxies, self-hosted\n // LLM servers, corporate gateways). Extracted for line limit.\n const custom = tryCustomOpenAiAdapter(logger);\n if (custom !== null) return custom;\n\n logger.info('No API keys available for any provider');\n return null;\n}\n\n/**\n * Resolve an API-vendor name to its `{vendor, slot}` pair (#3422). `slot` is the\n * *attribution* CLI slot (`getModelInfo`, capability profile) — NOT the routing\n * arm id, which stays distinct (`api:<vendor>`) so CLI and API telemetry never\n * merge. Exhaustive switch (concrete literals, no index-access undefined).\n */\nfunction resolveApiVendor(name: string): { vendor: ApiVendor; slot: CliName } | undefined {\n switch (name) {\n case 'anthropic':\n return { vendor: 'anthropic', slot: 'claude' };\n case 'openai':\n return { vendor: 'openai', slot: 'codex' };\n case 'google':\n return { vendor: 'google', slot: 'gemini' };\n case 'custom-openai':\n return { vendor: 'custom-openai', slot: 'opencode' };\n default:\n return undefined;\n }\n}\n\n/**\n * Wrap an `AdapterSelection{source:'api'}` for insertion into a CompositeRouter's\n * `Map<RoutingArmId, ICliAdapter>` (#3317 step 1 / #3422). Returns the distinct\n * routing arm id (`api:<vendor>`) and an `ICliAdapter` view of the IModelAdapter\n * (via {@link createModelToCliAdapter}). Returns null for CLI selections (the\n * router already gets those from `createAllAdapters` under their slot key) or an\n * unrecognized vendor.\n */\nexport function wrapApiSelectionForRouter(\n selection: AdapterSelection\n): { armId: ApiArmId; adapter: ICliAdapter } | null {\n if (selection.source !== 'api') return null;\n const resolved = resolveApiVendor(selection.name);\n if (resolved === undefined) return null;\n const adapter = createModelToCliAdapter(selection.adapter, {\n name: resolved.slot,\n capabilities: buildCliCapabilityProfiles()[resolved.slot],\n });\n return { armId: apiArmId(resolved.vendor), adapter };\n}\n\n/**\n * Build an `AdapterSelection{source:'api'}` for a single vendor when its key(s)\n * are present, else null. Reuses the same adapter constructors as\n * {@link tryApiAdapter} but is key-presence-only and never calls out (#3422).\n */\nfunction buildApiSelectionForVendor(\n vendor: ApiVendor,\n logger: ILogger,\n config: AutoAdapterConfig = {}\n): AdapterSelection | null {\n switch (vendor) {\n case 'anthropic': {\n const key = resolveApiKeyFromEnv(config.anthropicApiKey, 'ANTHROPIC_API_KEY');\n if (key === undefined) return null;\n const modelId = getCliModelName(getDefaultModelForCli('claude'));\n return {\n adapter: createClaudeAdapter({ modelId, apiKey: key }),\n source: 'api',\n name: 'anthropic',\n reason: `Using Anthropic API (native adapter, model: ${modelId})`,\n };\n }\n case 'openai': {\n const key = resolveApiKeyFromEnv(config.openaiApiKey, 'OPENAI_API_KEY');\n if (key === undefined) return null;\n const modelId = getCliModelName(getDefaultModelForCli('codex'));\n return {\n adapter: new SdkAdapter({ providerId: 'openai', modelId, apiKey: key }),\n source: 'api',\n name: 'openai',\n reason: `Using OpenAI API via AI SDK (model: ${modelId})`,\n };\n }\n case 'google': {\n const key = resolveApiKeyFromEnv(config.googleApiKey, 'GOOGLE_AI_API_KEY');\n if (key === undefined) return null;\n const modelId = getCliModelName(getDefaultModelForCli('gemini'));\n return {\n adapter: new SdkAdapter({ providerId: 'google', modelId, apiKey: key }),\n source: 'api',\n name: 'google',\n reason: `Using Google AI API via AI SDK (model: ${modelId})`,\n };\n }\n case 'custom-openai':\n return tryCustomOpenAiAdapter(logger);\n default: {\n const exhaustive: never = vendor;\n throw new Error(`Unknown API vendor: ${String(exhaustive)}`);\n }\n }\n}\n\n/** API vendors enumerated in routing-arm order (#3422). */\nconst API_ROUTING_VENDORS: readonly ApiVendor[] = [\n 'anthropic',\n 'openai',\n 'google',\n 'custom-openai',\n];\n\n/**\n * Enumerate the direct-API routing arms whose keys are present in the\n * environment, each wrapped as an `ICliAdapter` keyed by its distinct\n * `api:<vendor>` arm id (#3422). Key-presence-only and deterministic: a vendor\n * is included iff its required env var(s) are set; keys are never validated by\n * calling out. Used by `createAllAdapters` under `NEXUS_BILLING_MODE=api`.\n */\nexport function collectApiRoutingArms(\n logger: ILogger = defaultLogger\n): Array<{ armId: ApiArmId; adapter: ICliAdapter }> {\n const arms: Array<{ armId: ApiArmId; adapter: ICliAdapter }> = [];\n for (const vendor of API_ROUTING_VENDORS) {\n const selection = buildApiSelectionForVendor(vendor, logger);\n if (selection === null) continue;\n const wrapped = wrapApiSelectionForRouter(selection);\n if (wrapped === null) continue;\n arms.push(wrapped);\n // Only the custom-openai (gateway) arm can be undeclared; the helper is\n // silent for the three vendor arms (#4392 increment 2).\n warnIfGatewayCostUndeclared(wrapped.armId, logger);\n }\n return arms;\n}\n\n/** Try CLI first, then API as fallback. */\nasync function selectCliFirst(\n config: AutoAdapterConfig,\n logger: ILogger,\n cache?: ICliDetectionCache\n): Promise<AdapterSelection> {\n const cliResult = await tryCliAdapter(config, logger, cache);\n if (cliResult !== null) return cliResult;\n const apiResult = tryApiAdapter(config, logger);\n if (apiResult !== null) return apiResult;\n throw new Error(\n 'No adapters available. Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY.'\n );\n}\n\n/** Try API first, then CLI as fallback. */\nasync function selectApiFirst(\n config: AutoAdapterConfig,\n logger: ILogger,\n cache?: ICliDetectionCache\n): Promise<AdapterSelection> {\n const apiResult = tryApiAdapter(config, logger);\n if (apiResult !== null) return apiResult;\n const cliResult = await tryCliAdapter(config, logger, cache);\n if (cliResult !== null) return cliResult;\n throw new Error(\n 'No adapters available. Set ANTHROPIC_API_KEY/OPENAI_API_KEY/GOOGLE_AI_API_KEY or install a CLI (claude/gemini/codex).'\n );\n}\n\n/** CLI only - no API fallback. */\nasync function selectCliOnly(\n config: AutoAdapterConfig,\n logger: ILogger,\n cache?: ICliDetectionCache\n): Promise<AdapterSelection> {\n const cliResult = await tryCliAdapter(config, logger, cache);\n if (cliResult !== null) return cliResult;\n throw new Error(\n 'No CLI adapters available. Install and authenticate claude, gemini, or codex CLI.'\n );\n}\n\n/** API only - no CLI fallback. */\nfunction selectApiOnly(config: AutoAdapterConfig, logger: ILogger): AdapterSelection {\n const apiResult = tryApiAdapter(config, logger);\n if (apiResult !== null) return apiResult;\n throw new Error(\n 'No API key available. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY.'\n );\n}\n\n/**\n * Auto-selects the best available model adapter.\n * Uses caching to avoid repeated CLI health checks.\n *\n * @param config - Configuration options\n * @returns Selected adapter or throws if none available\n *\n * @example\n * ```typescript\n * // Use CLI if available, fall back to API\n * const { adapter, source, reason, cache } = await createAutoAdapter();\n * console.log(`Using ${source} adapter: ${reason}`);\n *\n * // Reuse cache for subsequent selections\n * const { adapter: adapter2 } = await createAutoAdapter({ cache });\n *\n * // Force CLI only\n * const { adapter } = await createAutoAdapter({ priority: 'cli-only' });\n * ```\n */\nexport async function createAutoAdapter(config: AutoAdapterConfig = {}): Promise<AdapterSelection> {\n const logger = config.logger ?? defaultLogger;\n const priority = config.priority ?? 'cli-first';\n const cache = resolveCache(config, logger);\n // #4392: outside the MCP server nothing else discovers the gateway, so the\n // first selection does (once per process); the family slots and the\n // custom-openai model below then read the same catalogue the server does.\n await ensureGatewayDiscovered();\n\n logger.info('Auto-selecting adapter', { priority, cacheEnabled: cache !== undefined });\n\n switch (priority) {\n case 'cli-first':\n return selectCliFirst(config, logger, cache);\n case 'api-first':\n return selectApiFirst(config, logger, cache);\n case 'cli-only':\n return selectCliOnly(config, logger, cache);\n case 'api-only':\n return selectApiOnly(config, logger);\n default: {\n const exhaustive: never = priority;\n throw new Error(`Unknown priority: ${String(exhaustive)}`);\n }\n }\n}\n","/**\n * Event Bus Helper Functions\n *\n * Pure utility functions for event bus operations.\n * Extracted from event-bus.ts to maintain file size limits.\n *\n * @module agents/collaboration/event-bus-helpers\n * (Source: Issue #182, ARCHITECTURE.md Hybrid Architecture)\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { getTimeProvider } from '../../core/index.js';\nimport type { SubscriptionId, TopicPattern, DomainEvent, EventFilter } from './event-bus-types.js';\n\n/** Default maximum history size */\nexport const DEFAULT_MAX_HISTORY_SIZE = 1000;\n\n/** Maximum number of subscriptions per bus */\nexport const MAX_SUBSCRIPTIONS = 500;\n\n/**\n * Internal subscription record.\n */\nexport interface SubscriptionRecord {\n readonly id: SubscriptionId;\n readonly pattern: TopicPattern;\n readonly regex: RegExp;\n readonly listener: (event: DomainEvent) => void | Promise<void>;\n}\n\n/** Maximum allowed topic pattern length */\nconst MAX_TOPIC_PATTERN_LENGTH = 200;\n\n/**\n * Convert a topic pattern to a regex for matching.\n * Supports wildcard patterns:\n * - 'session.created' -> exact match\n * - 'session.*' -> matches session.anything\n * - '*' -> matches everything\n *\n * Security Note (Issue #341): This function is safe from ReDoS because:\n * 1. The input is fully escaped before regex construction\n * 2. Only `*` wildcards are converted to `[^.]+` (bounded, non-greedy)\n * 3. Pattern length is bounded to prevent memory issues\n *\n * @throws Error if pattern exceeds MAX_TOPIC_PATTERN_LENGTH\n */\nexport function patternToRegex(pattern: TopicPattern): RegExp {\n // Validate length to prevent memory issues (Issue #341)\n if (pattern.length > MAX_TOPIC_PATTERN_LENGTH) {\n throw new Error(`Topic pattern exceeds maximum length of ${String(MAX_TOPIC_PATTERN_LENGTH)}`);\n }\n\n if (pattern === '*') {\n return /^.+$/;\n }\n // Use placeholder for * before escaping, then restore as regex wildcard\n // WILDCARD_PLACEHOLDER is a static constant, safe for RegExp (Issue #341)\n const WILDCARD_PLACEHOLDER = '\\x00WILDCARD\\x00';\n const withPlaceholder = pattern.replace(/\\*/g, WILDCARD_PLACEHOLDER);\n // Escape all regex special characters - this makes the pattern safe\n const escaped = withPlaceholder.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n // Replace placeholder with bounded wildcard - safe since input was escaped\n const withWildcards = escaped.replace(new RegExp(WILDCARD_PLACEHOLDER, 'g'), '[^.]+');\n return new RegExp(`^${withWildcards}$`);\n}\n\n/**\n * Check if a topic matches a pattern.\n */\nexport function topicMatchesPattern(topic: string, regex: RegExp): boolean {\n return regex.test(topic);\n}\n\n/**\n * Generate a unique event ID.\n */\nexport function generateEventId(): string {\n return `evt-${String(getTimeProvider().now())}-${randomUUID().slice(0, 8)}`;\n}\n\n/**\n * Generate a unique subscription ID.\n */\nexport function generateSubscriptionId(): SubscriptionId {\n return `sub-${String(getTimeProvider().now())}-${randomUUID().slice(0, 8)}`;\n}\n\n/**\n * Generate a unique correlation ID for request tracing.\n * (Source: Issue #224, Sprint #228)\n *\n * @example\n * ```typescript\n * const correlationId = generateCorrelationId();\n * // -> 'cor_a1b2c3d4'\n * ```\n */\nexport function generateCorrelationId(): string {\n return `cor_${randomUUID().slice(0, 8)}`;\n}\n\n/**\n * Create a child correlation ID that chains to a parent.\n * Enables hierarchical tracing of subtasks.\n * (Source: Issue #224, Sprint #228)\n *\n * @param parentCorrelationId - The parent correlation ID to chain from\n * @returns A new correlation ID in format 'parentId.child_xxxxxxxx'\n *\n * @example\n * ```typescript\n * const parentId = generateCorrelationId();\n * // -> 'cor_a1b2c3d4'\n *\n * const childId = createChildCorrelationId(parentId);\n * // -> 'cor_a1b2c3d4.child_e5f6g7h8'\n * ```\n */\nexport function createChildCorrelationId(parentCorrelationId: string): string {\n return `${parentCorrelationId}.child_${randomUUID().slice(0, 8)}`;\n}\n\n/**\n * Apply topic, session, correlation, and timestamp filters to events.\n */\nexport function applyHistoryFilters(history: DomainEvent[], filter: EventFilter): DomainEvent[] {\n let result: DomainEvent[] = history;\n\n if (filter.topic !== undefined && filter.topic !== '') {\n const regex = patternToRegex(filter.topic);\n result = result.filter((e) => topicMatchesPattern(e.topic, regex));\n }\n\n if (filter.sessionId !== undefined && filter.sessionId !== '') {\n result = result.filter((e) => e.sessionId === filter.sessionId);\n }\n\n if (filter.correlationId !== undefined && filter.correlationId !== '') {\n result = result.filter((e) => e.correlationId === filter.correlationId);\n }\n\n return applyTimestampFilters(result, filter);\n}\n\n/**\n * Apply timestamp-based filters to events.\n */\nexport function applyTimestampFilters(result: DomainEvent[], filter: EventFilter): DomainEvent[] {\n let filtered = result;\n\n if (filter.after !== undefined && filter.after !== '') {\n const afterTimestamp = filter.after;\n filtered = filtered.filter((e) => e.timestamp > afterTimestamp);\n }\n\n if (filter.before !== undefined && filter.before !== '') {\n const beforeTimestamp = filter.before;\n filtered = filtered.filter((e) => e.timestamp < beforeTimestamp);\n }\n\n return filtered;\n}\n\n/**\n * Apply limit to history results.\n */\nexport function applyHistoryLimit(result: DomainEvent[], filter: EventFilter): DomainEvent[] {\n if (filter.limit !== undefined && filter.limit > 0) {\n return result.slice(-filter.limit);\n }\n return result;\n}\n\n/**\n * Enrich event with generated fields if missing.\n */\nexport function enrichEvent(event: DomainEvent): DomainEvent {\n return {\n ...event,\n eventId: event.eventId || generateEventId(),\n timestamp: event.timestamp || getTimeProvider().nowIso(),\n };\n}\n\n/**\n * Count subscribers matching a topic from a subscription map.\n */\nexport function countMatchingSubscribers(\n topic: string,\n subscriptions: Map<SubscriptionId, SubscriptionRecord>\n): number {\n let count = 0;\n for (const record of subscriptions.values()) {\n if (topicMatchesPattern(topic, record.regex)) {\n count++;\n }\n }\n return count;\n}\n","/**\n * Event Bus Implementation\n *\n * Async message passing for agent-to-agent communication.\n * Supports topic-based routing, wildcard patterns, and event history.\n *\n * @module agents/collaboration/event-bus\n * (Source: Issue #182, ARCHITECTURE.md Hybrid Architecture)\n */\n\nimport { getTimeProvider } from '../../core/index.js';\nimport type {\n ICollaborationEventBus,\n DomainEvent,\n EventListener,\n Subscription,\n SubscriptionId,\n TopicPattern,\n EventFilter,\n EventBusOptions,\n EventBusStats,\n} from './event-bus-types.js';\n\nimport {\n DEFAULT_MAX_HISTORY_SIZE,\n MAX_SUBSCRIPTIONS,\n type SubscriptionRecord,\n patternToRegex,\n topicMatchesPattern,\n generateEventId,\n generateSubscriptionId,\n applyHistoryFilters,\n applyHistoryLimit,\n enrichEvent,\n countMatchingSubscribers,\n} from './event-bus-helpers.js';\n\nimport { CircularBuffer } from '../../core/circular-buffer.js';\n\n// Re-export correlation ID helpers for public API\nexport { generateCorrelationId, createChildCorrelationId } from './event-bus-helpers.js';\n\n/**\n * Event Bus for agent-to-agent communication.\n *\n * Features:\n * - Topic-based pub/sub with wildcard support\n * - Async and sync event emission\n * - Event history with filtering\n * - Error isolation (one listener failure doesn't block others)\n *\n * @example\n * ```typescript\n * const bus = new CollaborationEventBus();\n *\n * // Subscribe to all session events\n * const sub = bus.subscribe('session.*', (event) => {\n * console.log('Session event:', event.topic);\n * });\n *\n * // Emit an event\n * bus.emit(createSessionCreatedEvent({ sessionId: '123', ... }));\n *\n * // Cleanup\n * sub.unsubscribe();\n * ```\n */\nexport class CollaborationEventBus implements ICollaborationEventBus {\n private readonly subscriptions: Map<SubscriptionId, SubscriptionRecord> = new Map();\n private readonly history: CircularBuffer<DomainEvent>;\n private readonly asyncHandling: boolean;\n private readonly logger?: EventBusOptions['logger'];\n\n private stats: EventBusStats = {\n eventsEmitted: 0,\n subscriptionsCreated: 0,\n activeSubscriptions: 0,\n historySize: 0,\n errorCount: 0,\n };\n\n constructor(options: EventBusOptions = {}) {\n const maxHistorySize = options.maxHistorySize ?? DEFAULT_MAX_HISTORY_SIZE;\n this.history = new CircularBuffer<DomainEvent>(maxHistorySize);\n this.asyncHandling = options.asyncHandling ?? false;\n this.logger = options.logger;\n }\n\n /**\n * Emit an event synchronously to all matching subscribers.\n */\n emit(event: DomainEvent): void {\n const enrichedEvent = enrichEvent(event);\n this.addToHistory(enrichedEvent);\n this.stats.eventsEmitted++;\n\n this.logger?.debug('Event emitted', {\n topic: enrichedEvent.topic,\n eventId: enrichedEvent.eventId,\n subscriberCount: countMatchingSubscribers(enrichedEvent.topic, this.subscriptions),\n });\n\n for (const record of this.subscriptions.values()) {\n if (topicMatchesPattern(enrichedEvent.topic, record.regex)) {\n this.invokeListener(record, enrichedEvent);\n }\n }\n }\n\n /**\n * Emit an event and wait for all async handlers to complete.\n */\n async emitAsync(event: DomainEvent): Promise<void> {\n const enrichedEvent = enrichEvent(event);\n this.addToHistory(enrichedEvent);\n this.stats.eventsEmitted++;\n\n this.logger?.debug('Async event emitted', {\n topic: enrichedEvent.topic,\n eventId: enrichedEvent.eventId,\n });\n\n const promises: Promise<void>[] = [];\n\n for (const record of this.subscriptions.values()) {\n if (topicMatchesPattern(enrichedEvent.topic, record.regex)) {\n promises.push(this.invokeListenerAsync(record, enrichedEvent));\n }\n }\n\n await Promise.all(promises);\n }\n\n /**\n * Subscribe to events matching a topic pattern.\n */\n subscribe<T extends DomainEvent = DomainEvent>(\n pattern: TopicPattern,\n listener: EventListener<T>\n ): Subscription {\n if (this.subscriptions.size >= MAX_SUBSCRIPTIONS) {\n throw new Error(\n `Maximum subscription limit reached (${String(MAX_SUBSCRIPTIONS)}). ` +\n 'Unsubscribe from unused patterns before adding new ones.'\n );\n }\n\n const id = generateSubscriptionId();\n const regex = patternToRegex(pattern);\n\n const record: SubscriptionRecord = {\n id,\n pattern,\n regex,\n listener: listener as EventListener,\n };\n\n this.subscriptions.set(id, record);\n this.stats.subscriptionsCreated++;\n this.stats.activeSubscriptions = this.subscriptions.size;\n\n this.logger?.debug('Subscription created', { id, pattern });\n\n return {\n id,\n pattern,\n unsubscribe: () => {\n this.unsubscribe(id);\n },\n };\n }\n\n /**\n * Unsubscribe from events.\n */\n unsubscribe(subscriptionId: SubscriptionId): void {\n const existed = this.subscriptions.delete(subscriptionId);\n if (existed) {\n this.stats.activeSubscriptions = this.subscriptions.size;\n this.logger?.debug('Subscription removed', { subscriptionId });\n }\n }\n\n /**\n * Get event history matching filter criteria.\n */\n getHistory(filter?: EventFilter): readonly DomainEvent[] {\n const historyArray = this.history.toArray();\n if (filter === undefined) {\n return historyArray;\n }\n\n const filtered = applyHistoryFilters(historyArray, filter);\n return applyHistoryLimit(filtered, filter);\n }\n\n /**\n * Clear event history.\n */\n clearHistory(): void {\n this.history.clear();\n this.stats.historySize = 0;\n this.logger?.debug('History cleared');\n }\n\n /**\n * Get event bus statistics.\n */\n getStats(): EventBusStats {\n return { ...this.stats };\n }\n\n /**\n * Check if a topic pattern has any subscribers.\n */\n hasSubscribers(pattern: TopicPattern): boolean {\n const regex = patternToRegex(pattern);\n for (const record of this.subscriptions.values()) {\n // Check if the patterns could overlap\n if (\n topicMatchesPattern(pattern, record.regex) ||\n topicMatchesPattern(record.pattern, regex)\n ) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Add event to history, maintaining size limit via O(1) circular buffer.\n * @see Issue #407 - Performance optimization\n */\n private addToHistory(event: DomainEvent): void {\n this.history.push(event);\n this.stats.historySize = this.history.size;\n }\n\n /**\n * Invoke a listener synchronously with error isolation.\n */\n private invokeListener(record: SubscriptionRecord, event: DomainEvent): void {\n try {\n const result = record.listener(event);\n // If async handling is enabled and listener returns a promise, don't wait\n if (this.asyncHandling && result instanceof Promise) {\n result.catch((error: unknown) => {\n this.handleListenerError(record, event, error);\n });\n }\n } catch (error) {\n this.handleListenerError(record, event, error);\n }\n }\n\n /**\n * Invoke a listener asynchronously.\n */\n private async invokeListenerAsync(record: SubscriptionRecord, event: DomainEvent): Promise<void> {\n try {\n await record.listener(event);\n } catch (error) {\n this.handleListenerError(record, event, error);\n }\n }\n\n /**\n * Handle listener errors without disrupting other listeners.\n */\n private handleListenerError(\n record: SubscriptionRecord,\n event: DomainEvent,\n error: unknown\n ): void {\n this.stats.errorCount++;\n const errorObj = error instanceof Error ? error : new Error(String(error));\n this.logger?.error('Event listener error', errorObj, {\n subscriptionId: record.id,\n pattern: record.pattern,\n eventTopic: event.topic,\n eventId: event.eventId,\n });\n }\n}\n\n/**\n * Create a singleton event bus instance for global coordination.\n * Use with caution - prefer dependency injection for testability.\n */\nlet globalBus: CollaborationEventBus | null = null;\n\nexport function getGlobalEventBus(options?: EventBusOptions): CollaborationEventBus {\n globalBus ??= new CollaborationEventBus(options);\n return globalBus;\n}\n\n/**\n * Reset the global event bus (for testing).\n */\nexport function resetGlobalEventBus(): void {\n globalBus = null;\n}\n\n/**\n * Factory functions for creating typed events.\n */\nexport function createEvent<T extends DomainEvent>(\n topic: T['topic'],\n payload: T['payload'],\n options?: {\n sessionId?: string;\n correlationId?: string;\n }\n): T {\n return {\n eventId: generateEventId(),\n timestamp: getTimeProvider().nowIso(),\n topic,\n payload,\n sessionId: options?.sessionId,\n correlationId: options?.correlationId,\n } as T;\n}\n","/**\n * Event Bus Topic Constants\n *\n * Type-safe topic constants for event subscription.\n *\n * @module agents/collaboration/event-bus-topics\n * (Source: Issue #182, ARCHITECTURE.md Hybrid Architecture)\n */\n\n/**\n * Topic constants for type-safe subscription.\n */\nexport const EventTopics = {\n // Session events\n SESSION_CREATED: 'session.created',\n SESSION_STATUS_CHANGED: 'session.status_changed',\n SESSION_PARTICIPANT_JOINED: 'session.participant_joined',\n SESSION_RESULT_SUBMITTED: 'session.result_submitted',\n SESSION_FINALIZED: 'session.finalized',\n SESSION_ALL: 'session.*',\n\n // Message events\n MESSAGE_SENT: 'message.sent',\n MESSAGE_RECEIVED: 'message.received',\n MESSAGE_ALL: 'message.*',\n\n // Agent events\n AGENT_TASK_DELEGATED: 'agent.task_delegated',\n AGENT_RESULT_BROADCAST: 'agent.result_broadcast',\n AGENT_ALL: 'agent.*',\n\n // Consensus events\n CONSENSUS_VOTE_REQUESTED: 'consensus.vote_requested',\n CONSENSUS_VOTE_CAST: 'consensus.vote_cast',\n CONSENSUS_REACHED: 'consensus.reached',\n CONSENSUS_ALL: 'consensus.*',\n\n // Protocol events\n PROTOCOL_STARTED: 'protocol.started',\n PROTOCOL_ITERATION: 'protocol.iteration',\n PROTOCOL_COMPLETED: 'protocol.completed',\n PROTOCOL_ALL: 'protocol.*',\n\n // Aegean phase events (Issue #216)\n AEGEAN_ROUND_STARTED: 'protocol.aegean.round_started',\n AEGEAN_VOTE_COLLECTED: 'protocol.aegean.vote_collected',\n AEGEAN_QUORUM_DETECTED: 'protocol.aegean.quorum_detected',\n AEGEAN_ALL: 'protocol.aegean.*',\n\n // Reflexion phase events (Issue #216)\n REFLEXION_CRITIQUE_STARTED: 'protocol.reflexion.critique_started',\n REFLEXION_CRITIQUE_COMPLETED: 'protocol.reflexion.critique_completed',\n REFLEXION_SYNTHESIS: 'protocol.reflexion.synthesis',\n REFLEXION_ALL: 'protocol.reflexion.*',\n\n // Trinity phase events (Issue #216)\n TRINITY_PHASE_STARTED: 'protocol.trinity.phase_started',\n TRINITY_PHASE_COMPLETED: 'protocol.trinity.phase_completed',\n TRINITY_ALL: 'protocol.trinity.*',\n\n // Byzantine detection events (Issue #218)\n BYZANTINE_WEIGHT_UPDATED: 'byzantine.weight_updated',\n BYZANTINE_PATTERN_DETECTED: 'byzantine.pattern_detected',\n BYZANTINE_AGENT_FLAGGED: 'byzantine.agent_flagged',\n BYZANTINE_COLLUSION_SUSPECTED: 'byzantine.collusion_suspected',\n BYZANTINE_ALL: 'byzantine.*',\n\n // Wildcard\n ALL: '*',\n} as const;\n","/**\n * Resilient Model Adapter\n *\n * Transparent proxy implementing IModelAdapter with lazy detection,\n * automatic failover on circuit breaker events, and observable health.\n *\n * Key design: ResilientAdapter IS an IModelAdapter. Every existing consumer\n * works unchanged. The health/failover API lives on IResilientAdapter for\n * dashboard and monitoring consumers only.\n *\n * @module adapters/resilient-adapter\n * (Source: Issue #811 - Resilient model adapter architecture)\n */\n\nimport type {\n IModelAdapter,\n CompletionRequest,\n CompletionResponse,\n StreamChunk,\n ModelCapability,\n} from '../core/types/model.js';\nimport type { Result } from '../core/result.js';\nimport { ok, err } from '../core/result.js';\nimport { ModelError, ConfigError } from '../core/errors.js';\nimport type { ILogger } from '../core/index.js';\nimport { getTimeProvider, getRandomProvider } from '../core/index.js';\nimport { getErrorMessage, createLogger } from '../core/index.js';\nimport { UNRESOLVED_MODEL_ID } from '../config/model-equivalence.js';\n\nimport { createAutoAdapter, type AdapterSelection } from './auto-adapter.js';\nimport { isCallerCancelled } from './abort-utils.js';\nimport { ensureGatewayDiscovered, gatewayDiscoveryGeneration } from './gateway-rediscovery.js';\nimport {\n isRateLimitLikeError,\n isDurableCapacityError,\n toRateLimitError,\n recordRateLimitEvent,\n} from './rate-limit-detector.js';\nimport type { CliName, EndpointArmId } from '../cli-adapters/types.js';\nimport { isEndpointArmId } from '../cli-adapters/types.js';\nimport type {\n IResilientAdapter,\n AdapterHealthInfo,\n ResilientAdapterConfig,\n} from './resilient-adapter-types.js';\nimport type { CircuitStateChangeEvent } from '../cli-adapters/circuit-breaker-types.js';\nimport type { CircuitBreakerRegistry } from '../cli-adapters/circuit-breaker.js';\nimport { mapModelErrorToCategory } from '../cli-adapters/circuit-breaker.js';\nimport { breakerKeys } from '../cli-adapters/breaker-key.js';\nimport { getGlobalEventBus } from '../core/event-bus.js';\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Creates a resilient adapter with lazy detection and automatic failover.\n *\n * @example\n * ```typescript\n * const adapter = createResilientAdapter({ logger });\n * // No detection at creation time — detection happens on first use\n * const result = await adapter.complete(request); // triggers detection\n * ```\n */\nexport function createResilientAdapter(config?: ResilientAdapterConfig): IResilientAdapter {\n return new ResilientAdapter(config);\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Resilient adapter proxy. Implements IModelAdapter transparently.\n */\nexport class ResilientAdapter implements IResilientAdapter {\n private readonly logger: ILogger;\n private currentAdapter: IModelAdapter | undefined;\n private currentSelection: AdapterSelection | undefined;\n private hasEverDetected = false;\n private health: AdapterHealthInfo | undefined;\n private preferredCli: CliName | undefined;\n private readonly failoverCallbacks = new Set<(info: AdapterHealthInfo) => void>();\n private circuitBreakerRegistry: CircuitBreakerRegistry | undefined;\n private circuitListener: ((event: CircuitStateChangeEvent) => void) | undefined;\n private disposed = false;\n private readonly defaultCliTimeoutMs: number | undefined;\n /** Inflight detection promise for coalescing concurrent calls (Issue #1423). */\n private detectionPromise: Promise<IModelAdapter | undefined> | undefined;\n /** The {@link gatewayDiscoveryGeneration} the current selection was made under (#6659). */\n private detectedAtGeneration = 0;\n\n constructor(config?: ResilientAdapterConfig) {\n this.logger = config?.logger ?? createLogger({ component: 'resilient-adapter' });\n this.preferredCli = config?.preferredCli;\n this.defaultCliTimeoutMs = config?.defaultCliTimeoutMs;\n\n // #4659: arm at construction. The previous `attach`-only API was not on\n // IResilientAdapter, so neither production construction site could reach\n // it and the breaker never fired.\n if (config?.circuitBreakerRegistry !== undefined) {\n this.attachCircuitBreakerRegistry(config.circuitBreakerRegistry);\n }\n }\n\n // --- IModelAdapter properties (forwarded) ---\n\n /**\n * Before detection a CLI-pinned proxy identifies as the CLI it was asked\n * for (`cli-<name>`, the id its detected `CliToModelAdapter` will carry);\n * an unpinned proxy stays `resilient-proxy`.\n *\n * #6119: the voter fallover (#3587) keys seats by this id and skips a seat\n * whose key equals the fallback's. When codex never detected, the pinned\n * seat and the unpinned default were BOTH `resilient-proxy`, so the seat was\n * read as \"already on the fallback\" and errored instead of falling over.\n */\n get providerId(): string {\n if (this.currentAdapter !== undefined) return this.currentAdapter.providerId;\n return this.preferredCli === undefined ? 'resilient-proxy' : `cli-${this.preferredCli}`;\n }\n\n get modelId(): string {\n return this.currentAdapter?.modelId ?? UNRESOLVED_MODEL_ID;\n }\n\n get capabilities(): readonly ModelCapability[] {\n return this.currentAdapter?.capabilities ?? [];\n }\n\n /**\n * The gateway arm of the adapter currently serving this proxy, when a\n * gateway model serves it (#6604 family slots); otherwise undefined. A\n * telemetry writer handed this proxy reads it (`isGatewayModelAdapter`) to\n * price the call by the gateway's `NEXUS_GATEWAY_COST` declaration instead\n * of a list price.\n */\n get gatewayArm(): EndpointArmId | undefined {\n const arm: unknown = (this.currentAdapter as { gatewayArm?: unknown } | undefined)?.gatewayArm;\n return typeof arm === 'string' && isEndpointArmId(arm) ? arm : undefined;\n }\n\n // --- IModelAdapter methods ---\n\n async complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>> {\n const adapter = await this.ensureAdapter();\n if (adapter === undefined) {\n return err(new ModelError('No model adapter available'));\n }\n const result = await adapter.complete(request);\n if (!result.ok) {\n if (isRateLimitLikeError(result.error)) {\n const rlError = toRateLimitError(result.error, adapter.providerId);\n recordRateLimitEvent({\n provider: adapter.providerId,\n timestamp: getTimeProvider().now(),\n retryAfterMs: rlError.retryAfterMs,\n });\n this.logger.warn('Rate limit detected', {\n provider: adapter.providerId,\n retryAfterMs: rlError.retryAfterMs,\n });\n }\n this.recordBreakerFailure(adapter, result.error);\n }\n return result;\n }\n\n async *stream(request: CompletionRequest): AsyncIterable<StreamChunk> {\n const adapter = await this.ensureAdapter();\n if (adapter === undefined) {\n // #3105: error like complete() rather than yielding an empty stream — a\n // silent-empty stream masks \"no adapter available\" as a clean empty\n // completion, so streamWithFallback can't tell failure from a\n // legitimately-empty result.\n throw new ModelError('No model adapter available');\n }\n yield* adapter.stream(request);\n }\n\n async countTokens(text: string): Promise<number> {\n const adapter = await this.ensureAdapter();\n if (adapter === undefined) {\n return 0;\n }\n return adapter.countTokens(text);\n }\n\n validateConfig(): Result<void, ConfigError> {\n if (this.currentAdapter !== undefined) {\n return this.currentAdapter.validateConfig();\n }\n // Before first use, config is trivially valid\n return ok(undefined);\n }\n\n // --- IResilientAdapter methods ---\n\n getHealth(): AdapterHealthInfo | undefined {\n return this.health;\n }\n\n async refresh(): Promise<void> {\n this.currentAdapter = undefined;\n this.currentSelection = undefined;\n this.detectionPromise = undefined;\n await this.ensureAdapter();\n }\n\n setPreferredCli(cli: CliName | undefined): void {\n this.preferredCli = cli;\n this.currentAdapter = undefined;\n this.currentSelection = undefined;\n }\n\n onFailover(cb: (info: AdapterHealthInfo) => void): () => void {\n this.failoverCallbacks.add(cb);\n return () => {\n this.failoverCallbacks.delete(cb);\n };\n }\n\n /**\n * Attach a circuit breaker registry for automatic failover.\n * When the current adapter's circuit opens, the cached adapter\n * is cleared so the next call triggers re-detection.\n */\n /** The registry arming failover, or undefined if this adapter is unarmed (#4659). */\n getCircuitBreakerRegistry(): CircuitBreakerRegistry | undefined {\n return this.circuitBreakerRegistry;\n }\n\n attachCircuitBreakerRegistry(registry: CircuitBreakerRegistry): void {\n this.detachCircuitBreakerRegistry();\n this.circuitBreakerRegistry = registry;\n this.circuitListener = (event: CircuitStateChangeEvent) => {\n this.handleCircuitStateChange(event);\n };\n registry.addGlobalStateChangeListener(this.circuitListener);\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.detachCircuitBreakerRegistry();\n this.failoverCallbacks.clear();\n }\n\n // --- Private methods ---\n\n private async ensureAdapter(): Promise<IModelAdapter | undefined> {\n // #6659: the shared acquisition seam re-discovers a gateway that was down\n // at boot (backoff-bounded, one shared attempt; a no-op unless armed).\n // Once one is found, an adapter detected before it re-detects ONCE, so the\n // default and the family slots move onto the gateway. Not a failover: the\n // adapter left behind did not fail.\n // An adapter that already serves calls never waits on discovery: it fires\n // the attempt and keeps serving, and the generation check below switches\n // it on a LATER call. Only an adapter with nothing to serve yet waits,\n // since the discovery may be what gives it something (#6671 review).\n if (this.currentAdapter === undefined) {\n await ensureGatewayDiscovered();\n } else {\n void ensureGatewayDiscovered();\n }\n if (\n this.currentAdapter !== undefined &&\n this.detectedAtGeneration !== gatewayDiscoveryGeneration()\n ) {\n this.currentAdapter = undefined;\n this.currentSelection = undefined;\n this.hasEverDetected = false;\n }\n if (this.currentAdapter !== undefined) {\n return this.currentAdapter;\n }\n // Coalesce concurrent detection calls into a single probe (Issue #1423)\n this.detectionPromise ??= this.detectAdapter().finally(() => {\n this.detectionPromise = undefined;\n });\n return this.detectionPromise;\n }\n\n private async detectAdapter(): Promise<IModelAdapter | undefined> {\n // Read BEFORE detecting: a discovery that lands mid-detection leaves this\n // selection tagged stale, so the next call re-detects instead of keeping it.\n const generation = gatewayDiscoveryGeneration();\n try {\n this.logger.info('Detecting model adapter (lazy)');\n const config = {\n logger: this.logger,\n ...(this.preferredCli !== undefined && { preferredCli: this.preferredCli }),\n ...(this.defaultCliTimeoutMs !== undefined && {\n defaultCliTimeoutMs: this.defaultCliTimeoutMs,\n }),\n };\n const selection = await createAutoAdapter(config);\n this.applySelection(selection);\n this.detectedAtGeneration = generation;\n return this.currentAdapter;\n } catch (error) {\n const message = getErrorMessage(error);\n this.logger.warn('No model adapter available', { error: message });\n this.health = {\n source: 'api',\n state: 'unavailable',\n selectedAt: new Date(),\n failoverCount: this.health?.failoverCount ?? 0,\n lastError: message,\n };\n return undefined;\n }\n }\n\n private applySelection(selection: AdapterSelection): void {\n const isFailover = this.hasEverDetected;\n // #4670: capture the OUTGOING health before it is overwritten below. The\n // failover signal is about the adapter we are leaving — `unhealthyCliFrom`\n // reads `payload.source` as \"which CLI is unhealthy\" — and that state was\n // being destroyed one statement before `emitFailover` read it.\n const outgoingHealth = this.health;\n this.currentAdapter = selection.adapter;\n this.currentSelection = selection;\n this.hasEverDetected = true;\n\n const source = mapSelectionSource(selection);\n const failoverCount = (this.health?.failoverCount ?? 0) + (isFailover ? 1 : 0);\n\n this.health = {\n source,\n state: 'healthy',\n selectedAt: new Date(),\n failoverCount,\n ...(selection.modelVerified !== undefined && { modelVerified: selection.modelVerified }),\n };\n\n this.logger.info('Adapter selected', {\n source: selection.source,\n name: selection.name,\n model: selection.adapter.modelId,\n provider: selection.adapter.providerId,\n failover: isFailover,\n });\n\n if (isFailover) {\n // The state/source describe the adapter we LEFT; `failoverCount` is a\n // run-level counter, so it carries the post-increment value.\n this.emitFailover(\n outgoingHealth === undefined ? undefined : { ...outgoingHealth, failoverCount }\n );\n }\n }\n\n /**\n * Record a direct-API failure to the circuit breaker so API adapters get the\n * same degradation/failover learning that CLI subprocess failures get (#3423).\n *\n * The shared internal key policy preserves selected CLI slots, prefixes API\n * vendor names, and isolates gateway endpoints by slot (#7070).\n *\n * A CLI selection is NOT recorded here (#6712). Its CLI adapter's retry loop\n * (`executeCliRetryLoop`) has already recorded the failure in the same\n * registry under its route key, with the category taken from\n * the CliError code. Recording it again counted every CLI failure twice (the\n * second time usually as `unknown`), so the breaker opened at about half its\n * configured threshold. Only a direct-API selection, which has no inner\n * recorder, is recorded by this layer.\n *\n * Rate-limit failures are deliberately skipped here: they are already recorded\n * by the `recordRateLimitEvent` telemetry branch in `complete()`, and the\n * breaker counts rate limits as failures by default\n * (`countRateLimitsAsFailures`), so recording them again would double-count.\n *\n * Security (#3422 constraint): the logged payload carries only `provider` and\n * `category` — never `error.message`, the request, or the ModelError object,\n * any of which could embed credentials.\n */\n private recordBreakerFailure(adapter: IModelAdapter, error: ModelError): void {\n if (this.circuitBreakerRegistry === undefined || this.currentSelection === undefined) {\n return;\n }\n // #6712: the CLI adapter's retry loop owns recording for a CLI selection.\n if (this.currentSelection.source === 'cli') return;\n\n // #6691: a call its caller cancelled (cancel_job) is not a health signal.\n if (isCallerCancelled(error)) return;\n\n const category = mapModelErrorToCategory(error);\n // Skip rate limits: already accounted for by the rate-limit telemetry branch\n // (and the breaker counts them by default). Check BOTH the mapped category\n // AND the telemetry predicate — their rate-limit pattern lists differ\n // (`isRateLimitLikeError` matches \"quota exceeded\"/\"throttl\"/… that\n // `categorizeError` does not), so a code-less MODEL_ERROR could otherwise\n // fire the telemetry branch yet fall through to a counted failure here,\n // double-counting against the threshold (#3423 review).\n // #5359: a DURABLE capacity cap is excluded from this exemption. The\n // exemption is right for a transient throttle — an ordinary panel trips a\n // per-minute limit while plenty of quota remains, and opening a breaker on\n // that would empty the candidate pool for a condition clearing within the\n // minute. It is wrong for an exhausted credential, which does not clear:\n // never counting it means the breaker never opens, so every subsequent call\n // pays the same futile retries against the same dead key.\n const breaker = this.circuitBreakerRegistry.getArmBreaker(\n breakerKeys.forArm({\n name: this.currentSelection.name,\n model: adapter.modelId,\n gatewayArm: this.gatewayArm,\n })\n );\n if (isDurableCapacityError(error)) {\n breaker.recordFailure(category);\n this.logger.warn('Durable capacity cap recorded to circuit breaker', {\n provider: adapter.providerId,\n category,\n });\n return;\n }\n\n if (category === 'rate_limit' || isRateLimitLikeError(error)) {\n return;\n }\n\n breaker.recordFailure(category);\n\n this.logger.warn('API failure recorded to circuit breaker', {\n provider: adapter.providerId,\n category,\n });\n }\n\n private handleCircuitStateChange(event: CircuitStateChangeEvent): void {\n if (event.newState !== 'open') return;\n\n const selection = this.currentSelection;\n if (\n selection === undefined ||\n breakerKeys.forArm({\n name: selection.name,\n model: this.currentAdapter?.modelId,\n gatewayArm: this.gatewayArm,\n }) !== event.armId\n ) {\n return; // Not our current adapter\n }\n\n this.logger.warn('Current adapter circuit opened, clearing cache for re-detection', {\n cli: event.cliName,\n reason: event.reason,\n });\n\n this.currentAdapter = undefined;\n this.currentSelection = undefined;\n\n if (this.health !== undefined) {\n this.health = {\n ...this.health,\n state: 'degraded',\n lastError: event.reason,\n };\n }\n }\n\n /**\n * Emit the failover signal describing the adapter we failed AWAY FROM (#4670).\n *\n * This used to read `this.health`, which `applySelection` had just replaced\n * with the incoming adapter's `state: 'healthy'`. So every `adapter.failover`\n * payload said healthy, `unhealthyCliFrom` (`observability/failover-signals.ts`)\n * returned undefined for all of them, and `signal.swarm_unhealthy` was never\n * produced by this — the more reliable of its two producers.\n *\n * An undefined outgoing health emits NOTHING rather than falling back to the\n * current one. Falling back would silently restore the old behaviour, and a\n * failover whose prior state we cannot describe is not evidence that the\n * prior adapter was healthy.\n */\n private emitFailover(outgoingHealth: AdapterHealthInfo | undefined): void {\n const info = outgoingHealth;\n if (info === undefined) return;\n\n for (const cb of this.failoverCallbacks) {\n try {\n cb(info);\n } catch (error: unknown) {\n this.logger.debug('Failover callback error', { error: getErrorMessage(error) });\n }\n }\n\n try {\n const eventBus = getGlobalEventBus();\n eventBus.emit({\n eventId: `failover-${getTimeProvider().now().toString(36)}-${getRandomProvider().random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n topic: 'adapter.failover',\n payload: info,\n });\n } catch (error: unknown) {\n this.logger.debug('CollaborationEventBus emit failed during failover', {\n error: getErrorMessage(error),\n });\n }\n }\n\n private detachCircuitBreakerRegistry(): void {\n if (this.circuitBreakerRegistry !== undefined && this.circuitListener !== undefined) {\n this.circuitBreakerRegistry.removeGlobalStateChangeListener(this.circuitListener);\n }\n this.circuitBreakerRegistry = undefined;\n this.circuitListener = undefined;\n }\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction mapSelectionSource(selection: AdapterSelection): CliName | 'api' {\n if (selection.source === 'cli') {\n return selection.name as CliName;\n }\n return 'api';\n}\n","/**\n * A CLI slot adapter bound to one requested model (#6599).\n *\n * `UnifiedAdapterRegistry.getAdapterForModel` resolves a model preference to\n * its CLI slot, and the slot adapter is shared and CLI-scoped: it has no\n * model of its own beyond the CLI default. Returning it bare dropped the\n * model, so `execute_expert` ran the CLI's default whatever was asked for.\n * This view stamps the model onto every request that does not name its own,\n * and delegates everything else to the shared slot adapter, which the\n * registry still owns.\n *\n * @module adapters/model-bound-adapter\n */\n\nimport type {\n CompletionRequest,\n CompletionResponse,\n ConfigError,\n ModelCapability,\n ModelError,\n Result,\n} from '../core/index.js';\nimport type { StreamChunk } from '../core/types/model.js';\nimport type { CliName } from '../cli-adapters/types.js';\nimport type { CircuitBreakerRegistry } from '../cli-adapters/circuit-breaker.js';\nimport type { AdapterHealthInfo, IResilientAdapter } from './resilient-adapter-types.js';\n\nexport class ModelBoundAdapter implements IResilientAdapter {\n constructor(\n private readonly slot: IResilientAdapter,\n /** Canonical registry id every unmodelled request is sent with. */\n readonly boundModel: string\n ) {}\n\n get providerId(): string {\n return this.slot.providerId;\n }\n\n get modelId(): string {\n return this.slot.modelId;\n }\n\n get capabilities(): readonly ModelCapability[] {\n return this.slot.capabilities;\n }\n\n private bind(request: CompletionRequest): CompletionRequest {\n return request.model !== undefined ? request : { ...request, model: this.boundModel };\n }\n\n complete(request: CompletionRequest): Promise<Result<CompletionResponse, ModelError>> {\n return this.slot.complete(this.bind(request));\n }\n\n stream(request: CompletionRequest): AsyncIterable<StreamChunk> {\n return this.slot.stream(this.bind(request));\n }\n\n countTokens(text: string): Promise<number> {\n return this.slot.countTokens(text);\n }\n\n validateConfig(): Result<void, ConfigError> {\n return this.slot.validateConfig();\n }\n\n getHealth(): AdapterHealthInfo | undefined {\n return this.slot.getHealth();\n }\n\n refresh(): Promise<void> {\n return this.slot.refresh();\n }\n\n setPreferredCli(cli: CliName | undefined): void {\n this.slot.setPreferredCli(cli);\n }\n\n onFailover(cb: (info: AdapterHealthInfo) => void): () => void {\n return this.slot.onFailover(cb);\n }\n\n getCircuitBreakerRegistry(): CircuitBreakerRegistry | undefined {\n return this.slot.getCircuitBreakerRegistry?.();\n }\n\n /** No-op: the shared slot adapter belongs to the registry, which disposes it. */\n dispose(): void {\n // Intentionally empty — disposing the view must not dispose the slot.\n }\n}\n","/**\n * Unified Adapter Registry — single entry point for all model adapter access.\n *\n * Pre-computes task-to-CLI routing from the canonical model registry and\n * task specialization matrix at creation time. All consumers get adapters\n * through this registry instead of calling createAutoAdapter/createResilientAdapter\n * directly.\n *\n * Design:\n * - One IResilientAdapter per CLI (claude/gemini/codex), created lazily on first access\n * - One \"default\" adapter for unscoped requests (uses createAutoAdapter priority)\n * - Task routing is deterministic: category → primary CLI → cached adapter\n * - Session-scoped: create once at MCP startup, reuse for the session lifetime\n *\n * @module adapters/unified-registry\n * (Source: Issue #1149 — Unified Adapter Registry)\n * (Source: Issue #1151 — Single adapter entry point)\n */\n\nimport type { ILogger } from '../core/index.js';\nimport { ConfigError } from '../core/errors.js';\nimport { getDefaultCliCircuitBreakerRegistry } from '../cli-adapters/cli-circuit-breaker.js';\nimport { createLogger } from '../core/index.js';\nimport { createResilientAdapter } from './resilient-adapter.js';\nimport { ModelBoundAdapter } from './model-bound-adapter.js';\nimport { isGatewayArmId, warnIfGatewayCostUndeclared } from './sdk/gateway-cost.js';\nimport type { IResilientAdapter } from './resilient-adapter-types.js';\nimport type { CliName, EndpointArmId, ObservedArmId } from '../cli-adapters/types.js';\nimport { isCliName, isEndpointArmId } from '../cli-adapters/types.js';\nimport { TASK_SPECIALIZATION_MATRIX, detectTaskCategory } from '../config/task-specialization.js';\nimport type { TaskCategory } from '../config/task-specialization-types.js';\nimport {\n getDefaultModelForCli,\n getInTreeCapabilitiesMatrix,\n} from '../config/model-config-helpers.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Configuration for the unified registry. */\nexport interface UnifiedRegistryConfig {\n /** Logger instance */\n readonly logger?: ILogger;\n /** Default CLI timeout for subprocess calls (ms) */\n readonly defaultCliTimeoutMs?: number;\n}\n\n/** Summary of the pre-computed task routing table. */\nexport interface TaskRoutingEntry {\n readonly category: TaskCategory;\n readonly primaryCli: CliName;\n readonly secondaryCli: CliName;\n readonly primaryModel: string;\n}\n\n/** Snapshot of registry state for observability. */\nexport interface RegistrySnapshot {\n readonly taskRouting: readonly TaskRoutingEntry[];\n /** Every cached arm: lazily created CLI slots and registered `api:*` endpoint arms (#4392). */\n readonly cachedArms: readonly ObservedArmId[];\n readonly availableModels: number;\n}\n\n// ============================================================================\n// Registry\n// ============================================================================\n\n/**\n * Unified adapter registry. Centralizes all adapter creation and task routing.\n *\n * Usage:\n * ```typescript\n * const registry = createUnifiedRegistry({ logger });\n * const adapter = registry.getAdapter('code_generation'); // → codex adapter\n * const adapter2 = registry.getAdapterForCli('claude'); // → claude adapter\n * const adapter3 = registry.getDefault(); // → best available\n * ```\n */\n\nexport class UnifiedAdapterRegistry {\n private readonly logger: ILogger;\n private readonly defaultCliTimeoutMs: number | undefined;\n\n /**\n * Per-arm adapter cache. CLI slots are created lazily by\n * {@link getAdapterForCli}; `api:*` arms enter only through\n * {@link registerApiArm} and are never synthesised (#4392).\n */\n private readonly cliAdapters = new Map<ObservedArmId, IResilientAdapter>();\n\n /** Default adapter for unscoped requests. */\n private defaultAdapter: IResilientAdapter | undefined;\n\n constructor(config?: UnifiedRegistryConfig) {\n this.logger = config?.logger ?? createLogger({ component: 'unified-registry' });\n this.defaultCliTimeoutMs = config?.defaultCliTimeoutMs;\n this.logger.info('UnifiedAdapterRegistry initialized', {\n categories: TASK_SPECIALIZATION_MATRIX.length,\n models: getInTreeCapabilitiesMatrix().models.length,\n });\n }\n\n // --------------------------------------------------------------------------\n // Public API\n // --------------------------------------------------------------------------\n\n /** Logger used by this registry. Exposed so singleton helpers can warn. */\n getLogger(): ILogger {\n return this.logger;\n }\n\n /**\n * Get adapter for a task category. Routing is re-resolved on every read\n * (#3185) so a post-startup overlay/registry update propagates without a\n * restart. Falls back to default adapter if category unknown.\n */\n getAdapter(category: TaskCategory): IResilientAdapter {\n const routing = this.getRouting(category);\n if (routing === undefined) {\n this.logger.warn('Unknown task category, using default', { category });\n return this.getDefault();\n }\n return this.getAdapterForCli(routing.primaryCli);\n }\n\n /**\n * Get adapter for a free-text task description.\n * Detects category from keywords, falls back to default.\n */\n getAdapterForTask(taskDescription: string): IResilientAdapter {\n const match = detectTaskCategory(taskDescription);\n if (match !== null) {\n this.logger.debug('Task category detected', {\n category: match.category,\n cli: match.primaryCli,\n });\n return this.getAdapterForCli(match.primaryCli);\n }\n return this.getDefault();\n }\n\n /**\n * Get adapter pinned to a specific CLI.\n * Creates and caches one IResilientAdapter per CLI.\n */\n getAdapterForCli(cli: CliName): IResilientAdapter {\n const cached = this.cliAdapters.get(cli);\n if (cached !== undefined) return cached;\n\n const raw = createResilientAdapter({\n logger: this.logger,\n preferredCli: cli,\n // #4659: the SHARED registry — the same one that already gates\n // voter-panel availability (#4330). Per-adapter registries would let one\n // adapter keep routing to a CLI another has already seen fail.\n circuitBreakerRegistry: getDefaultCliCircuitBreakerRegistry(),\n ...(this.defaultCliTimeoutMs !== undefined && {\n defaultCliTimeoutMs: this.defaultCliTimeoutMs,\n }),\n });\n const adapter = raw;\n this.cliAdapters.set(cli, adapter);\n this.logger.info('Created CLI-specific adapter', {\n cli,\n });\n return adapter;\n }\n\n /**\n * Get the adapter for a routing arm (#4392). A CLI slot resolves exactly as\n * {@link getAdapterForCli} (created lazily, cached, armed with the shared\n * breaker registry). An `api:*` arm resolves to what {@link registerApiArm}\n * supplied, or `undefined` — never to a CLI slot, and never by creating one.\n */\n getAdapterForArm(arm: ObservedArmId): IResilientAdapter | undefined {\n // Split on CLI-slot membership, not on the validator: an `api:` string\n // that fails validation must read as \"not registered\", never be handed\n // to getAdapterForCli to mint a slot adapter under a garbage name.\n if (isCliName(arm)) {\n return this.getAdapterForCli(arm);\n }\n return this.cliAdapters.get(arm);\n }\n\n /**\n * Register an `api:*` arm's adapter under its endpoint identity (#4392).\n * Refuses built-in vendor arms (`api:anthropic`, `api:openai`, `api:google`, `api:gemini`)\n * to prevent hijacking or redirecting vendor traffic without authorization.\n * Accepts a dynamic `EndpointArmId`; the id is re-validated at runtime\n * because the `EndpointArmId` type admits any `api:` string, so a cast from an\n * unvalidated name is exactly what this refuses.\n * Registering an id twice replaces (and disposes) the earlier adapter.\n * CLI-slot behaviour is untouched. Endpoint arms are observable here and in\n * the shared breaker registry. The router factory admits them only with\n * NEXUS_ROUTE_GATEWAY_ARMS opt-in and a cost declaration (#7151). An arm\n * registered without NEXUS_GATEWAY_COST is warned about once here, even\n * when routing is disabled (#4392 increment 2).\n */\n registerApiArm(arm: EndpointArmId, adapter: IResilientAdapter): void {\n if (!isEndpointArmId(arm)) {\n throw new Error(`Invalid api arm id: ${JSON.stringify(arm)} (expected api:<endpoint>)`);\n }\n if (!isGatewayArmId(arm) || arm === 'api:gemini') {\n throw new Error(`Cannot overwrite built-in vendor arm: ${arm}`);\n }\n this.cliAdapters.get(arm)?.dispose();\n this.cliAdapters.set(arm, adapter);\n this.logger.info('Registered api arm adapter', { arm });\n warnIfGatewayCostUndeclared(arm, this.logger);\n }\n\n /**\n * Get adapter for a model preference string (e.g., \"claude-opus-4-6\").\n * Resolves the model to its CLI via the canonical registry.\n * Falls back to default adapter if model not recognized.\n *\n * An exact match returns the CLI slot adapter bound to the matched registry\n * id, so the model reaches the CLI instead of its default (#6599). A prefix\n * match routes to the CLI only, as before: the name was not an entry.\n */\n getAdapterForModel(modelPreference: string): IResilientAdapter {\n // Prefer exact matches (id / cliAlias / cliModelName) over prefix matches.\n // For prefix fallback, longest-prefix-wins so a future registry containing\n // both 'gemini-pro' and 'gemini-pro-experimental' resolves correctly even\n // though the registry's natural array order isn't sorted by id length.\n // Defense-in-depth — no current registry has prefix overlaps. (#2192)\n const allModels = getInTreeCapabilitiesMatrix().models;\n const exact = allModels.find(\n (m) =>\n m.id === modelPreference ||\n m.cliAlias === modelPreference ||\n m.cliModelName === modelPreference\n );\n const prefix =\n exact ??\n [...allModels]\n .filter((m) => modelPreference.startsWith(m.id))\n .sort((a, b) => b.id.length - a.id.length)[0];\n const model = prefix;\n if (model !== undefined) {\n this.logger.debug('Model resolved to CLI', {\n model: modelPreference,\n cli: model.cliName,\n });\n const slot = this.getAdapterForCli(model.cliName as CliName);\n return exact !== undefined ? new ModelBoundAdapter(slot, exact.id) : slot;\n }\n this.logger.debug('Model not in registry, using default', {\n model: modelPreference,\n });\n return this.getDefault();\n }\n\n /**\n * Get adapter for an expert role (e.g., \"code_expert\").\n * Uses ROLE_TO_TASK_CATEGORY mapping → task specialization → CLI.\n */\n getAdapterForRole(role: string): IResilientAdapter {\n const category = ROLE_TO_CATEGORY[role];\n if (category !== undefined) return this.getAdapter(category);\n return this.getDefault();\n }\n\n /**\n * Get the default adapter (no CLI preference — auto-detection priority).\n */\n getDefault(): IResilientAdapter {\n if (this.defaultAdapter !== undefined) return this.defaultAdapter;\n const raw = createResilientAdapter({\n logger: this.logger,\n circuitBreakerRegistry: getDefaultCliCircuitBreakerRegistry(),\n ...(this.defaultCliTimeoutMs !== undefined && {\n defaultCliTimeoutMs: this.defaultCliTimeoutMs,\n }),\n });\n this.defaultAdapter = raw;\n return this.defaultAdapter;\n }\n\n /**\n * Get snapshot of registry state for observability/debugging. Routing is\n * re-resolved on read (#3185) so the snapshot reflects the live registry.\n */\n getSnapshot(): RegistrySnapshot {\n return {\n taskRouting: TASK_SPECIALIZATION_MATRIX.map((spec) => this.resolveRouting(spec)),\n cachedArms: [...this.cliAdapters.keys()],\n availableModels: getInTreeCapabilitiesMatrix().models.length,\n };\n }\n\n /**\n * Resolve the routing for a specific category.\n *\n * Computed on every read (#3185) rather than cached at construction, so a\n * post-startup model-registry / overlay update (e.g. a default-model change\n * surfaced via `getDefaultModelForCli`) propagates to routing decisions\n * without a process restart. The matrix is ~10 categories — the per-read\n * resolution cost is negligible.\n */\n getRouting(category: TaskCategory): TaskRoutingEntry | undefined {\n const spec = TASK_SPECIALIZATION_MATRIX.find((s) => s.category === category);\n if (spec === undefined) return undefined;\n return this.resolveRouting(spec);\n }\n\n /**\n * Dispose all cached adapters.\n */\n dispose(): void {\n for (const adapter of this.cliAdapters.values()) {\n adapter.dispose();\n }\n this.cliAdapters.clear();\n this.defaultAdapter?.dispose();\n this.defaultAdapter = undefined;\n this.logger.info('UnifiedAdapterRegistry disposed');\n }\n\n // --------------------------------------------------------------------------\n // Private\n // --------------------------------------------------------------------------\n\n /**\n * Resolve one specialization-matrix row into a routing entry, re-reading the\n * primary model from the (overlay-aware) model registry each call (#3185).\n */\n private resolveRouting(spec: (typeof TASK_SPECIALIZATION_MATRIX)[number]): TaskRoutingEntry {\n return {\n category: spec.category,\n primaryCli: spec.primaryCli,\n secondaryCli: spec.secondaryCli,\n primaryModel: resolveDefaultModel(spec.primaryCli),\n };\n }\n}\n\n// ============================================================================\n// Role → Category Mapping (consolidated from create-expert-routing.ts)\n// ============================================================================\n\n/** Maps expert roles to task categories for CLI specialization. */\nconst ROLE_TO_CATEGORY: Record<string, TaskCategory> = {\n code_expert: 'code_generation',\n architecture_expert: 'architecture',\n security_expert: 'security_review',\n documentation_expert: 'documentation',\n testing_expert: 'testing',\n devops_expert: 'devops',\n research_expert: 'research',\n pm_expert: 'planning',\n ux_expert: 'planning',\n infrastructure_expert: 'devops',\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Resolve the default model name for a CLI from the canonical registry. */\nfunction resolveDefaultModel(cli: string): string {\n if (isCliName(cli)) {\n return getDefaultModelForCli(cli);\n }\n return cli;\n}\n\n// ============================================================================\n// Factory & Singleton\n// ============================================================================\n\nlet globalRegistry: UnifiedAdapterRegistry | undefined;\n\n/**\n * Create a new UnifiedAdapterRegistry instance.\n * For most uses, prefer `getGlobalRegistry()` instead.\n */\nexport function createUnifiedRegistry(config?: UnifiedRegistryConfig): UnifiedAdapterRegistry {\n return new UnifiedAdapterRegistry(config);\n}\n\n/**\n * Claim the global registry for a process entry point, choosing its logger\n * and initial settings (#6012, #7151). First claim wins; later claims reuse\n * that configuration. Later non-empty settings are warned about because\n * they cannot be applied; a logger-only claim remains silent and idempotent.\n *\n * That difference is the point. There is not exactly one composition root: the\n * bundled CLI enters through `cli.ts main()`, and an embedder can start the MCP\n * server directly without it. Roots may name a logger without reconfiguration;\n * explicitly supplied settings must never be silently discarded.\n *\n * This does NOT provide per-caller log attribution: the singleton has one\n * logger. It makes that one logger a deliberate choice rather than a\n * consequence of which module happened to run first.\n */\nexport function claimGlobalRegistry(\n logger: ILogger,\n config?: Omit<UnifiedRegistryConfig, 'logger'>\n): UnifiedAdapterRegistry {\n if (globalRegistry === undefined) {\n globalRegistry = new UnifiedAdapterRegistry({ ...config, logger });\n } else if (config !== undefined && Object.keys(config).length > 0) {\n logger.warn(\n 'UnifiedAdapterRegistry claim ignored configuration: singleton already initialized',\n {\n providedKeys: Object.keys(config),\n }\n );\n }\n return globalRegistry;\n}\n\n/**\n * Thrown by {@link getGlobalRegistry} when a non-empty config arrives after\n * the singleton exists (#5211). The registry has no way to apply it — the\n * logger and `defaultCliTimeoutMs` are fixed at construction — so until this\n * error existed the config was logged at `warn` and dropped, and the caller\n * went on with a registry built from someone else's settings. A config that is\n * accepted and ignored is an instrument that misreports what it was given.\n *\n * The check is on presence, not on equality with the live config: the registry\n * does not keep the config it was built from, and a caller re-supplying the\n * same values is still a caller that believes it configured something.\n */\nexport class RegistryAlreadyInitializedError extends ConfigError {\n constructor(providedKeys: readonly string[]) {\n super(\n 'UnifiedAdapterRegistry singleton is already initialized, so getGlobalRegistry() cannot ' +\n `apply the supplied config (keys: ${providedKeys.join(', ')}). Call resetGlobalRegistry() ` +\n 'first if reconfiguration is intentional, or getGlobalRegistry() with no config to use the ' +\n 'existing instance; claimGlobalRegistry(logger) is the idempotent way to name the logger.',\n { context: { providedKeys: [...providedKeys] } }\n );\n this.name = 'RegistryAlreadyInitializedError';\n }\n}\n\n/**\n * Get the global singleton registry.\n * Creates it on first access with default config.\n *\n * If the singleton already exists and a non-empty config is supplied, this\n * throws {@link RegistryAlreadyInitializedError} — the config cannot be\n * applied, and returning the existing instance would silently hand the caller\n * a registry configured by whoever ran first (#5211). Omitting the config, or\n * passing an empty object, returns the existing instance as before.\n */\nexport function getGlobalRegistry(config?: UnifiedRegistryConfig): UnifiedAdapterRegistry {\n if (globalRegistry === undefined) {\n globalRegistry = new UnifiedAdapterRegistry(config);\n return globalRegistry;\n }\n if (config !== undefined && Object.keys(config).length > 0) {\n throw new RegistryAlreadyInitializedError(Object.keys(config));\n }\n return globalRegistry;\n}\n\n/** Reset the global registry (for testing). */\nexport function resetGlobalRegistry(): void {\n globalRegistry?.dispose();\n globalRegistry = undefined;\n}\n","/**\n * nexus-agents/cli-adapters - Antigravity (`agy`) CLI Response Parser\n *\n * Parses `agy --output-format json`, the replacement for the retired standalone\n * `gemini` CLI (#4346).\n *\n * FAIL-CLOSED BY CONSTRUCTION. `agy` exits 0 even when the run failed — a bad\n * model returns `{\"status\":\"ERROR\",\"response\":\"\",\"error\":\"…\"}` with exit code 0.\n * The verdict lives in the `status` field, so this parser treats anything that\n * is not an explicit `SUCCESS` envelope with a string `response` as a failure:\n * unparseable output, truncated JSON, a missing `status`, an unrecognized\n * `status`, and a non-string `response` all yield `null`. Callers must not\n * infer success from the process exit code.\n *\n * Verified against `agy` v1.1.9 (2026-08-09).\n *\n * @module cli-adapters/parsers/agy-parser\n */\n\nimport { z } from 'zod';\nimport type { ICliResponseParser, TokenUsage } from '../types.js';\n\n/**\n * The usage block agy reports. `thinking_tokens` and `cache_read_tokens` have no\n * home in {@link TokenUsage}; see {@link AgyResponseParser.extractUsage} for how\n * they are handled rather than dropped.\n */\nconst AgyUsageSchema = z.object({\n input_tokens: z.number(),\n output_tokens: z.number(),\n thinking_tokens: z.number().optional(),\n cache_read_tokens: z.number().optional(),\n total_tokens: z.number(),\n});\n\n/**\n * A successful agy envelope. `status` is pinned to the literal `SUCCESS` so an\n * unrecognized future status (e.g. a `PARTIAL`) fails the parse instead of being\n * waved through as a success.\n */\nconst AgySuccessSchema = z.object({\n status: z.literal('SUCCESS'),\n response: z.string(),\n conversation_id: z.string().optional(),\n duration_seconds: z.number().optional(),\n num_turns: z.number().optional(),\n usage: AgyUsageSchema.optional(),\n});\n\n/** A failed agy envelope — still delivered with exit code 0. */\nconst AgyErrorSchema = z.object({\n status: z.string(),\n error: z.string().optional(),\n response: z.string().optional(),\n conversation_id: z.string().optional(),\n});\n\n/** A parsed, validated agy success envelope. */\nexport type AgyCliResponse = z.infer<typeof AgySuccessSchema>;\n\n/** Parse raw stdout as JSON, or undefined when it is not JSON at all. */\nfunction asJson(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Parser for `agy --output-format json`.\n *\n * `parse` returns a value ONLY for a well-formed success envelope. Failure\n * detail is available separately via {@link AgyResponseParser.extractErrorMessage}.\n */\nexport class AgyResponseParser implements ICliResponseParser<AgyCliResponse> {\n readonly name = 'agy-parser';\n readonly supportedVersionRange = '>=1.0.0 <2.0.0';\n\n parse(raw: string): AgyCliResponse | null {\n const json = asJson(raw);\n if (json === undefined) return null;\n const parsed = AgySuccessSchema.safeParse(json);\n return parsed.success ? parsed.data : null;\n }\n\n extractResponse(raw: string): string | null {\n return this.parse(raw)?.response ?? null;\n }\n\n /**\n * The error text from a non-SUCCESS envelope, or null when the run succeeded\n * or the output was not a recognizable agy envelope at all.\n *\n * Returning the message lets the adapter classify it (rate limit, auth,\n * bad model) through the shared taxonomy rather than reporting a bare\n * PARSE_ERROR — the same reason `opencode-parser` grew this method.\n */\n extractErrorMessage(raw: string): string | null {\n const json = asJson(raw);\n if (json === undefined) return null;\n // A valid success envelope has no error to report.\n if (AgySuccessSchema.safeParse(json).success) return null;\n const parsed = AgyErrorSchema.safeParse(json);\n if (!parsed.success) return null;\n return parsed.data.error ?? `agy reported status '${parsed.data.status}'`;\n }\n\n /**\n * Maps agy's usage block onto {@link TokenUsage}.\n *\n * `thinking_tokens` are **folded into `outputTokens`** rather than dropped:\n * they are generated, billable tokens, and discarding them would understate\n * cost in exactly the outcome data the routing loop learns from.\n * `cache_read_tokens` are deliberately NOT added — they are a subset of input\n * already counted in `input_tokens`, so adding them would double-count.\n */\n /**\n * agy's `conversation_id` is the session handle — it is what `--conversation`\n * accepts to resume a run, so it maps directly onto the session-id contract.\n */\n extractSessionId(raw: string): string | null {\n const id = this.parse(raw)?.conversation_id;\n return id === undefined || id === '' ? null : id;\n }\n\n extractUsage(raw: string): TokenUsage | null {\n const parsed = this.parse(raw);\n if (parsed?.usage === undefined) return null;\n const { input_tokens, output_tokens, thinking_tokens, total_tokens } = parsed.usage;\n return {\n inputTokens: input_tokens,\n outputTokens: output_tokens + (thinking_tokens ?? 0),\n totalTokens: total_tokens,\n };\n }\n}\n","/**\n * nexus-agents/config - Antigravity (`agy`) model-slug mapping\n *\n * Maps canonical registry model ids onto the model slugs the `agy` CLI accepts\n * (#4346).\n *\n * WHY THIS IS SEPARATE FROM `cliModelName`. The obvious move — repointing the\n * gemini entries' `cliModelName` at agy slugs — is wrong: that field is ALSO\n * read by the API-based `GeminiAdapter` via `GEMINI_MODELS`\n * (`adapters/gemini-types.ts:21-23`), which calls the Google API directly and\n * needs real API ids like `gemini-2.5-flash`. agy's slugs (`gemini-3.6-flash-low`)\n * are meaningless to that API. One field cannot serve both surfaces, so the\n * CLI-transport naming lives here.\n *\n * Lives under `config/` because `scripts/check-model-string-drift.ts` blocks\n * version-bearing model-id literals outside this directory, and enforces it in\n * CI and pre-push.\n *\n * Verified against `agy models` on v1.1.21 (2026-08-26). `agy models` is once\n * again enumerable non-interactively — it completed piped in ~1s, exit 0, over\n * three runs. #4393 recorded it hanging for 90s without a TTY on v1.1.11; that\n * was an upstream defect and it is fixed. `scripts/check-agy-model-drift.ts`\n * now compares this list against the live CLI so it cannot silently rot again.\n *\n * Re-checked on v1.3.1 (2026-10-07): agy no longer serves any `gemini-3.5-*`\n * slug and rejects one with status ERROR at exit 0, so those were removed\n * (#7217). It now also lists 3.8 Flash; adopting that is a new-model decision\n * (#6625) and is deliberately not made here.\n *\n * @module config/agy-model-map\n */\n\nimport { findCanonicalModel } from './model-config-helpers.js';\n\n/**\n * The model slugs `agy` accepts, as reported by `agy models`.\n *\n * agy bakes reasoning effort into the slug (`-high`/`-medium`/`-low`) rather\n * than taking it as a separate axis. A `--effort` flag also exists; the slug\n * suffix is used here because it is what `agy models` enumerates, making it the\n * machine-readable contract.\n *\n * agy is multi-model — it also fronts `claude-sonnet-4-6`,\n * `claude-opus-4-6-thinking` and `gpt-oss-120b-medium`. Those are deliberately\n * NOT mapped: the `gemini` routing arm means \"Gemini-family models\", and this\n * repo already routes Claude through the claude adapter and GPT-OSS through\n * openrouter arms. Adding duplicate routes here would give the router redundant\n * arms to disambiguate with no consumer asking for them (#4346, 7/0 vote).\n */\nexport const AGY_MODEL_SLUGS = [\n 'gemini-3.7-flash-high',\n 'gemini-3.7-flash-medium',\n 'gemini-3.7-flash-low',\n 'gemini-3.6-flash-high',\n 'gemini-3.6-flash-medium',\n 'gemini-3.6-flash-low',\n 'gemini-3.1-pro-high',\n 'gemini-3.1-pro-low',\n] as const;\n\nexport type AgyModelSlug = (typeof AGY_MODEL_SLUGS)[number];\n\n/**\n * Canonical registry model id → agy slug.\n *\n * Mapped by TIER SEMANTICS, not by version-string similarity, because agy's\n * generations do not line up with the registry's. The registry's quality\n * profile is the guide: the two `pro` entries take the pro slugs (higher\n * reasoning gets `-high`), and the three flash entries take flash slugs\n * descending by the cost/quality trade-off each entry records.\n *\n * `gemini-pro` and `gemini-flash` are registry entries for the 2.5 generation,\n * which agy does not serve at all; they map to the nearest surviving tier rather\n * than being dropped, so routing that already selects them keeps working.\n */\nconst CANONICAL_TO_AGY: Readonly<Record<string, AgyModelSlug>> = {\n // reasoning 10 — the strongest entry takes the strongest pro tier\n 'gemini-3-pro': 'gemini-3.1-pro-high',\n // reasoning 9, 2.5-generation — nearest surviving pro tier\n 'gemini-pro': 'gemini-3.1-pro-low',\n // speed 10 / quality 8. agy 1.3.1 dropped every 3.5 slug (#7217); the\n // newest Flash already listed takes over at the same effort tier.\n 'gemini-3.5-flash': 'gemini-3.7-flash-medium',\n // speed 10 / quality 8, cheaper than the above — same effort tier as before\n 'gemini-3-flash': 'gemini-3.7-flash-low',\n // cheapest entry, quality 7, 2.5-generation\n 'gemini-flash': 'gemini-3.6-flash-low',\n};\n\n/**\n * agy slug → canonical registry id. Derived from {@link CANONICAL_TO_AGY} so the\n * two directions cannot drift (#4395).\n *\n * Needed because the forward map alone left the arm unable to describe what it\n * actually ran: `getModelInfo()` reported the registry's `cliModelName` (a\n * Google API id agy does not accept) while `getCommand()` spawned the slug. That\n * mismatch reached `TaskOutcome.model`, so the routing loop was told the wrong\n * model produced each outcome, and pricing could not resolve the slug at all.\n */\nconst AGY_TO_CANONICAL: ReadonlyMap<string, string> = new Map(\n Object.entries(CANONICAL_TO_AGY).map(([canonical, slug]) => [slug, canonical])\n);\n\n/**\n * Resolve an agy slug back to the canonical registry id, or null when the slug\n * is one agy serves but the registry has no entry for.\n *\n * Null rather than a guess: several registry entries map onto the same slug\n * where agy's generations do not line up with ours, so a reverse lookup is\n * lossy by construction. Callers should fall back to the raw slug rather than\n * inventing an entry.\n */\nexport function fromAgyModelSlug(slug: string): string | null {\n return AGY_TO_CANONICAL.get(slug) ?? null;\n}\n\n/** The slug used when a caller names a model agy cannot serve. */\nexport const DEFAULT_AGY_MODEL: AgyModelSlug = 'gemini-3.1-pro-high';\n\n/** Whether a string is a slug `agy` will accept. */\nexport function isAgyModelSlug(value: string): value is AgyModelSlug {\n return (AGY_MODEL_SLUGS as readonly string[]).includes(value);\n}\n\n/**\n * Resolve a model identifier to a slug `agy` accepts.\n *\n * Accepts an already-valid agy slug unchanged (so callers can pin one\n * directly), then a canonical registry id, and otherwise falls back to\n * {@link DEFAULT_AGY_MODEL}.\n *\n * The fallback is deliberate rather than an error: an unmapped id reaching agy\n * produces `{\"status\":\"ERROR\",\"error\":\"invalid model selection ...\"}` **with\n * exit code 0**, which is a far worse failure than quietly running a valid\n * model. The substitution is logged by the caller.\n */\nexport function toAgyModelSlug(model: string): AgyModelSlug {\n if (isAgyModelSlug(model)) return model;\n const direct = CANONICAL_TO_AGY[model];\n if (direct !== undefined) return direct;\n // #4395: callers legitimately pin a registry `cliModelName` (a Google API id\n // like `gemini-2.5-pro`) rather than the canonical entry id. Resolve it to the\n // canonical entry before mapping, so a pinned model is honoured instead of\n // silently falling through to the default.\n const canonical = findCanonicalModel('gemini', model)?.id;\n if (canonical !== undefined) {\n const viaCanonical = CANONICAL_TO_AGY[canonical];\n if (viaCanonical !== undefined) return viaCanonical;\n }\n return DEFAULT_AGY_MODEL;\n}\n","/**\n * nexus-agents/cli-adapters - Gemini CLI Adapter Helpers\n *\n * CLI-specific helper functions for retry logic and error handling.\n * Model info lookups consolidated into config/model-config-helpers.ts (#886).\n */\n\nimport type { CliError, CliName } from '../types.js';\n\n// -----------------------------------------------------------------------------\n// Fallback Defaults (for unknown models not in canonical registry)\n// -----------------------------------------------------------------------------\n\n/**\n * Fallback defaults for Gemini models not in the canonical registry.\n * All current models are in config/in-tree-data.ts and served by\n * buildModelInfo('gemini', model). This provides sensible defaults\n * when an unknown model name is encountered at runtime.\n *\n * @see config/in-tree-data.ts — single source of truth for current models\n */\nexport const GEMINI_LEGACY_DEFAULTS = {\n displayNames: {} as Readonly<Record<string, string>>,\n contextWindows: {} as Readonly<Record<string, number>>,\n inputCosts: {} as Readonly<Record<string, number>>,\n outputCosts: {} as Readonly<Record<string, number>>,\n contextWindow: 1_000_000,\n inputCost: 0.15,\n outputCost: 0.6,\n} as const;\n\n// -----------------------------------------------------------------------------\n// Re-exports from canonical cli-retry-loop.ts (Issue #1596)\n// -----------------------------------------------------------------------------\n\nexport { calculateBackoffDelay, isRetryableError, categorizeError } from '../cli-retry-loop.js';\n\n// -----------------------------------------------------------------------------\n// Error Factory\n// -----------------------------------------------------------------------------\n\n/** Creates a circuit breaker open error. */\nexport function createCircuitOpenError(cli: CliName): CliError {\n return {\n code: 'EXECUTION_ERROR',\n message: `Circuit breaker is open - ${cli} CLI temporarily unavailable`,\n cli,\n retryable: false,\n };\n}\n\n// -----------------------------------------------------------------------------\n// Utility Functions\n// -----------------------------------------------------------------------------\n\n// Re-export from canonical source for backward compatibility\nexport { delay } from '../../utils/async-utils.js';\n","/**\n * agy invocation helpers shared by the gemini adapter and the `pnpm review`\n * script (#4389), so both spawn agy with the same default model and the same\n * print-mode wait.\n *\n * @module cli-adapters/adapters/agy-invocation\n */\n\nimport { getCliModelName, getDefaultModelForCli } from '../../config/model-config-helpers.js';\n\n/** Derive the CLI model name for the default Gemini model from the canonical registry. */\nexport const DEFAULT_GEMINI_CLI_MODEL: string = getCliModelName(getDefaultModelForCli('gemini'));\n\n/** Headroom between agy's print-mode wait and the subprocess guard (#6277). */\nconst AGY_PRINT_TIMEOUT_HEADROOM_MS = 5_000;\n/** Shortest wait handed to agy; below this a seat cannot answer at all. */\nconst AGY_PRINT_TIMEOUT_FLOOR_S = 30;\n\n/**\n * agy's `--print-timeout` argv (Go duration, whole seconds) for a task\n * budget: the guard minus a fixed headroom, never below the floor. No\n * budget → no flag, so agy's own default applies.\n */\nexport function agyPrintTimeoutArgs(timeoutMs: number | undefined): readonly string[] {\n if (timeoutMs === undefined) return [];\n const seconds = Math.floor((timeoutMs - AGY_PRINT_TIMEOUT_HEADROOM_MS) / 1000);\n return ['--print-timeout', `${String(Math.max(AGY_PRINT_TIMEOUT_FLOOR_S, seconds))}s`];\n}\n","/**\n * nexus-agents/cli-adapters - Gemini CLI Adapter\n *\n * Subprocess-based adapter for Gemini CLI with:\n * - Tiered timeout profiles based on task complexity\n * - Resilient JSON parsing with fallback strategies\n * - Exponential backoff retry logic\n * - Circuit breaker integration for sustained failures\n *\n * (Source: cli-project_plan.md v2.1.0)\n * (Source: Issue #366 - Gemini CLI timeout and parser improvements)\n * (Source: Issue #389 - Merged enhanced adapter back to canonical)\n */\n\nimport type { Result, ILogger } from '../../core/index.js';\nimport { ok, err, createLogger, getTimeProvider } from '../../core/index.js';\nimport type {\n ICliResponseParser,\n CliTask,\n CliResponse,\n CliError,\n ModelInfo,\n CliName,\n ExecutionOptions,\n ResolvedExecutionOptions,\n BaseAdapterOptions,\n} from '../types.js';\nimport { SubprocessCliAdapter, type CommandConfig } from '../subprocess-adapter.js';\nimport { withEnforcedAccessMode } from '../access-mode.js';\nimport { AgyResponseParser } from '../parsers/agy-parser.js';\nimport { toAgyModelSlug, AGY_MODEL_SLUGS } from '../../config/agy-model-map.js';\nimport type { CliModelInfo } from '../types-capability.js';\nimport {\n getTimeoutForTask,\n estimateTaskComplexity,\n type TaskComplexity,\n} from '../cli-timeout-profiles.js';\nimport {\n CliCircuitBreaker,\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n type CircuitBreakerConfig,\n type CircuitBreakerSnapshot,\n} from '../circuit-breaker.js';\nimport { GEMINI_LEGACY_DEFAULTS, createCircuitOpenError } from './gemini-adapter-helpers.js';\nimport { executeCliRetryLoop } from '../cli-retry-loop.js';\nimport { GEMINI_CLI_COMMAND } from '../cli-error-envelope.js';\nimport { DEFAULT_GEMINI_CLI_MODEL, agyPrintTimeoutArgs } from './agy-invocation.js';\nimport { buildModelInfo } from '../../config/model-config-helpers.js';\n\n/** Configuration for Gemini adapter. Extends BaseAdapterOptions with retry/circuit breaker. */\nexport interface GeminiConfig extends BaseAdapterOptions {\n /** Maximum retry attempts (default: 3) */\n readonly maxRetries?: number;\n /** Base delay for exponential backoff in ms (default: 1000) */\n readonly baseDelayMs?: number;\n /** Maximum delay for backoff in ms (default: 30000) */\n readonly maxDelayMs?: number;\n /** Circuit breaker configuration */\n readonly circuitBreakerConfig?: Partial<CircuitBreakerConfig>;\n /** Enable circuit breaker (default: true) */\n readonly enableCircuitBreaker?: boolean;\n}\n\n/** Execution result with metadata. */\nexport interface GeminiExecutionResult {\n readonly response: CliResponse;\n readonly retryCount: number;\n readonly totalDurationMs: number;\n readonly complexity: TaskComplexity;\n readonly circuitState: 'closed' | 'open' | 'half-open';\n}\n\nconst DEFAULT_CONFIG: Required<Omit<GeminiConfig, 'logger' | 'circuitBreakerConfig'>> = {\n model: DEFAULT_GEMINI_CLI_MODEL,\n maxRetries: 3,\n baseDelayMs: 1000,\n maxDelayMs: 30_000,\n enableCircuitBreaker: true,\n};\n\n/**\n * The executable name spawned by the Gemini CLI adapter (#4346, #6278).\n * The standalone gemini CLI is EOL — it exits 55 with IneligibleTierError on\n * every invocation.\n */\nexport { GEMINI_CLI_COMMAND };\n\n/**\n * Gemini CLI adapter with reliability features.\n *\n * Includes tiered timeouts, resilient parsing, retry logic, and circuit breaker.\n */\nexport class GeminiCliAdapter extends SubprocessCliAdapter {\n readonly name: CliName = 'gemini';\n // agy cannot enforce read-only analysis (#6962), so it refuses those tasks.\n // #6754 mapped the mode to `--mode plan --sandbox` from `agy --help` alone.\n // Observed live on 2026-10-02 with agy 1.2.15: given exactly that argv and a\n // prompt asking it to, agy created `pwned.txt` and rewrote a committed file\n // in a scratch repository, on two differently phrased prompts. Plan mode\n // writes a plan and then executes it in print mode; `--sandbox` restricts\n // the terminal, not the file-edit tools.\n override readonly enforcesReadOnlyAnalysis = false;\n\n /**\n * #4346: the arm is still called `gemini` (it serves Google's Gemini models\n * and keeps the routing/LinUCB identity), but the executable is `agy`. The\n * standalone gemini CLI is EOL — it exits 55 with IneligibleTierError on\n * every invocation.\n */\n override get binaryName(): string {\n return GEMINI_CLI_COMMAND;\n }\n protected readonly parser: ICliResponseParser;\n\n private readonly model: string;\n private readonly maxRetries: number;\n private readonly baseDelayMs: number;\n private readonly maxDelayMs: number;\n private readonly circuitBreaker: CliCircuitBreaker | null;\n private readonly adapterLogger: ILogger;\n\n constructor(options?: GeminiConfig) {\n const mergedConfig = { ...DEFAULT_CONFIG, ...options };\n super(options?.logger);\n\n this.model = mergedConfig.model;\n this.maxRetries = mergedConfig.maxRetries;\n this.baseDelayMs = mergedConfig.baseDelayMs;\n this.maxDelayMs = mergedConfig.maxDelayMs;\n this.parser = new AgyResponseParser();\n this.adapterLogger = options?.logger ?? createLogger({ component: 'gemini-adapter' });\n\n // Initialize circuit breaker if enabled\n if (mergedConfig.enableCircuitBreaker) {\n const cbConfig: CircuitBreakerConfig = {\n ...DEFAULT_CIRCUIT_BREAKER_CONFIG,\n ...options?.circuitBreakerConfig,\n };\n this.circuitBreaker = new CliCircuitBreaker('gemini', cbConfig);\n } else {\n this.circuitBreaker = null;\n }\n }\n\n /** Key-free model enumeration via the models.dev snapshot (#3405). */\n /**\n * The slugs this arm can actually run (#5085).\n *\n * NOT `listModelsForCli('gemini')`, which resolves the models.dev `google`\n * vendor — 82 Google **API** ids like `gemini-2.5-flash`. This arm spawns\n * `agy`, which accepts none of them; the same reasoning already documented\n * for `cliModelName` in `config/agy-model-map.ts` applies to enumeration.\n * Reporting the API list made every consumer confidently wrong rather than\n * empty, which is worse.\n */\n listModels(): Promise<readonly CliModelInfo[]> {\n return Promise.resolve(AGY_MODEL_SLUGS.map((id) => ({ id, provider: 'antigravity' })));\n }\n\n /**\n * Gets Gemini model information.\n * Resolves from canonical registry when possible, falls back to legacy lookup.\n * Note: maxOutput is capped at 8_192 (Gemini CLI constraint).\n */\n getModelInfo(): ModelInfo {\n const fromRegistry = buildModelInfo('gemini', this.model);\n if (fromRegistry !== undefined) {\n return { ...fromRegistry, maxOutput: 8_192 };\n }\n return {\n id: this.model,\n name: GEMINI_LEGACY_DEFAULTS.displayNames[this.model] ?? this.model,\n contextWindow:\n GEMINI_LEGACY_DEFAULTS.contextWindows[this.model] ?? GEMINI_LEGACY_DEFAULTS.contextWindow,\n maxOutput: 8_192,\n costPerMillionInput:\n GEMINI_LEGACY_DEFAULTS.inputCosts[this.model] ?? GEMINI_LEGACY_DEFAULTS.inputCost,\n costPerMillionOutput:\n GEMINI_LEGACY_DEFAULTS.outputCosts[this.model] ?? GEMINI_LEGACY_DEFAULTS.outputCost,\n };\n }\n\n /**\n * Executes a task with reliability features.\n */\n override async execute(\n task: CliTask,\n options?: ExecutionOptions\n ): Promise<Result<CliResponse, CliError>> {\n const result = await this.executeWithMetadata(task, options);\n\n if (result.ok) {\n // #6792: this path bypasses the base execute, so it stamps the mode too.\n return ok(withEnforcedAccessMode(result.value.response, task));\n }\n\n return err(result.error);\n }\n\n /**\n * Executes with full metadata about retry attempts and circuit state.\n */\n async executeWithMetadata(\n task: CliTask,\n options?: ExecutionOptions\n ): Promise<Result<GeminiExecutionResult, CliError>> {\n // #6754: this path bypasses the base execute, so it applies the same\n // fail-closed access-mode check first.\n const refusal = await this.accessModeRefusal(task);\n if (refusal !== undefined) return err(refusal);\n const circuitCheckResult = this.checkCircuitBreaker();\n if (circuitCheckResult !== null) {\n return err(circuitCheckResult);\n }\n\n const startTime = getTimeProvider().now();\n const complexity = estimateTaskComplexity(task.content);\n const effectiveOptions = this.buildExecutionOptions(task.content, options);\n\n const result = await this.executeWithRetryTracking(task, effectiveOptions);\n\n return this.buildExecutionResult(result, startTime, complexity);\n }\n\n /**\n * Gets current circuit breaker snapshot.\n */\n getCircuitBreakerSnapshot(): CircuitBreakerSnapshot | null {\n return this.circuitBreaker?.getSnapshot() ?? null;\n }\n\n /**\n * Resets the circuit breaker to closed state.\n */\n resetCircuitBreaker(): void {\n this.circuitBreaker?.reset();\n }\n\n /**\n * Gets CLI command and arguments for execution.\n */\n protected override getCommand(task: CliTask): CommandConfig {\n const args: string[] = [];\n\n // #4346: the standalone `gemini` CLI is retired — it fails every invocation\n // with IneligibleTierError (exit 55). `agy` (Antigravity) is Google's own\n // replacement. Flag spellings differ entirely from the old CLI:\n // -o json -> --output-format json\n // -m <model> -> --model <slug>\n // --resume -> --conversation\n // --policy -> (no equivalent; see systemPrompt handling below)\n args.push('--output-format', 'json');\n\n // Registry model ids and agy slugs are different namespaces — see\n // config/agy-model-map.ts for why `cliModelName` cannot carry the agy slug.\n // An unmapped id would make agy return status:ERROR with exit code 0, so the\n // resolver substitutes a valid slug rather than letting that happen.\n const requested = task.model ?? this.model;\n const model = toAgyModelSlug(requested);\n if (model !== requested) {\n this.adapterLogger.debug('Substituted an agy model slug', { requested, model });\n }\n args.push('--model', model);\n\n if (task.sessionId !== undefined && task.sessionId !== '') {\n args.push('--conversation', task.sessionId);\n }\n\n // #6254: agy's workspace is its STORED project, not the directory it is\n // spawned in — the other arms take the cwd as their tree by default; agy\n // does not. Measured: spawned from this repository with no --add-dir, a\n // voter seat read `packages/nexus-agents/package.json` out of an unrelated\n // checkout on the same machine and reported that file's version, and on\n // governor panels it abstained \"no repository or accessible sandbox was\n // provided\". The task's `workDir` (the same option the claude adapter\n // honours) wins; otherwise the process cwd, which is what the subprocess\n // inherits and what the voter prompt names.\n const workDir = task.options?.['workDir'];\n args.push('--add-dir', typeof workDir === 'string' && workDir !== '' ? workDir : process.cwd());\n\n // #6277: agy's own print-mode wait defaults to 5m0s regardless of the\n // budget the caller gave us. Measured on the #6260 governor panels: a\n // contrarian seat with a 600 s budget hit agy's 5-minute default, agy\n // exited 0 with {\"status\":\"SUCCESS\",\"response\":\"\"}, and the vote path\n // read the empty answer as a parse failure for the rest of the budget.\n // Derive the CLI's wait from the task timeout, a little below the guard\n // so agy's own timeout fires first and its stderr is readable.\n args.push(...agyPrintTimeoutArgs(task.timeoutMs));\n\n // agy has no system-prompt flag. The old CLI's `--policy <file>` preserved\n // system-role framing (#1886); agy offers only `--agent`, which selects a\n // preconfigured agent rather than accepting inline instructions. So the\n // system prompt is prepended to the user content — a deliberate downgrade\n // in framing fidelity, recorded here so it is not mistaken for an\n // oversight. No temp file is written, which also removes the tempdir-leak\n // surface the old path had.\n const content =\n task.systemPrompt !== undefined && task.systemPrompt !== ''\n ? `${task.systemPrompt}\\n\\n${task.content}`\n : task.content;\n\n // agy reads text stdin in print mode when no prompt flag is present.\n // Explicit --print (even with an empty value) suppresses that stdin read.\n // Keep large artifact prompts out of argv's per-argument limit (#7106).\n return { command: this.binaryName, args, stdin: content };\n }\n\n private checkCircuitBreaker(): CliError | null {\n if (this.circuitBreaker === null) {\n return null;\n }\n if (this.circuitBreaker.getState() === 'open') {\n return createCircuitOpenError('gemini');\n }\n return null;\n }\n\n private buildExecutionOptions(\n taskContent: string,\n options?: ExecutionOptions\n ): ResolvedExecutionOptions {\n const complexity = estimateTaskComplexity(taskContent);\n const timeoutMs = options?.timeoutMs ?? getTimeoutForTask(this.name, complexity);\n\n return {\n timeoutMs,\n allowRetry: options?.allowRetry ?? true,\n maxRetries: options?.maxRetries ?? this.maxRetries,\n trackUsage: options?.trackUsage ?? true,\n onProgress: options?.onProgress,\n };\n }\n\n private buildExecutionResult(\n result: Result<{ response: CliResponse; retryCount: number }, CliError>,\n startTime: number,\n complexity: TaskComplexity\n ): Result<GeminiExecutionResult, CliError> {\n const totalDurationMs = getTimeProvider().now() - startTime;\n const circuitState = this.circuitBreaker?.getState() ?? 'closed';\n\n if (result.ok) {\n this.circuitBreaker?.recordSuccess();\n return ok({\n response: result.value.response,\n retryCount: result.value.retryCount,\n totalDurationMs,\n complexity,\n circuitState,\n });\n }\n\n return err(result.error);\n }\n\n private async executeWithRetryTracking(\n task: CliTask,\n options: ResolvedExecutionOptions\n ): Promise<Result<{ response: CliResponse; retryCount: number }, CliError>> {\n return executeCliRetryLoop(() => this.executeTask(task, options), {\n maxRetries: options.maxRetries,\n allowRetry: this.shouldOuterRetry(options),\n baseDelayMs: this.baseDelayMs,\n maxDelayMs: this.maxDelayMs,\n circuitBreaker: this.circuitBreaker,\n cli: this.name,\n logger: this.adapterLogger,\n });\n }\n}\n\n/** Creates a Gemini CLI adapter with reliability features. */\nexport function createGeminiAdapter(options?: GeminiConfig): GeminiCliAdapter {\n return new GeminiCliAdapter(options);\n}\n","/**\n * nexus-agents/cli-adapters - Codex CLI Adapter\n *\n * Subprocess-based adapter for Codex CLI.\n * Extends SubprocessCliAdapter to reuse retry logic, health checks,\n * version detection, and capacity tracking.\n *\n * (Source: cli-project_plan.md v2.1.0)\n * (Source: Issue #1140 — Migrated to SubprocessCliAdapter base class)\n *\n * SECURITY: All spawn() calls use array-based args without shell: true.\n * User task content is passed through stdin (no shell interpolation).\n */\n\nimport { writeFileSync, rmSync } from 'node:fs';\nimport { nexusMkdtempSync } from '../../config/nexus-tmp-dir.js';\nimport { join } from 'node:path';\nimport type { ICliResponseParser, CliTask, ModelInfo, CliName, CliError } from '../types.js';\nimport { codexSandboxPreflight, createCodexSandboxGuard } from '../codex-sandbox-preflight.js';\nimport { SubprocessCliAdapter, type CommandConfig } from '../subprocess-adapter.js';\nimport { CodexResponseParser } from '../parsers/codex-parser.js';\nimport type { CliModelInfo } from '../types-capability.js';\nimport { listModelsForCli } from '../../config/models-dev-by-vendor.js';\nimport { isReadOnlyAnalysis } from '../access-mode.js';\nimport {\n CODEX_SYSTEM_CONFIG_FILES,\n codexMcpDisableArgs,\n scanCodexMcpServers,\n} from '../codex-mcp-isolation.js';\nimport { mcpScanRefusal, scanOrThrow, subprocessScanContext } from '../mcp-config-scan.js';\nimport {\n CODEX_LEGACY_DEFAULTS,\n type CodexAdapterOptions,\n toCodexModelSlug,\n} from './codex-adapter-helpers.js';\nimport {\n getDefaultModelForCli,\n getCliModelName,\n buildModelInfo,\n} from '../../config/model-config-helpers.js';\n\n// Re-export CLI-specific helpers for backward compatibility\nexport { createCodexError, normalizeCodexResponse, delay } from './codex-adapter-helpers.js';\n\n/**\n * Codex CLI adapter using subprocess transport.\n *\n * Extends SubprocessCliAdapter which provides:\n * - Retry logic with exponential backoff\n * - Health checks with version compatibility\n * - Capacity tracking\n * - Subprocess spawn with timeout handling\n */\n/**\n * The codex sandbox every `codex exec` runs under (#6754). Read-only analysis\n * mode needs nothing beyond it: `-s read-only` already refuses writes and\n * network, so this adapter enforces the mode on every task, not only on the\n * ones that ask. Named so a change to the default is a visible change to the\n * mode's guarantee.\n */\nconst CODEX_EXEC_SANDBOX = 'read-only';\n\nexport class CodexCliAdapter extends SubprocessCliAdapter {\n readonly name: CliName = 'codex';\n override readonly enforcesReadOnlyAnalysis = true;\n protected readonly parser: ICliResponseParser = new CodexResponseParser();\n\n private readonly model: string;\n private sandboxArgs: readonly string[] = [];\n private readonly sandboxRefusal: () => Promise<CliError | undefined>;\n\n constructor(options?: CodexAdapterOptions) {\n super(options?.logger);\n this.model = options?.model ?? getCliModelName(getDefaultModelForCli('codex'));\n this.sandboxRefusal = createCodexSandboxGuard(\n options?.sandboxProbe ?? codexSandboxPreflight,\n this.logger,\n (args) => {\n this.sandboxArgs = args;\n },\n options?.platform\n );\n }\n\n /**\n * The adapter always executes under read-only, including default-mode tasks.\n * A read-only analysis task is also refused when codex's MCP config cannot\n * be listed (#6970): its servers run outside the sandbox.\n */\n protected override async accessModeRefusal(task: CliTask): Promise<CliError | undefined> {\n const base = await super.accessModeRefusal(task);\n if (base !== undefined) return base;\n if (isReadOnlyAnalysis(task)) {\n const scan = scanCodexMcpServers(\n subprocessScanContext(this.name, task),\n this.codexSystemConfigFiles()\n );\n if (!scan.ok) return mcpScanRefusal(this.name, scan.error);\n }\n return this.sandboxRefusal();\n }\n\n /**\n * The system config files the MCP scan reads (#6970). A seam so tests can\n * keep the host's real `/etc/codex` out of the scan.\n */\n protected codexSystemConfigFiles(): readonly string[] {\n return CODEX_SYSTEM_CONFIG_FILES;\n }\n\n /**\n * `-c mcp_servers.<name>.enabled=false` for every MCP server codex would\n * load (#6970). Measured live on codex-cli 0.160.0: `-s read-only` does not\n * cover MCP servers, which start outside the sandbox, and the nexus-agents\n * server wrote `.gitignore` and `.nexus-agents/` into the tree. Throws when\n * the config cannot be listed, so the task never spawns with a server it\n * could not see.\n */\n private readOnlyMcpArgs(task: CliTask): readonly string[] {\n if (!isReadOnlyAnalysis(task)) return [];\n const servers = scanOrThrow(\n this.name,\n scanCodexMcpServers(subprocessScanContext(this.name, task), this.codexSystemConfigFiles())\n );\n return codexMcpDisableArgs(servers);\n }\n\n /** Key-free model enumeration via the models.dev snapshot (#3405). */\n listModels(): Promise<readonly CliModelInfo[]> {\n return Promise.resolve(listModelsForCli(this.name));\n }\n\n /**\n * Gets Codex model information.\n * Resolves from canonical registry when possible, falls back to legacy lookup.\n */\n getModelInfo(): ModelInfo {\n const fromRegistry = buildModelInfo('codex', this.model);\n if (fromRegistry !== undefined) return fromRegistry;\n return {\n id: this.model,\n name: CODEX_LEGACY_DEFAULTS.displayNames[this.model] ?? this.model,\n contextWindow: CODEX_LEGACY_DEFAULTS.contextWindow,\n maxOutput: CODEX_LEGACY_DEFAULTS.maxOutput,\n costPerMillionInput:\n CODEX_LEGACY_DEFAULTS.inputCosts[this.model] ?? CODEX_LEGACY_DEFAULTS.inputCost,\n costPerMillionOutput:\n CODEX_LEGACY_DEFAULTS.outputCosts[this.model] ?? CODEX_LEGACY_DEFAULTS.outputCost,\n };\n }\n\n /**\n * Gets CLI command and arguments for execution.\n * Task content is read from stdin via `codex exec -` to avoid argv size limits.\n */\n protected getCommand(task: CliTask): CommandConfig {\n const args: string[] = ['exec'];\n\n // Add JSON output\n args.push('--json');\n\n // Add model only if specified (use CLI default otherwise). task.model is\n // the canonical registry id, which codex rejects — translate it (#5091).\n const model = task.model ?? this.model;\n if (model !== '') {\n args.push('-m', toCodexModelSlug(model, this.logger));\n }\n\n // The awaited preflight selects the backend; every task stays read-only.\n args.push('-s', CODEX_EXEC_SANDBOX, ...this.sandboxArgs, ...this.readOnlyMcpArgs(task));\n\n // Skip git repo check for standalone prompts\n args.push('--skip-git-repo-check');\n\n // Honor systemPrompt via codex's `model_instructions_file` config key\n // (per openai/codex#11588 — closed with this workaround). We materialize\n // the prompt into a tempfile, pass it via `-c`, and clean up on exit.\n let cleanup: (() => void) | undefined;\n if (task.systemPrompt !== undefined && task.systemPrompt !== '') {\n const dir = nexusMkdtempSync('nexus-codex-sysprompt-');\n const file = join(dir, 'instructions.md');\n writeFileSync(file, task.systemPrompt, { encoding: 'utf8', mode: 0o600 });\n args.push('-c', `model_instructions_file=${file}`);\n cleanup = (): void => {\n // Recursive rm so we drop the parent tempdir, not just the file\n // inside it. Pre-fix every codex call with a systemPrompt leaked\n // one empty `/tmp/nexus-codex-sysprompt-XXXXXX` dir until the OS\n // reaper ran — exhausting inodes on long-running MCP daemons.\n try {\n rmSync(dir, { recursive: true, force: true });\n } catch {\n // best-effort; tempdir auto-cleanup will eventually reap it\n }\n };\n }\n\n // `codex exec -` reads stdin, avoiding Linux's per-argument size limit (#7106).\n args.push('-');\n\n return {\n command: 'codex',\n args,\n stdin: task.content,\n ...(cleanup === undefined ? {} : { cleanup }),\n };\n }\n}\n","/** Model-free, process-cached check of the sandbox used by Codex seats (#6841). */\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { getErrorMessage } from '../core/index.js';\nimport { CLI_SUBPROCESS_TIMEOUTS, resolveClassGuardMs } from '../config/timeouts.js';\nimport { UNVERIFIABLE_STDERR_RE } from '../cli/voter-unverifiable.js';\nimport { codexPlatformSandboxArgs } from './adapters/codex-adapter-helpers.js';\nimport { sanitizeOutput } from '../security/output-sanitizer.js';\nimport type { ILogger } from '../core/logger.js';\nimport type { CliError } from './types.js';\nimport { createHostUnavailableCliError } from './cli-error-helpers.js';\n\n/** Unknown is unmeasured, never evidence that the sandbox works. */\nexport type CodexSandboxPreflightResult = (\n { readonly status: 'ok' } | { readonly status: 'broken' | 'unknown'; readonly reason: string }\n) & { readonly sandboxArgs?: readonly string[] };\n\n/** Runner seam: no model call, shell interpolation, or inherited stdin. */\nexport type CodexSandboxProbeExec = (\n command: string,\n args: readonly string[],\n timeoutMs: number\n) => Promise<{ readonly exitCode: number | null; readonly stderr: string }>;\n\nconst execFileAsync = promisify(execFile);\n\nconst defaultExec: CodexSandboxProbeExec = async (command, args, timeoutMs) => {\n try {\n const execution = execFileAsync(command, [...args], {\n encoding: 'utf8',\n timeout: timeoutMs,\n killSignal: 'SIGKILL',\n });\n // execFile pipes stdin; close it so the probe cannot wait for input.\n execution.child.stdin?.end();\n await execution;\n return { exitCode: 0, stderr: '' };\n } catch (error: unknown) {\n const failure = error as { code?: unknown; stderr?: unknown };\n return {\n exitCode: typeof failure.code === 'number' ? failure.code : null,\n stderr:\n typeof failure.stderr === 'string' && failure.stderr.trim() !== ''\n ? failure.stderr\n : getErrorMessage(error),\n };\n }\n};\n\nasync function probeCandidate(\n exec: CodexSandboxProbeExec,\n sandboxArgs: readonly string[]\n): Promise<CodexSandboxPreflightResult> {\n try {\n const timeoutMs = Math.min(\n CLI_SUBPROCESS_TIMEOUTS.statusProbeMs,\n resolveClassGuardMs('interactive')\n );\n const args = ['sandbox', '-c', 'sandbox_mode=\"read-only\"', ...sandboxArgs, '--', 'true'];\n const { exitCode, stderr } = await exec('codex', args, timeoutMs);\n if (exitCode === 0) return { status: 'ok', sandboxArgs };\n const lines = sanitizeOutput(stderr)\n .split('\\n')\n .map((line) => line.trim());\n const cause = lines.find((line) => UNVERIFIABLE_STDERR_RE.test(line));\n const status = exitCode !== null && cause !== undefined ? 'broken' : 'unknown';\n const detail = cause ?? lines.find((line) => line !== '') ?? 'no diagnostic output';\n const exit = exitCode === null ? 'did not complete' : `exit ${String(exitCode)}`;\n return { status, reason: `codex sandbox ${exit}: ${detail}` };\n } catch (error: unknown) {\n return { status: 'unknown', reason: sanitizeOutput(getErrorMessage(error)) };\n }\n}\n\n/**\n * First success wins, even after a recognized failure. Without any success,\n * ANY completed numeric failure with a recognized stderr line means broken;\n * a null exit or runner exception alone is unmeasured. Keep the first broken\n * cause rather than letting a later timeout hide it. Candidates are nonempty.\n */\nasync function probe(\n exec: CodexSandboxProbeExec,\n platform: NodeJS.Platform\n): Promise<CodexSandboxPreflightResult> {\n const candidates = platform === 'linux' ? [[], codexPlatformSandboxArgs(platform)] : [[]];\n let failure: { status: 'broken' | 'unknown'; reason: string } = {\n status: 'unknown',\n reason: 'no sandbox candidates measured',\n };\n let measured = false;\n for (const sandboxArgs of candidates) {\n const result = await probeCandidate(exec, sandboxArgs);\n if (result.status === 'ok') return result;\n if (!measured || (failure.status !== 'broken' && result.status === 'broken')) {\n failure = result;\n }\n measured = true;\n }\n // Unknown uses the modern default, not the deprecated flag that panics on\n // >=0.156.1. Older Codex gets legacy whenever that candidate actually passes;\n // an unsupported probe cannot establish that legacy would work either.\n return { ...failure, sandboxArgs: [] };\n}\n\n/**\n * A memoized promise with an injected runner. Concurrent callers share the\n * pending probe; all verdicts, including unknown, are cached. Seats proceed\n * on unknown under the plain read-only sandbox\n * and log the reason; a recognized sandbox failure refuses execution.\n */\nexport function createCodexSandboxPreflight(\n exec: CodexSandboxProbeExec,\n platform: NodeJS.Platform = process.platform\n): () => Promise<CodexSandboxPreflightResult> {\n let cached: Promise<CodexSandboxPreflightResult> | undefined;\n return () => (cached ??= probe(exec, platform));\n}\n\n/** The single default probe shared by doctor and every Codex seat/arm in this process. */\nexport const codexSandboxPreflight = createCodexSandboxPreflight(defaultExec);\n\n/** Refuse before initialization; retain unknown provenance once per adapter. */\nexport function createCodexSandboxGuard(\n preflight: () => CodexSandboxPreflightResult | Promise<CodexSandboxPreflightResult>,\n logger: ILogger,\n onSandboxArgs: (args: readonly string[]) => void,\n platform: NodeJS.Platform = process.platform\n): () => Promise<CliError | undefined> {\n let cached: Promise<CodexSandboxPreflightResult> | undefined;\n return async () => {\n // The async wrapper turns a synchronous throw into a rejection, and the\n // catch turns any rejection into unknown: a memoized rejection would make\n // every later call on this adapter throw instead of proceeding.\n cached ??= (async () => preflight())()\n .catch((error: unknown): CodexSandboxPreflightResult => ({\n status: 'unknown',\n reason: sanitizeOutput(getErrorMessage(error)),\n // Plain, as for any unknown: the legacy flag panics on codex-cli >= 0.156.1.\n sandboxArgs: [],\n }))\n .then((result) => {\n // Old injected Result | Promise<Result> shapes omit sandboxArgs. Keep\n // their previous platform behavior; explicit [] always means plain.\n const sandboxArgs = result.sandboxArgs ?? codexPlatformSandboxArgs(platform);\n onSandboxArgs(sandboxArgs);\n if (result.status === 'unknown') {\n logger.warn('Codex sandbox preflight unknown; proceeding with read-only sandbox', {\n cli: 'codex',\n reason: result.reason,\n sandboxArgs,\n });\n }\n return result;\n });\n const result = await cached;\n return result.status === 'broken'\n ? createHostUnavailableCliError(\n `Codex read-only sandbox unavailable: ${result.reason} (checked once per process; restart the MCP server after fixing the host)`,\n 'codex'\n )\n : undefined;\n };\n}\n\n/** Read-only root, fresh PID namespace and session, with network retained. */\nexport const BWRAP_READ_ONLY_ARGS = [\n '--ro-bind',\n '/',\n '/',\n '--dev',\n '/dev',\n '--proc',\n '/proc',\n '--unshare-pid',\n '--die-with-parent',\n '--new-session',\n] as const;\n\n/** Direct bwrap capability measurement, sharing the Codex preflight runner (#7011). */\nexport type BwrapIsolation = {\n readonly mode: 'os-sandbox' | 'best-effort';\n readonly reason?: string;\n};\n\n/** Cache the actual profile's success or failure, including concurrent callers. */\nexport function createBwrapPreflight(\n exec: CodexSandboxProbeExec = defaultExec,\n platform: NodeJS.Platform = process.platform\n): () => Promise<BwrapIsolation> {\n let cached: Promise<BwrapIsolation> | undefined;\n return () =>\n (cached ??= (async (): Promise<BwrapIsolation> => {\n if (platform !== 'linux') return { mode: 'best-effort', reason: 'bwrap requires Linux' };\n try {\n const result = await exec(\n 'bwrap',\n [...BWRAP_READ_ONLY_ARGS, '--', 'true'],\n Math.min(CLI_SUBPROCESS_TIMEOUTS.statusProbeMs, resolveClassGuardMs('interactive'))\n );\n if (result.exitCode === 0) return { mode: 'os-sandbox' };\n return {\n mode: 'best-effort',\n reason: `bwrap probe failed: ${sanitizeOutput(result.stderr) || 'no diagnostic output'}`,\n };\n } catch (error: unknown) {\n return {\n mode: 'best-effort',\n reason: `bwrap probe failed: ${sanitizeOutput(getErrorMessage(error))}`,\n };\n }\n })());\n}\n","/**\n * A seat that could not read the artifact is `unverifiable` (#6094).\n *\n * Design panel on #6068 (option C, 6 of 6). Before this, a voter whose\n * sandboxed shell failed — `bwrap: loopback: Failed RTM_NEWADDR` on a\n * userns-restricted host — returned a parsed JSON vote and was recorded as an\n * ordinary `abstain` with `source: 'llm'`. The retry path never saw it, the\n * tally could not tell \"read it and abstained\" from \"never saw it\", and one\n * seat voted APPROVE on the proposal text after failing to read\n * (`vote-1789058788915-6lfrbuq`). A record that cannot represent absence\n * launders a blind seat as a considered one — the Mission's p1 class.\n *\n * Classification order: the structured signal first (stderr the CLI transport\n * captured while serving the completion), the reasoning text as a fallback.\n * Regex over prose both misses and false-positives, which is why it is the\n * fallback and why its constant is named — the six real ledger entries in\n * `voter-unverifiable.test.ts` are its regression set.\n *\n * @module cli/voter-unverifiable\n */\n\nimport type { AgentVoteResult, UnverifiableSignal } from './vote-types.js';\n\n/**\n * The structured signal: a sandbox / shell failure on the CLI's stderr. The\n * bubblewrap and landlock strings are what codex emits on a host where\n * `apparmor_restrict_unprivileged_userns=1` (Ubuntu 24.04+ default, #6093).\n */\nexport const UNVERIFIABLE_STDERR_RE =\n /\\bbwrap: |RTM_NEWADDR|filesystem-restricted execution requires bubblewrap|\\b(?:sandbox|landlock)\\b[^\\n]*\\b(?:denied|failed|not permitted)\\b/i;\n\n/**\n * The fallback's error strings: the seat's own reasoning quotes a failed read.\n *\n * Anchored on the concrete phrases the six real ledger entries used. It\n * deliberately does NOT match a bare \"could not read\" — a seat that read the\n * artifact may say a comment \"could not be read easily\" and still have judged\n * the code. Since #6104 a match here is necessary but not sufficient: a seat\n * that quotes the error and then asserts a successful read (`RECOVERY_PHRASE_RE`\n * or `FILE_LINE_CITATION_RE`) keeps its vote. The `UNVERIFIABLE:` prefix the\n * voter prompt asks for is its own rule, `UNVERIFIABLE_PREFIX_RE`, and needs\n * no error string.\n */\nexport const UNVERIFIABLE_REASONING_RE =\n /\\bbwrap: |RTM_NEWADDR|\\b(?:repository|source|shell) (?:reads?|access|execution|inspection) failed\\b|\\bcould not (?:read|inspect) the artifact\\b/i;\n\n/**\n * The prefix `voter-prompts.ts` asks a blind seat to BEGIN its reasoning with.\n * Anchored at the start: a seat that mentions the word mid-sentence is quoting\n * the instruction, not obeying it.\n */\nconst UNVERIFIABLE_PREFIX_RE = /^\\s*UNVERIFIABLE:/i;\n\n/**\n * A `path/file.ext:LINE` citation — the location form the PR-review addendum\n * in `voter-prompts.ts` asks findings to use. A seat that cites a line read\n * the file. Requires a dotted extension before the colon so a clock time, a\n * ratio or a bare SHA does not count.\n */\nconst FILE_LINE_CITATION_RE = /(?:^|[\\s(`'\"])[\\w./-]*[\\w-]+\\.[a-z][a-z\\d]{0,5}:\\d+\\b/i;\n\n/**\n * The recovery phrases a seat writes when a first read failed and a later one\n * did not (#6104). ONE named list: extend it here, never inline. The two\n * strings the #6101 adversarial review executed are the first two rows.\n * Module-private, like the other two guards: behaviour is asserted through\n * `classifyUnverifiable`, so the regexes can change without a consumer.\n */\nconst RECOVERY_PHRASE_RE =\n /\\b(?:retry|second attempt|subsequent attempt|re-?run) succeeded\\b|\\bthen read\\b|\\bwas able to read\\b/i;\n\n/** Which sub-rule of the reasoning fallback fired; reported for the debug log. */\nexport type UnverifiableReasoningRule = 'prefix' | 'error_without_recovery';\n\n/** Evidence available after one completion: the transport's stderr, the parsed reasoning. */\nexport interface UnverifiableEvidence {\n readonly cliStderr?: string | undefined;\n readonly reasoning: string;\n}\n\n/** True when the reasoning asserts a successful read: a recovery phrase or a file:line citation. */\nfunction assertsSuccessfulRead(reasoning: string): boolean {\n return RECOVERY_PHRASE_RE.test(reasoning) || FILE_LINE_CITATION_RE.test(reasoning);\n}\n\n/**\n * Classify a parsed vote as unverifiable, naming which evidence did it, or\n * `undefined` when the seat gave no sign of having failed to read.\n *\n * The stderr signal is primary and unconditional. The reasoning fallback\n * fires on the `UNVERIFIABLE:` prefix, or on an error string only when the\n * reasoning does not also assert a successful read (#6104) — a seat that\n * quotes `bwrap:` and then says the retry succeeded read the artifact, and\n * discarding it was a measured false-positive class. `onReasoningRule`\n * receives the sub-rule that fired so the caller can log it.\n *\n * The empty case is named: no stderr and clean reasoning is a seat that read\n * the artifact, and its decision stands.\n */\nexport function classifyUnverifiable(\n evidence: UnverifiableEvidence,\n onReasoningRule?: (rule: UnverifiableReasoningRule) => void\n): UnverifiableSignal | undefined {\n const stderr = evidence.cliStderr ?? '';\n if (stderr !== '' && UNVERIFIABLE_STDERR_RE.test(stderr)) return 'stderr';\n const { reasoning } = evidence;\n if (UNVERIFIABLE_PREFIX_RE.test(reasoning)) {\n onReasoningRule?.('prefix');\n return 'reasoning';\n }\n if (UNVERIFIABLE_REASONING_RE.test(reasoning) && !assertsSuccessfulRead(reasoning)) {\n onReasoningRule?.('error_without_recovery');\n return 'reasoning';\n }\n return undefined;\n}\n\n/**\n * Re-record a parsed vote as an unverifiable seat.\n *\n * The decision the model returned is DISCARDED (the caller logs it): the seat\n * never carries approve/reject, conditions, or a `selectedOption` — a blind seat\n * cannot have chosen. Confidence is 0 because there is no verdict to be\n * confident in. Everything that IS real provenance — the reasoning text, the\n * model, the CLI, the token counts — is kept.\n */\nexport function markUnverifiable(\n result: AgentVoteResult,\n signal: UnverifiableSignal\n): AgentVoteResult {\n const { selectedOption: _discarded, ...rest } = result;\n const { conditions: _conditions, ...vote } = result.vote;\n return {\n ...rest,\n source: 'unverifiable',\n unverifiableSignal: signal,\n vote: { ...vote, decision: 'abstain', confidence: 0 },\n };\n}\n\n/**\n * An absent seat: one that errored, or one that answered without having read\n * the artifact. Both are absences, not judgments — the per-role retry\n * relaunches them and `absolute_quorum` voids on them alike.\n */\nexport function isAbsentSeat(v: Pick<AgentVoteResult, 'source'>): boolean {\n return v.source === 'error' || v.source === 'unverifiable';\n}\n","/**\n * nexus-agents/cli-adapters - Codex CLI Adapter Helpers\n *\n * CLI-specific helper functions for Codex subprocess adapter.\n * Model info lookups consolidated into config/model-config-helpers.ts (#886).\n */\n\nimport type { BaseAdapterOptions, CliError, CliName, TokenUsage, CliResponse } from '../types.js';\nimport { createCliError as sharedCreateCliError } from '../cli-error-helpers.js';\nimport type { ILogger } from '../../core/logger.js';\nimport { resolveCliModelName } from '../../config/model-config-helpers.js';\nimport type { CodexSandboxPreflightResult } from '../codex-sandbox-preflight.js';\n\n// -----------------------------------------------------------------------------\n// Legacy Fallback Defaults (for non-canonical models)\n// -----------------------------------------------------------------------------\n\n/** Legacy fallback values for Codex models not in the canonical registry. */\nexport const CODEX_LEGACY_DEFAULTS = {\n displayNames: {\n o3: 'O3',\n 'o3-mini': 'O3 Mini',\n 'o4-mini': 'O4 Mini',\n } as Readonly<Record<string, string>>,\n inputCosts: {\n o3: 10.0,\n 'o3-mini': 1.1,\n 'o4-mini': 1.1,\n } as Readonly<Record<string, number>>,\n outputCosts: {\n o3: 40.0,\n 'o3-mini': 4.4,\n 'o4-mini': 4.4,\n } as Readonly<Record<string, number>>,\n contextWindow: 400_000,\n maxOutput: 100_000,\n inputCost: 1.1,\n outputCost: 4.4,\n} as const;\n\n// -----------------------------------------------------------------------------\n// Sandbox backend selection (#6093)\n// -----------------------------------------------------------------------------\n\n/** Options accepted by both codex transports (subprocess and MCP). */\nexport interface CodexAdapterOptions extends BaseAdapterOptions {\n /**\n * Injectable model-free sandbox preflight; the default is shared process-wide.\n * A synchronous probe (the 8.115.0 shape) is still accepted (#6846).\n * Results without sandboxArgs retain the previous platform arguments:\n * legacy landlock on Linux, plain elsewhere. Explicit [] selects plain.\n */\n readonly sandboxProbe?: () => CodexSandboxPreflightResult | Promise<CodexSandboxPreflightResult>;\n /**\n * Platform for compatibility arguments when an injected result omits them.\n * Defaults to `process.platform`. Explicit sandboxArgs override this option;\n * the shared default probe always measures the actual host platform.\n */\n readonly platform?: NodeJS.Platform;\n}\n\n/**\n * The `-c key=value` override that switches codex's Linux sandbox from bwrap\n * to the legacy landlock backend. Spelled exactly as `codex features list`\n * names it (`use_legacy_landlock`, flagged deprecated on codex-cli 0.153.4):\n * `-c` accepts any key, so a misspelling would be silently ignored.\n */\nexport const CODEX_LEGACY_LANDLOCK_CONFIG = 'features.use_legacy_landlock=true';\n\n/**\n * Legacy candidate / compatibility argv: `['-c', CODEX_LEGACY_LANDLOCK_CONFIG]`\n * on Linux, nothing elsewhere. Default seats use preflight-selected args.\n *\n * Why (#6093, measured on codex-cli 0.153.4 / bwrap 0.9.0): on hosts with\n * `kernel.apparmor_restrict_unprivileged_userns=1` (the Ubuntu 24.04+ default)\n * every bwrap-backed sandbox mode — `read-only`, `workspace-write`, network\n * off — dies with `bwrap: loopback: Failed RTM_NEWADDR: Operation not\n * permitted` before codex reads a single file, so the two codex voter seats\n * abstained with \"repository inspection failed\" or voted on the proposal\n * text alone. With the legacy landlock backend reads work and writes are\n * still refused (`Permission denied`). The read scope is read-only-all-disk,\n * the same scope the read-only bwrap profile already granted, so this widens\n * nothing: a seat could always read dotfiles and echo them into its\n * reasoning. The host-level alternative is\n * `kernel.apparmor_restrict_unprivileged_userns=0` or an AppArmor profile for\n * bwrap; this flag makes the seats work without host changes.\n *\n * Used by the ordered preflight and the guard's old-result compatibility\n * fallback so the platform gate exists once. Both subcommands\n * accept `-c` after the subcommand name (verified with `--help`, which rejects\n * an unknown flag in that position with exit 2).\n */\nexport function codexPlatformSandboxArgs(\n platform: NodeJS.Platform = process.platform\n): readonly string[] {\n return platform === 'linux' ? ['-c', CODEX_LEGACY_LANDLOCK_CONFIG] : [];\n}\n\n// -----------------------------------------------------------------------------\n// Error Handling\n// -----------------------------------------------------------------------------\n\n/**\n * Creates a CLI error with the canonical retryable-flag logic.\n * Kept as an alias under this name for backward compatibility with callers\n * that imported `createCodexError` before the helper was consolidated in\n * `cli-error-helpers.ts` (#2181). Prefer `createCliError` from the shared\n * helper in new code.\n */\nexport function createCodexError(\n code: CliError['code'],\n message: string,\n cli: CliName,\n cause?: Error\n): CliError {\n return sharedCreateCliError(code, message, cli, cause);\n}\n\n// -----------------------------------------------------------------------------\n// Response Normalization\n// -----------------------------------------------------------------------------\n\n/** Normalizes CLI response to common format. */\nexport function normalizeCodexResponse(\n text: string,\n usage?: TokenUsage,\n extra?: Partial<CliResponse>\n): CliResponse {\n return {\n text,\n ...(usage !== undefined && { usage }),\n ...extra,\n };\n}\n\n// Re-export from canonical source for backward compatibility\nexport { delay } from '../../utils/async-utils.js';\n\n/**\n * Translate a model identifier to the slug the `codex` binary accepts (#5091).\n *\n * `task.model` arrives as the canonical registry id (`codex-5.3`), which codex\n * rejects; the registry's `cliModelName` (`gpt-5.4`) is what `-m` and the MCP\n * `model` argument want. Shared by the subprocess and MCP transports so the\n * translation exists once.\n *\n * Unknown model: passed through verbatim with a warning, the same fail-open\n * choice `claude-adapter.ts` (`MODEL_TO_CLI_ALIAS[m] ?? m`) and\n * `opencode-adapter.ts` (`resolveOpenCodeModel`) make. A caller pinning a slug\n * the registry has not caught up with (codex ships new ones between releases)\n * must still be able to run it, and codex rejects a bad `-m` with a non-zero\n * exit, so the failure stays visible — unlike agy, whose exit-0 error is why\n * `toAgyModelSlug` substitutes a default instead.\n */\nexport function toCodexModelSlug(model: string, logger: ILogger): string {\n const slug = resolveCliModelName('codex', model);\n if (slug === undefined) {\n logger.warn('Model is not in the model registry for codex; passing it to codex unchanged', {\n model,\n });\n return model;\n }\n return slug;\n}\n","/**\n * nexus-agents/cli-adapters - Codex CLI Response Parser\n *\n * Defensive parser for Codex CLI NDJSON output.\n * Handles version 0.7x.x output format.\n *\n * (Source: cli-project_plan.md v2.1.0)\n * (Source: docs/research/cli-integration-architecture.md)\n */\n\nimport type { ICliResponseParser, TokenUsage } from '../types.js';\nimport { asRecord, extractNumberField } from '../../utils/type-coercion.js';\nimport { createLogger } from '../../core/index.js';\n\nconst logger = createLogger({ component: 'codex-parser' });\n\n/**\n * Codex CLI NDJSON event types.\n */\nexport type CodexEventType =\n 'thread.started' | 'turn.started' | 'item.completed' | 'turn.completed';\n\n/**\n * Base Codex event structure.\n */\nexport interface CodexEvent {\n readonly type: CodexEventType;\n}\n\n/**\n * Thread started event.\n */\nexport interface CodexThreadStarted extends CodexEvent {\n readonly type: 'thread.started';\n readonly thread_id: string;\n}\n\n/**\n * Item completed event (contains response or reasoning).\n */\nexport interface CodexItemCompleted extends CodexEvent {\n readonly type: 'item.completed';\n readonly item: {\n readonly id: string;\n readonly type: string;\n readonly text: string;\n };\n}\n\n/**\n * Turn completed event (contains usage).\n */\nexport interface CodexTurnCompleted extends CodexEvent {\n readonly type: 'turn.completed';\n readonly usage?: {\n readonly input_tokens: number;\n readonly cached_input_tokens?: number;\n readonly output_tokens: number;\n };\n}\n\n/**\n * Aggregated Codex response from NDJSON stream.\n */\nexport interface CodexCliResponse {\n readonly threadId?: string;\n readonly messages: readonly string[];\n readonly reasoning: readonly string[];\n readonly usage?: TokenUsage;\n}\n\n/**\n * Parser for Codex CLI NDJSON output.\n * Implements defensive parsing - processes stream of events.\n */\nexport class CodexResponseParser implements ICliResponseParser<CodexCliResponse> {\n readonly name = 'codex-parser';\n readonly supportedVersionRange = '>=0.70.0 <1.0.0';\n\n /**\n * Parses complete Codex CLI NDJSON stream.\n */\n parse(raw: string): CodexCliResponse | null {\n const lines = raw.trim().split('\\n');\n let threadId: string | undefined;\n const messages: string[] = [];\n const reasoning: string[] = [];\n let usage: TokenUsage | undefined;\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n const failed = this.processLine(\n line,\n messages,\n reasoning,\n (id) => (threadId = id),\n (u) => (usage = u)\n );\n if (failed) return null;\n }\n\n if (messages.length === 0 && reasoning.length === 0) {\n return null;\n }\n\n return {\n messages,\n reasoning,\n ...(threadId !== undefined && { threadId }),\n ...(usage !== undefined && { usage }),\n };\n }\n\n /**\n * Processes a single NDJSON line; returns true for a terminal failed turn.\n */\n private processLine(\n line: string,\n messages: string[],\n reasoning: string[],\n setThreadId: (id: string) => void,\n setUsage: (usage: TokenUsage) => void\n ): boolean {\n try {\n const event: unknown = JSON.parse(line);\n const record = asRecord(event);\n if (record === null) return false;\n\n const eventType = record.type;\n // A completed message may precede a failed turn. The captured CLI error\n // ends with turn.failed; an earlier message cannot turn it into success.\n // Ordinary error events can be recoverable, so only this terminal event\n // denies the result (#7073).\n if (eventType === 'turn.failed') return true;\n\n if (eventType === 'thread.started') {\n const tid = record.thread_id;\n if (typeof tid === 'string') setThreadId(tid);\n } else if (eventType === 'item.completed') {\n this.processItemCompleted(record, messages, reasoning);\n } else if (eventType === 'turn.completed') {\n const usage = this.extractUsageFromEvent(record);\n if (usage !== null) setUsage(usage);\n }\n } catch {\n // Skip malformed NDJSON lines\n logger.debug('Skipped malformed NDJSON line', { snippet: line.slice(0, 100) });\n }\n return false;\n }\n\n /**\n * Extracts just the response text (most stable field).\n * Concatenates all agent_message items.\n */\n extractResponse(raw: string): string | null {\n const parsed = this.parse(raw);\n if (parsed === null || parsed.messages.length === 0) {\n return null;\n }\n\n return parsed.messages.join('\\n');\n }\n\n /**\n * Returns the terminal failed-turn message, falling back to its error event.\n * A completed turn clears recoverable errors instead of surfacing them.\n */\n extractErrorMessage(raw: string): string | null {\n let errorMessage: string | null = null;\n for (const line of raw.trim().split('\\n')) {\n if (line.trim() === '') continue;\n try {\n const event: unknown = JSON.parse(line);\n const record = asRecord(event);\n if (record === null) continue;\n if (record.type === 'turn.completed') {\n errorMessage = null;\n continue;\n }\n if (record.type !== 'turn.failed' && record.type !== 'error') continue;\n errorMessage = this.errorMessageFromEvent(record) ?? errorMessage;\n if (record.type === 'turn.failed') return errorMessage;\n } catch {\n // Malformed diagnostics cannot supply a terminal error message.\n continue;\n }\n }\n return errorMessage;\n }\n\n /** Validates the message field from a failed turn or error event. */\n private errorMessageFromEvent(record: Record<string, unknown>): string | null {\n const message =\n record.type === 'turn.failed' ? asRecord(record.error)?.message : record.message;\n return typeof message === 'string' && message.trim() !== '' ? message : null;\n }\n\n /**\n * Extracts token usage from NDJSON stream.\n */\n extractUsage(raw: string): TokenUsage | null {\n const lines = raw.trim().split('\\n');\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n\n try {\n const event: unknown = JSON.parse(line);\n const record = asRecord(event);\n if (record === null) continue;\n\n if (record.type === 'turn.completed') {\n return this.extractUsageFromEvent(record);\n }\n } catch {\n logger.debug('Skipped malformed NDJSON line', { snippet: line.slice(0, 100) });\n continue;\n }\n }\n\n return null;\n }\n\n /**\n * Extracts session ID (thread_id) for resumption.\n */\n extractSessionId(raw: string): string | null {\n const lines = raw.trim().split('\\n');\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n\n try {\n const event: unknown = JSON.parse(line);\n const record = asRecord(event);\n if (record === null) continue;\n\n if (record.type === 'thread.started') {\n const threadId = record.thread_id;\n if (typeof threadId === 'string') {\n return threadId;\n }\n }\n } catch {\n logger.debug('Skipped malformed NDJSON line', { snippet: line.slice(0, 100) });\n continue;\n }\n }\n\n return null;\n }\n\n /**\n * Processes an item.completed event.\n */\n private processItemCompleted(\n record: Record<string, unknown>,\n messages: string[],\n reasoning: string[]\n ): void {\n const item = asRecord(record.item);\n if (item === null) return;\n\n const itemType = item.type;\n const text = item.text;\n\n if (typeof text !== 'string') return;\n\n if (itemType === 'agent_message') {\n messages.push(text);\n } else if (itemType === 'reasoning') {\n reasoning.push(text);\n }\n }\n\n /**\n * Extracts usage from a turn.completed event.\n */\n private extractUsageFromEvent(record: Record<string, unknown>): TokenUsage | null {\n const usage = asRecord(record.usage);\n if (usage === null) return null;\n\n const inputTokens = extractNumberField(usage, 'input_tokens');\n const outputTokens = extractNumberField(usage, 'output_tokens');\n\n if (inputTokens === null || outputTokens === null) {\n return null;\n }\n\n const cachedInputTokens = extractNumberField(usage, 'cached_input_tokens');\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n ...(cachedInputTokens !== null && { cachedInputTokens }),\n };\n }\n}\n","/**\n * Disable every codex MCP server for a read-only analysis run (#6970).\n *\n * `codex exec -s read-only` sandboxes the model's own tools, but MCP servers\n * from codex's config start outside that sandbox. Measured live on codex-cli\n * 0.160.0: the nexus-agents server registered in `~/.codex/config.toml` wrote\n * `.gitignore` and `.nexus-agents/` into the tree on every read-only run.\n * `-c mcp_servers.<name>.enabled=false` per server made the run clean;\n * `-c mcp_servers={}` did not.\n *\n * Config layers read, as codex-cli 0.160.0 names them:\n * - system: `/etc/codex/config.toml` and the legacy `/etc/codex/managed_config.toml`\n * - user: `$CODEX_HOME/config.toml`, default `~/.codex/config.toml`\n * - project: `.codex/config.toml` in each directory from the cwd up to the\n * project root (the first directory holding a `project_root_markers` entry,\n * default `.git`). codex loads these only for a trusted project; this module\n * does not decide trust, see {@link CodexMcpServer.transportKey}.\n *\n * Refused rather than listed (the scan fails closed), since this module\n * cannot name the servers they add:\n * - plugins. A `plugins` table in any config layer with an entry not set\n * `enabled = false`, or an installed plugin under `$CODEX_HOME/plugins/`\n * that declares MCP servers (a `.mcp.json`, or `mcpServers` in its\n * `.codex-plugin/`, `.claude-plugin/` or `.cursor-plugin/` `plugin.json`).\n * - cloud-managed config: a `cloud-config-bundle-cache.json` in `$CODEX_HOME`,\n * which codex 0.160.0 writes for a workspace whose admin pushes config.\n * Before that cache exists, the account is classified instead: a run whose\n * `auth.json` is not a personal plan is refused (#6977), see\n * {@link cloudConfigAuthRefusal}.\n */\n\nimport { readdirSync, realpathSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseToml } from 'smol-toml';\n\nimport type { Result } from '../core/index.js';\nimport { ok, err } from '../core/index.js';\nimport { isRecord } from '../utils/type-coercion.js';\nimport { cloudConfigAuthRefusal } from './codex-cloud-config-auth.js';\nimport {\n type McpScanContext,\n childHome,\n envValue,\n projectDirs,\n readConfigIfPresent,\n} from './mcp-config-scan.js';\n\n/** The key that selects an MCP server's transport in codex config. */\ntype TransportKey = 'command' | 'url';\n\n/** One MCP server codex's config registers. */\nexport interface CodexMcpServer {\n readonly name: string;\n /**\n * The transport key (`command` or `url`), set only for a server that no\n * system or user config defines. codex rejects a `-c` override for a server\n * no loaded layer defines (`invalid transport`), and an untrusted project's\n * layer is not loaded; repeating the transport key makes the override a\n * complete, disabled definition either way.\n *\n * Only the key is kept: the override repeats it with\n * {@link CODEX_DISABLED_TRANSPORT_PLACEHOLDER}, never the configured value\n * (#6978). A configured url or command can embed a credential, and `-c`\n * values sit in the child's argv, readable via `ps` and `/proc`. Measured\n * live on codex-cli 0.160.0: a placeholder value with `enabled=false`\n * passes validation and starts nothing, for a trusted project (whose own\n * definition it overrides) and an untrusted one alike.\n */\n readonly transportKey?: TransportKey;\n}\n\n/**\n * The value a disabled project-only server's transport key is repeated with\n * (#6978). Never started: the same override sets `enabled = false`. `.invalid`\n * is a reserved TLD (RFC 2606), so the url cannot resolve even if it were.\n */\nconst CODEX_DISABLED_TRANSPORT_PLACEHOLDER: Readonly<Record<TransportKey, string>> = {\n command: 'nexus-agents-disabled-mcp-server',\n url: 'http://disabled.invalid/',\n};\n\n/** System config files, lowest precedence first. */\nexport const CODEX_SYSTEM_CONFIG_FILES: readonly string[] = [\n '/etc/codex/config.toml',\n '/etc/codex/managed_config.toml',\n];\n\n/** codex's default `project_root_markers`. */\nconst DEFAULT_PROJECT_ROOT_MARKERS: readonly string[] = ['.git'];\n\n/**\n * A server name codex's `-c` key parser accepts as one dotted segment. codex\n * splits the key on `.`, so a name outside this set cannot be addressed and\n * the scan fails closed.\n */\nconst ADDRESSABLE_NAME = /^[A-Za-z0-9_-]+$/;\n\ninterface ParsedLayer {\n readonly servers: ReadonlyMap<string, TransportKey | undefined>;\n readonly projectRootMarkers?: readonly string[];\n /** Names in the layer's `plugins` table not explicitly disabled. */\n readonly enabledPlugins: readonly string[];\n /** The layer's `cli_auth_credentials_store`, when set. */\n readonly credentialsStore?: string;\n}\n\n/** Plugin entries in a `plugins` table that are not `enabled = false`. */\nfunction enabledPlugins(path: string, table: unknown): Result<readonly string[], string> {\n if (table === undefined) return ok([]);\n if (!isRecord(table)) return err(`${path}: plugins is not a table`);\n return ok(\n Object.entries(table)\n .filter(([, entry]) => !(isRecord(entry) && entry['enabled'] === false))\n .map(([name]) => name)\n );\n}\n\n/** The server's transport key; its value is deliberately not read (#6978). */\nfunction transportOf(name: string, entry: unknown): Result<TransportKey | undefined, string> {\n if (!isRecord(entry)) return err(`mcp_servers.${name} is not a table`);\n if ('command' in entry) return ok('command');\n if ('url' in entry) return ok('url');\n return ok(undefined);\n}\n\nfunction parseServers(\n path: string,\n table: unknown\n): Result<Map<string, TransportKey | undefined>, string> {\n const servers = new Map<string, TransportKey | undefined>();\n if (table === undefined) return ok(servers);\n if (!isRecord(table)) return err(`${path}: mcp_servers is not a table`);\n for (const [name, entry] of Object.entries(table)) {\n if (!ADDRESSABLE_NAME.test(name)) {\n return err(`${path}: MCP server name ${JSON.stringify(name)} cannot be addressed by -c`);\n }\n const transport = transportOf(name, entry);\n if (!transport.ok) return err(`${path}: ${transport.error}`);\n servers.set(name, transport.value);\n }\n return ok(servers);\n}\n\nfunction readMarkers(path: string, value: unknown): Result<readonly string[] | undefined, string> {\n if (value === undefined) return ok(undefined);\n if (Array.isArray(value) && value.every((m): m is string => typeof m === 'string')) {\n return ok(value);\n }\n return err(`${path}: project_root_markers is not an array of strings`);\n}\n\n/** The layer's `cli_auth_credentials_store`, which must be a string when set. */\nfunction readStore(path: string, value: unknown): Result<string | undefined, string> {\n if (value === undefined || typeof value === 'string') return ok(value);\n return err(`${path}: cli_auth_credentials_store is not a string`);\n}\n\n/** One config file's servers; a missing file is an empty layer. */\nfunction readLayer(path: string): Result<ParsedLayer, string> {\n const text = readConfigIfPresent(path);\n if (!text.ok) return text;\n if (text.value === undefined) return ok({ servers: new Map(), enabledPlugins: [] });\n let doc: Record<string, unknown>;\n try {\n doc = parseToml(text.value);\n } catch (error: unknown) {\n return err(`cannot parse ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n return parseLayer(path, doc);\n}\n\n/** The keys of one parsed config document this module reads. */\nfunction parseLayer(path: string, doc: Record<string, unknown>): Result<ParsedLayer, string> {\n const servers = parseServers(path, doc['mcp_servers']);\n if (!servers.ok) return servers;\n const markers = readMarkers(path, doc['project_root_markers']);\n if (!markers.ok) return markers;\n const plugins = enabledPlugins(path, doc['plugins']);\n if (!plugins.ok) return plugins;\n const store = readStore(path, doc['cli_auth_credentials_store']);\n if (!store.ok) return store;\n return ok({\n servers: servers.value,\n enabledPlugins: plugins.value,\n ...(markers.value !== undefined && { projectRootMarkers: markers.value }),\n ...(store.value !== undefined && { credentialsStore: store.value }),\n });\n}\n\n/** Read every layer in `paths`, stopping at the first failure. */\nfunction readLayers(paths: readonly string[]): Result<ParsedLayer[], string> {\n const layers: ParsedLayer[] = [];\n for (const path of paths) {\n const layer = readLayer(path);\n if (!layer.ok) return layer;\n layers.push(layer.value);\n }\n return ok(layers);\n}\n\n/** The `CODEX_HOME` the child would use. */\nfunction codexHome(env: McpScanContext['env']): string {\n return envValue(env, 'CODEX_HOME') ?? join(childHome(env), '.codex');\n}\n\n/** The user config path the child would read. */\nexport function codexUserConfigPath(env: McpScanContext['env']): string {\n return join(codexHome(env), 'config.toml');\n}\n\n/** The cloud-managed config cache codex 0.160.0 keeps in `CODEX_HOME`. */\nexport const CODEX_CLOUD_CONFIG_CACHE = 'cloud-config-bundle-cache.json';\n\n/** Manifest directories codex reads a plugin's `plugin.json` from. */\nconst PLUGIN_MANIFEST_DIRS: ReadonlySet<string> = new Set([\n '.codex-plugin',\n '.claude-plugin',\n '.cursor-plugin',\n]);\n\n/**\n * How deep the plugin walk goes before it refuses: plugin roots sit at\n * `cache/<marketplace>/<plugin>/<version>/`, depth 4 below `plugins/`.\n */\nconst PLUGIN_WALK_DEPTH = 6;\n\n/** Whether one plugin manifest declares MCP servers; an unreadable one counts. */\nfunction manifestDeclaresMcp(path: string): Result<boolean, string> {\n const text = readConfigIfPresent(path);\n if (!text.ok) return text;\n if (text.value === undefined) return ok(false);\n let doc: unknown;\n try {\n doc = JSON.parse(text.value);\n } catch {\n return err(`cannot parse plugin manifest ${path}`);\n }\n return ok(isRecord(doc) && doc['mcpServers'] !== undefined);\n}\n\n/** Whether `path`, a directory entry, is a directory once symlinks resolve. */\nfunction isDirectory(path: string): boolean {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** `dir`'s entry names; a missing directory has none. */\nfunction listDir(dir: string): Result<readonly string[], string> {\n try {\n return ok(readdirSync(dir));\n } catch (error: unknown) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === 'ENOENT' || code === 'ENOTDIR') return ok([]);\n return err(`cannot list ${dir}: ${code ?? String(error)}`);\n }\n}\n\n/**\n * The declaring file in a plugin root (a directory holding `.mcp.json` or a\n * manifest directory), or `undefined`. The root's other content (skills,\n * assets, scripts) is not walked: codex reads declarations only from here.\n */\nfunction pluginRootMcp(dir: string, names: readonly string[]): Result<string | undefined, string> {\n if (names.includes('.mcp.json')) return ok(join(dir, '.mcp.json'));\n for (const name of names.filter((n) => PLUGIN_MANIFEST_DIRS.has(n))) {\n const path = join(dir, name, 'plugin.json');\n const declares = manifestDeclaresMcp(path);\n if (!declares.ok) return declares;\n if (declares.value) return ok(path);\n }\n return ok(undefined);\n}\n\n/**\n * The first installed plugin file under `dir` that declares MCP servers, or\n * `undefined`. Symlinked directories are followed (codex may follow them).\n * Fails closed: a directory deeper than {@link PLUGIN_WALK_DEPTH} without a\n * plugin root, or a symlink loop, is an error rather than \"no MCP\", since a\n * declaration past it would go unseen. `ancestors` holds the real paths on\n * the current branch.\n */\nfunction findPluginMcp(\n dir: string,\n depth: number,\n ancestors: ReadonlySet<string> = new Set()\n): Result<string | undefined, string> {\n const entries = listDir(dir);\n if (!entries.ok) return entries;\n if (entries.value.length === 0) return ok(undefined);\n if (entries.value.some((n) => n === '.mcp.json' || PLUGIN_MANIFEST_DIRS.has(n))) {\n return pluginRootMcp(dir, entries.value);\n }\n const branch = descendBranch(dir, depth, ancestors);\n if (!branch.ok) return branch;\n for (const name of entries.value) {\n const path = join(dir, name);\n if (!isDirectory(path)) continue;\n const found = findPluginMcp(path, depth + 1, branch.value);\n if (!found.ok || found.value !== undefined) return found;\n }\n return ok(undefined);\n}\n\n/**\n * The ancestor set for walking below `dir`, or an error when the walk must\n * not go further: `dir` repeats an ancestor (a symlink loop) or lies past\n * {@link PLUGIN_WALK_DEPTH}.\n */\nfunction descendBranch(\n dir: string,\n depth: number,\n ancestors: ReadonlySet<string>\n): Result<ReadonlySet<string>, string> {\n let real: string;\n try {\n real = realpathSync(dir);\n } catch (error: unknown) {\n const code = (error as NodeJS.ErrnoException).code;\n return err(`cannot resolve ${dir}: ${code ?? String(error)}`);\n }\n if (ancestors.has(real)) return err(`symlink loop in the plugin tree at ${dir}`);\n if (depth > PLUGIN_WALK_DEPTH) {\n return err(`plugin tree deeper than ${String(PLUGIN_WALK_DEPTH)} levels at ${dir}`);\n }\n return ok(new Set(ancestors).add(real));\n}\n\n/**\n * An error when codex would load MCP servers from a source this module\n * cannot list: an enabled plugin entry, an installed plugin declaring MCP\n * servers, cached cloud-managed config, or an account codex would fetch\n * cloud-managed config for.\n */\nfunction unlistableSourceRefusal(\n env: McpScanContext['env'],\n layers: readonly ParsedLayer[]\n): Result<undefined, string> {\n const plugin = layers.flatMap((l) => l.enabledPlugins)[0];\n if (plugin !== undefined) {\n return err(`plugin ${JSON.stringify(plugin)} is enabled; its MCP servers cannot be listed`);\n }\n const home = codexHome(env);\n const declared = findPluginMcp(join(home, 'plugins'), 0);\n if (!declared.ok) return declared;\n if (declared.value !== undefined) {\n return err(`installed plugin declares MCP servers (${declared.value}); they cannot be listed`);\n }\n const cache = join(home, CODEX_CLOUD_CONFIG_CACHE);\n try {\n statSync(cache);\n } catch (error: unknown) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT' && code !== 'ENOTDIR') {\n return err(`cannot stat ${cache}: ${code ?? String(error)}`);\n }\n // Nothing cached yet: refuse an account codex would fetch for (#6977).\n // Any layer naming a non-file store counts, so a project layer cannot\n // hide one set below it.\n const store = layers\n .map((l) => l.credentialsStore)\n .find((s) => s !== undefined && s !== 'file');\n return cloudConfigAuthRefusal(home, store);\n }\n return err(`cloud-managed config is cached at ${cache}; its MCP servers cannot be listed`);\n}\n\n/**\n * Every MCP server codex would load for a run in `ctx`, or an error when a\n * config file that exists cannot be read or parsed, or when codex would load\n * servers from a source this module cannot list (plugins, cloud config).\n */\nexport function scanCodexMcpServers(\n ctx: McpScanContext,\n systemFiles: readonly string[] = CODEX_SYSTEM_CONFIG_FILES\n): Result<readonly CodexMcpServer[], string> {\n const always = readLayers([...systemFiles, codexUserConfigPath(ctx.env)]);\n if (!always.ok) return always;\n const markers =\n always.value.findLast((l) => l.projectRootMarkers !== undefined)?.projectRootMarkers ??\n DEFAULT_PROJECT_ROOT_MARKERS;\n // Nearest directory first, so the first definition seen wins.\n const project = readLayers(\n projectDirs(ctx.cwd, markers).map((dir) => join(dir, '.codex', 'config.toml'))\n );\n if (!project.ok) return project;\n const unlistable = unlistableSourceRefusal(ctx.env, [...always.value, ...project.value]);\n if (!unlistable.ok) return unlistable;\n\n return ok(mergeServers(always.value, project.value));\n}\n\n/**\n * The servers of the always-loaded layers, then those only a project layer\n * defines (nearest first, so the first definition seen wins), with the\n * transport key kept for the latter.\n */\nfunction mergeServers(\n always: readonly ParsedLayer[],\n project: readonly ParsedLayer[]\n): readonly CodexMcpServer[] {\n const baseNames = new Set(always.flatMap((l) => [...l.servers.keys()]));\n const projectOnly = new Map<string, TransportKey | undefined>();\n for (const layer of project) {\n for (const [name, transport] of layer.servers) {\n if (!baseNames.has(name) && !projectOnly.has(name)) projectOnly.set(name, transport);\n }\n }\n return [\n ...[...baseNames].map((name) => ({ name })),\n ...[...projectOnly].map(([name, transportKey]) =>\n transportKey === undefined ? { name } : { name, transportKey }\n ),\n ];\n}\n\n/** The `-c` overrides that disable `servers`, as `key → value`. */\nexport function codexMcpDisableConfig(\n servers: readonly CodexMcpServer[]\n): Readonly<Record<string, unknown>> {\n const config: Record<string, unknown> = {};\n for (const server of servers) {\n config[`mcp_servers.${server.name}.enabled`] = false;\n if (server.transportKey !== undefined) {\n config[`mcp_servers.${server.name}.${server.transportKey}`] =\n CODEX_DISABLED_TRANSPORT_PLACEHOLDER[server.transportKey];\n }\n }\n return config;\n}\n\n/**\n * `codex exec` argv that disables `servers`: one `-c key=value` pair per\n * override. Values are written as JSON, which codex parses as TOML (a JSON\n * string or array is a valid TOML basic string or array).\n */\nexport function codexMcpDisableArgs(servers: readonly CodexMcpServer[]): readonly string[] {\n return Object.entries(codexMcpDisableConfig(servers)).flatMap(([key, value]) => [\n '-c',\n `${key}=${JSON.stringify(value)}`,\n ]);\n}\n","/**\n * Refuse a read-only codex run for an account codex would fetch cloud-managed\n * config for (#6977).\n *\n * {@link scanCodexMcpServers} refuses when `cloud-config-bundle-cache.json`\n * exists, but on a workspace account's first run nothing is cached yet: codex\n * fetches the bundle at startup, and an MCP server it defines starts outside\n * the read-only sandbox. Nothing on disk names those servers before the fetch.\n *\n * codex-cli 0.160.0 has no flag or config key that turns the fetch off\n * (`codex exec --help`, `codex features list`). Its gate is the account\n * alone, `cloud_config_eligible_auth` in `codex-rs/cloud-config/src/service.rs`\n * at tag `rust-v0.160.0`: a codex-backend auth mode whose plan is\n * business-like, education-like or enterprise. The plan is the\n * `chatgpt_plan_type` claim of the `id_token` in `$CODEX_HOME/auth.json`\n * (`CodexAuth::account_plan_type`), readable offline.\n *\n * This module allows only the personal plans and refuses everything else,\n * including team plans (a workspace account codex 0.160.0 does not fetch for)\n * and any plan it does not know, so a later codex that widens the gate is\n * refused rather than missed. Credentials that cannot be read here (a keyring\n * store, or an auth mode whose plan is not in the file) are refused too.\n *\n * No credential is read beyond the plan claim, and none reaches a message.\n */\n\nimport { join } from 'node:path';\n\nimport type { Result } from '../core/index.js';\nimport { ok, err } from '../core/index.js';\nimport { isRecord } from '../utils/type-coercion.js';\nimport { readConfigIfPresent } from './mcp-config-scan.js';\n\n/** Plans codex 0.160.0 never fetches cloud-managed config for. */\nconst PERSONAL_PLANS: ReadonlySet<string> = new Set([\n 'free',\n 'go',\n 'plus',\n 'pro',\n 'prolite',\n 'promax',\n]);\n\n/** Auth modes that never reach the codex backend, so never fetch the bundle. */\nconst NON_BACKEND_MODES: ReadonlySet<string> = new Set([\n 'apikey',\n 'bedrockApiKey',\n 'bedrockAccessKeys',\n]);\n\n/** Auth modes whose plan is the `id_token` claim in auth.json. */\nconst ID_TOKEN_MODES: ReadonlySet<string> = new Set(['chatgpt', 'chatgptAuthTokens']);\n\n/** The JWT claim namespace that carries `chatgpt_plan_type`. */\nconst AUTH_CLAIMS = 'https://api.openai.com/auth';\n\n/** A plan value safe to echo: a plain identifier, never free text. */\nconst ECHOABLE_VALUE = /^[A-Za-z0-9_]{1,40}$/;\n\nconst REFUSAL_SUFFIX =\n 'codex may fetch cloud-managed config whose MCP servers cannot be listed before the run';\n\n/** Credential fields that select a mode when `auth_mode` is absent, in codex's order. */\nconst MODE_BY_FIELD: ReadonlyArray<readonly [string, string]> = [\n ['personal_access_token', 'personalAccessToken'],\n ['bedrock_api_key', 'bedrockApiKey'],\n ['bedrock_access_keys', 'bedrockAccessKeys'],\n ['OPENAI_API_KEY', 'apikey'],\n];\n\n/**\n * codex's `AuthDotJson::resolved_mode`: `auth_mode` when set, else the first\n * credential field present, else `chatgpt`. A non-string `auth_mode` is\n * `undefined`, which is refused.\n */\nfunction resolvedMode(auth: Record<string, unknown>): string | undefined {\n const explicit = auth['auth_mode'];\n if (explicit !== undefined) return typeof explicit === 'string' ? explicit : undefined;\n const byField = MODE_BY_FIELD.find(\n ([field]) => auth[field] !== undefined && auth[field] !== null\n );\n return byField?.[1] ?? 'chatgpt';\n}\n\n/** The `chatgpt_plan_type` claim of `auth`'s id_token, or an error. */\nfunction planClaim(auth: Record<string, unknown>): Result<string, string> {\n const tokens = auth['tokens'];\n const idToken = isRecord(tokens) ? tokens['id_token'] : undefined;\n if (typeof idToken !== 'string') return err('auth.json has no id_token to read the plan from');\n const payload = idToken.split('.')[1];\n let claims: unknown;\n try {\n claims =\n payload === undefined ? undefined : JSON.parse(Buffer.from(payload, 'base64url').toString());\n } catch {\n claims = undefined;\n }\n const namespace = isRecord(claims) ? claims[AUTH_CLAIMS] : undefined;\n const plan = isRecord(namespace) ? namespace['chatgpt_plan_type'] : undefined;\n if (typeof plan !== 'string') return err('the auth.json id_token carries no account plan');\n return ok(plan);\n}\n\n/** A file value as it may appear in a message: echoed only when a plain identifier. */\nfunction echoable(value: string | undefined): string {\n return value !== undefined && ECHOABLE_VALUE.test(value)\n ? JSON.stringify(value)\n : 'an unrecognized value';\n}\n\n/** auth.json parsed as an object, `undefined` when absent, or an error. */\nfunction readAuth(codexHome: string): Result<Record<string, unknown> | undefined, string> {\n const path = join(codexHome, 'auth.json');\n const text = readConfigIfPresent(path);\n if (!text.ok) return text;\n if (text.value === undefined) return ok(undefined);\n let doc: unknown;\n try {\n doc = JSON.parse(text.value);\n } catch {\n return err(`cannot parse ${path}`);\n }\n return isRecord(doc) ? ok(doc) : err(`${path} is not a JSON object`);\n}\n\n/**\n * An error when the account in `codexHome` is one codex may fetch\n * cloud-managed config for, or cannot be classified offline.\n * `credentialsStore` is the `cli_auth_credentials_store` the child's config\n * sets; `undefined` is codex's default, `file`.\n */\nexport function cloudConfigAuthRefusal(\n codexHome: string,\n credentialsStore: string | undefined\n): Result<undefined, string> {\n if (credentialsStore !== undefined && credentialsStore !== 'file') {\n return err(\n `cli_auth_credentials_store = ${echoable(credentialsStore)} keeps the account outside auth.json, so its plan cannot be checked; ${REFUSAL_SUFFIX}`\n );\n }\n const auth = readAuth(codexHome);\n if (!auth.ok) return err(`${auth.error}; ${REFUSAL_SUFFIX}`);\n // No auth.json under the file store: no ChatGPT login, so no fetch.\n if (auth.value === undefined) return ok(undefined);\n return accountRefusal(auth.value);\n}\n\n/** The refusal for one parsed auth.json: by auth mode, then by plan. */\nfunction accountRefusal(auth: Record<string, unknown>): Result<undefined, string> {\n const mode = resolvedMode(auth);\n if (mode !== undefined && NON_BACKEND_MODES.has(mode)) return ok(undefined);\n if (mode === undefined || !ID_TOKEN_MODES.has(mode)) {\n return err(`codex auth_mode ${echoable(mode)} has no plan readable offline; ${REFUSAL_SUFFIX}`);\n }\n const plan = planClaim(auth);\n if (!plan.ok) return err(`${plan.error}; ${REFUSAL_SUFFIX}`);\n if (PERSONAL_PLANS.has(plan.value)) return ok(undefined);\n return err(\n `codex account plan ${echoable(plan.value)} is not a personal plan; ${REFUSAL_SUFFIX}`\n );\n}\n","/**\n * Shared pieces for listing the MCP servers a spawned CLI would load (#6970).\n *\n * Why: a read-only analysis run of codex still starts every MCP server the\n * CLI's own config registers. Those servers run OUTSIDE the CLI's sandbox, so\n * one that writes on startup (nexus-agents itself writes `.gitignore` and\n * `.nexus-agents/`) or exposes write-capable tools defeats the read-only\n * guarantee. Measured live on 2026-10-02: codex `-s read-only` left\n * `.gitignore` in the tree. The fix disables each configured server by name\n * for the run, so the adapter has to know every name the CLI would load.\n * (opencode showed the same defect and more; it refuses read-only analysis\n * instead, #6979.)\n *\n * Fail-closed contract: a config file that exists but cannot be read or\n * parsed is an error, never \"no servers\". The caller refuses the read-only\n * task rather than running it with servers it could not see.\n */\n\nimport {\n closeSync,\n constants as fsConstants,\n fstatSync,\n openSync,\n readSync,\n statSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\n\nimport type { Result } from '../core/index.js';\nimport { ok, err } from '../core/index.js';\nimport type { CliError, CliName, CliTask } from './types.js';\nimport { accessModeConflict } from './access-mode.js';\nimport { buildChildEnv } from './subprocess-env.js';\nimport { spawnCwd } from './subprocess-adapter.js';\n\n/** Where a CLI would run: the child's environment and working directory. */\nexport interface McpScanContext {\n readonly env: Readonly<Record<string, string | undefined>>;\n readonly cwd: string;\n}\n\n/**\n * The largest config file the scan reads. Real CLI configs are a few KiB; the\n * cap keeps a hostile project file from exhausting memory in this process.\n */\nexport const MAX_CONFIG_BYTES = 1024 * 1024;\n\n/**\n * Open flags: read-only, and non-blocking so a FIFO cannot stall the open.\n * `O_NONBLOCK` is absent on Windows, where `| undefined` contributes 0.\n */\nconst OPEN_FLAGS = fsConstants.O_RDONLY | fsConstants.O_NONBLOCK;\n\n/** Up to `MAX_CONFIG_BYTES + 1` bytes of `fd`, so an oversized file is detectable. */\nfunction readCapped(fd: number): Buffer {\n const buffer = Buffer.alloc(MAX_CONFIG_BYTES + 1);\n let total = 0;\n for (;;) {\n const n = readSync(fd, buffer, total, buffer.length - total, null);\n if (n === 0) return buffer.subarray(0, total);\n total += n;\n if (total === buffer.length) return buffer;\n }\n}\n\n/**\n * The text of `path`, `undefined` when no such file exists, or an error for\n * any other failure (permission denied, a directory in its place, ...).\n *\n * The scan runs on untrusted project trees, so the path must resolve (after\n * symlinks) to a regular file of at most {@link MAX_CONFIG_BYTES}. A symlink\n * to `/dev/zero`, a FIFO or a device would otherwise hang or exhaust memory\n * synchronously in this process. The type is checked on the opened\n * descriptor, so the file checked is the file read.\n */\nexport function readConfigIfPresent(path: string): Result<string | undefined, string> {\n let fd: number;\n try {\n fd = openSync(path, OPEN_FLAGS);\n } catch (error: unknown) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === 'ENOENT' || code === 'ENOTDIR') return ok(undefined);\n return err(`cannot read ${path}: ${code ?? String(error)}`);\n }\n try {\n const stat = fstatSync(fd);\n if (!stat.isFile()) return err(`cannot read ${path}: not a regular file`);\n if (stat.size > MAX_CONFIG_BYTES) {\n return err(`cannot read ${path}: larger than ${String(MAX_CONFIG_BYTES)} bytes`);\n }\n const bytes = readCapped(fd);\n if (bytes.length > MAX_CONFIG_BYTES) {\n return err(`cannot read ${path}: larger than ${String(MAX_CONFIG_BYTES)} bytes`);\n }\n return ok(bytes.toString('utf8'));\n } catch (error: unknown) {\n const code = (error as NodeJS.ErrnoException).code;\n return err(`cannot read ${path}: ${code ?? String(error)}`);\n } finally {\n closeSync(fd);\n }\n}\n\n/** Whether `dir` contains any of `markers` (a file or a directory). */\nfunction hasMarker(dir: string, markers: readonly string[]): boolean {\n return markers.some((marker) => {\n try {\n statSync(join(dir, marker));\n return true;\n } catch {\n return false;\n }\n });\n}\n\n/**\n * `cwd` and its ancestors, nearest first, up to and including the first one\n * that holds a project-root marker. With no marker anywhere the walk reaches\n * the filesystem root: listing a directory the CLI would skip only adds names\n * to disable, while missing one the CLI loads would leave a server running.\n */\nexport function projectDirs(cwd: string, markers: readonly string[]): readonly string[] {\n const dirs: string[] = [];\n let dir = resolve(cwd);\n for (;;) {\n dirs.push(dir);\n if (hasMarker(dir, markers)) return dirs;\n const parent = dirname(dir);\n if (parent === dir) return dirs;\n dir = parent;\n }\n}\n\n/** The child's home directory: its `HOME`, else this process's. */\nexport function childHome(env: McpScanContext['env']): string {\n const home = env['HOME'];\n return home !== undefined && home !== '' ? home : homedir();\n}\n\n/** A non-empty env value, or `undefined`. */\nexport function envValue(env: McpScanContext['env'], name: string): string | undefined {\n const value = env[name];\n return value !== undefined && value !== '' ? value : undefined;\n}\n\n/**\n * The scan context for a subprocess CLI task: the env the child is spawned\n * with and the directory it runs in, so the scan reads the same files the\n * CLI will.\n */\nexport function subprocessScanContext(\n cli: CliName,\n task: Pick<CliTask, 'options'>\n): McpScanContext {\n return {\n env: buildChildEnv(cli),\n cwd: spawnCwd(task.options?.['workDir']) ?? process.cwd(),\n };\n}\n\n/** The refusal for a read-only task whose MCP config could not be listed. */\nexport function mcpScanRefusal(cli: CliName, reason: string): CliError {\n return accessModeConflict(\n cli,\n 'read-only-analysis',\n `cannot list the MCP servers ${cli} would load, so they cannot be disabled (${reason})`\n );\n}\n\n/**\n * The scan's value, or a throw carrying the refusal message. For a command\n * builder, which runs after the refusal check passed: a config that broke in\n * between must still stop the spawn.\n */\nexport function scanOrThrow<T>(cli: CliName, scan: Result<T, string>): T {\n if (!scan.ok) throw new Error(mcpScanRefusal(cli, scan.error).message);\n return scan.value;\n}\n","/**\n * nexus-agents/cli-adapters - Codex MCP Adapter\n *\n * MCP-based adapter for Codex CLI. Preferred transport for Codex integration.\n * Extends BaseCliAdapter to reuse retry logic, health checks, version\n * detection, and capacity tracking.\n *\n * (Source: Issue #1140 — Migrated to BaseCliAdapter base class)\n *\n * SECURITY: All spawn() calls use array-based args without shell interpolation.\n */\n\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport type {\n CliName,\n CliTransport,\n CliTask,\n CliResponse,\n CliError,\n ModelInfo,\n ResolvedExecutionOptions,\n} from '../types.js';\nimport type { Result } from '../../core/index.js';\nimport { getErrorMessage, ok, err, getTimeProvider, createLogger } from '../../core/index.js';\nimport type { CliModelInfo } from '../types-capability.js';\nimport { listModelsForCli } from '../../config/models-dev-by-vendor.js';\nimport { BaseCliAdapter } from '../base-adapter.js';\nimport { accessModeConflict, isReadOnlyAnalysis } from '../access-mode.js';\nimport { MAX_RESPONSE_STDERR_CHARS, spawnCwd } from '../subprocess-adapter.js';\nimport { createCallerInputCliError } from '../cli-error-helpers.js';\nimport { codexSandboxPreflight, createCodexSandboxGuard } from '../codex-sandbox-preflight.js';\nimport {\n CODEX_SYSTEM_CONFIG_FILES,\n codexMcpDisableConfig,\n scanCodexMcpServers,\n} from '../codex-mcp-isolation.js';\nimport { type McpScanContext, mcpScanRefusal, scanOrThrow } from '../mcp-config-scan.js';\n\nimport { type CodexAdapterOptions, toCodexModelSlug } from './codex-adapter-helpers.js';\nimport {\n CODEX_LEGACY_DEFAULTS,\n type McpToolResult,\n extractTextFromContent,\n createTimeout,\n determineErrorCode,\n NEXUS_MCP_DEPTH_ENV,\n nextCodexMcpDepthOrThrow,\n} from './codex-mcp-adapter-helpers.js';\nimport {\n getDefaultModelForCli,\n getCliModelName,\n buildModelInfo,\n} from '../../config/model-config-helpers.js';\n\n/**\n * Where the `codex mcp-server` child reads its config (#6970). The transport\n * spawns it in this process's cwd with the SDK's default environment plus\n * {@link NEXUS_MCP_DEPTH_ENV}; of that environment only `HOME` locates a\n * codex config file (`CODEX_HOME` is not passed through).\n */\nfunction mcpServerScanContext(): McpScanContext {\n return { env: { HOME: process.env['HOME'] }, cwd: process.cwd() };\n}\n\n/**\n * Codex CLI adapter using MCP transport.\n *\n * Extends BaseCliAdapter which provides:\n * - Retry logic with exponential backoff\n * - Health checks with version compatibility\n * - Capacity tracking\n * - Error creation helpers\n */\nexport class CodexMcpAdapter extends BaseCliAdapter {\n readonly name: CliName = 'codex';\n /**\n * #6754: a new thread is started with `sandbox: 'read-only'` on every call.\n * A `codex-reply` carries no sandbox argument, so a read-only task that\n * continues a session is refused in {@link accessModeRefusal}.\n */\n override readonly enforcesReadOnlyAnalysis = true;\n readonly transport: CliTransport = 'mcp';\n\n private readonly model: string;\n private sandboxArgs: readonly string[] = [];\n private readonly sandboxRefusal: () => Promise<CliError | undefined>;\n private client: Client | undefined;\n private mcpTransport: StdioClientTransport | undefined;\n private connected = false;\n /**\n * Stderr attribution state (#6094). The registry caches one adapter per CLI\n * and voter roles run under `Promise.all`, so the mcp-server's stderr pipe is\n * shared by every in-flight call. `inFlight` is the current overlap;\n * `overlapEpoch` advances whenever a call starts while another is in flight,\n * so a capture that began alone can still see that it was later overlapped.\n */\n private inFlight = 0;\n private overlapEpoch = 0;\n\n constructor(options?: CodexAdapterOptions) {\n super(options?.logger ?? createLogger({ component: 'codex-mcp-adapter' }));\n this.model = options?.model ?? getCliModelName(getDefaultModelForCli('codex'));\n this.sandboxRefusal = createCodexSandboxGuard(\n options?.sandboxProbe ?? codexSandboxPreflight,\n this.logger,\n (args) => {\n this.sandboxArgs = args;\n },\n options?.platform\n );\n }\n\n /**\n * Key-free model enumeration via the models.dev snapshot (#3405), matching\n * `CodexCliAdapter`.\n *\n * #4318: this was missing, and `buildDefaultModelSources` includes an adapter\n * only when `hasListModels(adapter)` is true. Since `createAllAdapters`\n * defaults codex to the mcp transport, codex was silently filtered out of\n * `list_available_models` — the probe reported one fewer transport than it\n * had, with no error anywhere. Model enumeration is transport-independent, so\n * the two adapters must answer identically.\n */\n listModels(): Promise<readonly CliModelInfo[]> {\n return Promise.resolve(listModelsForCli(this.name));\n }\n\n /**\n * Gets Codex model information.\n * Resolves from canonical registry when possible, falls back to legacy lookup.\n */\n getModelInfo(): ModelInfo {\n const fromRegistry = buildModelInfo('codex', this.model);\n if (fromRegistry !== undefined) return fromRegistry;\n return {\n id: this.model,\n name: CODEX_LEGACY_DEFAULTS.displayNames[this.model] ?? this.model,\n contextWindow: CODEX_LEGACY_DEFAULTS.contextWindow,\n maxOutput: CODEX_LEGACY_DEFAULTS.maxOutput,\n costPerMillionInput:\n CODEX_LEGACY_DEFAULTS.inputCosts[this.model] ?? CODEX_LEGACY_DEFAULTS.inputCost,\n costPerMillionOutput:\n CODEX_LEGACY_DEFAULTS.outputCosts[this.model] ?? CODEX_LEGACY_DEFAULTS.outputCost,\n };\n }\n\n /**\n * Initializes the MCP connection to Codex.\n */\n async initialize(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n this.initCapacityTracker();\n this.logger.debug('Initializing Codex MCP connection');\n\n // Recursion guard (#3350): refuse to spawn `codex mcp-server` if we're\n // already nested inside a nexus-spawned codex MCP context, and stamp the\n // child with the incremented depth so it (and anything it spawns) inherits\n // the marker. Throws before any spawn when nested — breaking the loop.\n const childDepth = nextCodexMcpDepthOrThrow();\n\n // initialize() also has direct callers that do not pass through execute().\n const refusal = await this.sandboxRefusal();\n if (refusal !== undefined) throw new Error(refusal.message);\n\n try {\n // Use the same selected backend as the read-only preflight.\n this.mcpTransport = new StdioClientTransport({\n command: 'codex',\n args: ['mcp-server', ...this.sandboxArgs],\n stderr: 'pipe',\n env: { [NEXUS_MCP_DEPTH_ENV]: childDepth },\n });\n\n this.client = new Client({ name: 'nexus-agents', version: '2.0.0' }, { capabilities: {} });\n await this.client.connect(this.mcpTransport);\n this.connected = true;\n this.initialized = true;\n this.logger.info('Codex MCP connection established');\n } catch (error) {\n this.connected = false;\n const connectionError = error instanceof Error ? error : new Error('Connection failed');\n this.logger.error('Failed to initialize Codex MCP connection', connectionError);\n throw error;\n }\n }\n\n /**\n * Executes a task via MCP client.\n * Called by BaseCliAdapter.execute() with retry handling.\n */\n async executeTask(\n _task: CliTask,\n options: ResolvedExecutionOptions\n ): Promise<Result<CliResponse, CliError>> {\n const startTime = getTimeProvider().now();\n\n if (this.client === undefined) {\n return err(this.createError('CONNECTION_ERROR', 'MCP client not initialized'));\n }\n\n // #6094: read the mcp-server's piped stderr for the duration of THIS call.\n // A sandbox failure inside the codex tool loop (bwrap on a userns-\n // restricted host) is written there while the tool result still carries\n // the model's parsed answer; without this the pipe was never read.\n const stderrCapture = this.captureTransportStderr();\n try {\n const result = await Promise.race([\n this.callCodexTool(_task),\n createTimeout(options.timeoutMs),\n ]);\n\n if (result === null) {\n return err(this.createError('TIMEOUT', 'Execution timed out'));\n }\n\n return this.parseToolResult(result, startTime, stderrCapture.stop());\n } catch (error) {\n return this.handleExecutionError(error);\n } finally {\n stderrCapture.stop();\n }\n }\n\n /**\n * Attach a listener to the transport's stderr pipe; `stop()` detaches it\n * and returns what was written meanwhile (capped like the subprocess path).\n * A transport without a readable stderr (tests, or `stderr: 'inherit'`)\n * yields an empty capture, which the caller records as absent.\n *\n * ATTRIBUTION (#6094 review): the pipe is process-wide, so a line written\n * while two calls overlap cannot be assigned to either. If another call was\n * in flight at ANY point during this capture, the capture is discarded\n * (debug-logged) and the seat falls through to the reasoning fallback.\n * Attributing it to both would classify a seat that read the artifact as\n * unverifiable.\n */\n private captureTransportStderr(): { stop: () => string } {\n this.inFlight++;\n if (this.inFlight > 1) this.overlapEpoch++;\n const epochAtStart = this.overlapEpoch;\n const overlappedAtStart = this.inFlight > 1;\n const stream = (this.mcpTransport as { stderr?: NodeJS.ReadableStream | null } | undefined)\n ?.stderr;\n let captured = '';\n const onData = (chunk: Buffer | string): void => {\n if (captured.length < MAX_RESPONSE_STDERR_CHARS) captured += chunk.toString();\n };\n stream?.on('data', onData);\n let stopped = false;\n return {\n stop: (): string => {\n if (stopped) return '';\n stopped = true;\n stream?.off('data', onData);\n this.inFlight--;\n const overlapped = overlappedAtStart || this.overlapEpoch !== epochAtStart;\n if (overlapped && captured !== '') {\n this.logger.debug('Codex MCP stderr not attributed: another call was in flight', {\n capturedChars: captured.length,\n });\n return '';\n }\n return captured.slice(0, MAX_RESPONSE_STDERR_CHARS);\n },\n };\n }\n\n /**\n * #7012: refuse directory-bound tasks; the MCP tool's cwd support is\n * unverified, so neither new nor continued sessions can honour workDir.\n * #6754: a continued session cannot be pinned to the read-only sandbox.\n * #6970: nor can a read-only task run when codex's MCP config cannot be\n * listed, since its servers run outside the sandbox.\n */\n protected override async accessModeRefusal(task: CliTask): Promise<CliError | undefined> {\n const base = await super.accessModeRefusal(task);\n if (base !== undefined) return base;\n if (spawnCwd(task.options?.['workDir']) !== undefined) {\n return createCallerInputCliError(\n 'Refusing Codex MCP task with workDir: cwd support is unverified for the MCP tools. ' +\n 'Use the subprocess transport to honour the working directory.',\n this.name\n );\n }\n if (isReadOnlyAnalysis(task)) {\n if (task.sessionId !== undefined && task.sessionId !== '') {\n return accessModeConflict(\n this.name,\n 'read-only-analysis',\n 'a continued codex session carries no sandbox setting'\n );\n }\n const scan = scanCodexMcpServers(mcpServerScanContext(), this.codexSystemConfigFiles());\n if (!scan.ok) return mcpScanRefusal(this.name, scan.error);\n }\n return this.sandboxRefusal();\n }\n\n /**\n * The system config files the MCP scan reads (#6970). A seam so tests can\n * keep the host's real `/etc/codex` out of the scan.\n */\n protected codexSystemConfigFiles(): readonly string[] {\n return CODEX_SYSTEM_CONFIG_FILES;\n }\n\n /**\n * The `config` argument of a new `codex` thread for a read-only task: the\n * same per-server disables `codex exec` gets as `-c` (#6970). The tool\n * applies `config` as `-c` overrides. Throws when the config cannot be\n * listed.\n */\n private readOnlyMcpConfig(task: CliTask): { config?: Readonly<Record<string, unknown>> } {\n if (!isReadOnlyAnalysis(task)) return {};\n const servers = scanOrThrow(\n this.name,\n scanCodexMcpServers(mcpServerScanContext(), this.codexSystemConfigFiles())\n );\n return servers.length === 0 ? {} : { config: codexMcpDisableConfig(servers) };\n }\n\n /**\n * Calls the codex or codex-reply tool on Codex MCP server.\n * @see https://developers.openai.com/codex/mcp/\n */\n private async callCodexTool(task: CliTask): Promise<McpToolResult> {\n if (this.client === undefined) {\n throw new Error('Client not initialized');\n }\n\n const isReply = task.sessionId !== undefined && task.sessionId !== '';\n const toolName = isReply ? 'codex-reply' : 'codex';\n\n // task.model is the canonical registry id, which codex rejects — translate\n // it to the slug the MCP server's `model` argument accepts (#5091).\n const baseArgs = {\n prompt: task.content,\n ...(task.model !== undefined && { model: toCodexModelSlug(task.model, this.logger) }),\n };\n\n const args = isReply\n ? { ...baseArgs, threadId: task.sessionId }\n : {\n ...baseArgs,\n sandbox: 'read-only' as const,\n 'approval-policy': 'never' as const,\n ...this.readOnlyMcpConfig(task),\n };\n\n const result = await this.client.callTool({\n name: toolName,\n arguments: args,\n });\n\n return result as McpToolResult;\n }\n\n /**\n * Parses MCP tool result to CLI response.\n */\n private parseToolResult(\n result: McpToolResult,\n startTime: number,\n stderr: string\n ): Result<CliResponse, CliError> {\n if (result.isError === true) {\n const errorText = extractTextFromContent(result.content);\n // #4373: this hardcoded EXECUTION_ERROR and never looked at the message,\n // so a quota-dead codex-mcp was indistinguishable from any other failure\n // and never counted as a serving failure against the circuit breaker the\n // voter gate reads (#4330). Classify the text the same way the error path\n // below does.\n const code = errorText === null ? 'EXECUTION_ERROR' : determineErrorCode(errorText);\n return err(this.createError(code, errorText ?? 'Tool execution failed'));\n }\n\n const text = extractTextFromContent(result.content);\n if (text === null) {\n return err(this.createError('PARSE_ERROR', 'No text content in response'));\n }\n\n return ok({\n text,\n durationMs: getTimeProvider().now() - startTime,\n raw: result,\n ...(stderr !== '' ? { stderr } : {}),\n });\n }\n\n /**\n * Handles execution errors.\n */\n private handleExecutionError(error: unknown): Result<CliResponse, CliError> {\n const message = getErrorMessage(error);\n const errorCode = determineErrorCode(message);\n\n if (errorCode === 'CONNECTION_ERROR') {\n this.connected = false;\n }\n\n return err(this.createError(errorCode, message, error as Error));\n }\n\n /**\n * Disposes the adapter and closes MCP connection.\n */\n async dispose(): Promise<void> {\n if (this.mcpTransport !== undefined) {\n this.logger.debug('Closing Codex MCP connection');\n await this.mcpTransport.close();\n this.mcpTransport = undefined;\n }\n this.client = undefined;\n this.connected = false;\n this.initialized = false;\n }\n}\n","/**\n * nexus-agents/cli-adapters - Codex MCP Adapter Helpers\n *\n * CLI-specific helper functions for Codex MCP adapter.\n * Model info lookups consolidated into config/model-config-helpers.ts (#886).\n *\n * (Source: cli-project_plan.md v2.1.0, Issue #90)\n */\n\nimport type { ResolvedExecutionOptions, CliError, CliName } from '../types.js';\nimport { CODEX_MCP_TIMEOUTS } from '../../config/timeouts.js';\nimport { isRateLimitText } from '../../adapters/rate-limit-detector.js';\nimport {\n createCliError as sharedCreateCliError,\n isRetryableErrorCode as sharedIsRetryableErrorCode,\n} from '../cli-error-helpers.js';\n\n// Re-export legacy defaults from the subprocess helpers (DRY)\nexport { CODEX_LEGACY_DEFAULTS } from './codex-adapter-helpers.js';\n\n/**\n * Default execution options for Codex MCP.\n * Timeout and retry values derived from config/timeouts.ts (#1220).\n */\nexport const DEFAULT_CODEX_MCP_OPTIONS: ResolvedExecutionOptions = {\n timeoutMs: CODEX_MCP_TIMEOUTS.defaultMs,\n allowRetry: true,\n maxRetries: CODEX_MCP_TIMEOUTS.maxRetries,\n trackUsage: true,\n onProgress: undefined,\n};\n\n// ---------------------------------------------------------------------------\n// Recursion guard for `codex mcp-server` spawning (#3350)\n// ---------------------------------------------------------------------------\n\n/**\n * Env var stamped on the `codex mcp-server` child nexus spawns, marking how\n * deep we are in the nexus→codex-mcp spawn nesting. Inherited by anything the\n * codex MCP server itself spawns (including a nested `nexus-agents\n * --mode=server` if codex is misconfigured to launch one).\n */\nexport const NEXUS_MCP_DEPTH_ENV = 'NEXUS_MCP_DEPTH';\n\n/**\n * Highest nesting depth at which nexus will spawn `codex mcp-server`. `0`\n * means only the top-level nexus process spawns it; any deeper attempt is the\n * recursive codex↔nexus loop and is refused.\n */\nconst MAX_CODEX_MCP_SPAWN_DEPTH = 0;\n\n/** Read the current nesting depth from an env bag; clamps missing/junk to 0. */\nexport function readMcpDepth(env: NodeJS.ProcessEnv = process.env): number {\n const raw = Number.parseInt(env[NEXUS_MCP_DEPTH_ENV] ?? '0', 10);\n return Number.isFinite(raw) && raw > 0 ? raw : 0;\n}\n\n/**\n * Recursion guard (#3350). Returns the depth string to stamp on the spawned\n * `codex mcp-server` child, or throws if we are already nested — which would\n * re-enter the codex↔nexus MCP spawn loop that corrupted the codex OAuth\n * token (dozens of leaked servers racing the shared refresh-token rotation).\n */\nexport function nextCodexMcpDepthOrThrow(env: NodeJS.ProcessEnv = process.env): string {\n const depth = readMcpDepth(env);\n if (depth > MAX_CODEX_MCP_SPAWN_DEPTH) {\n throw new Error(\n `Refusing to spawn 'codex mcp-server': already nested inside a ` +\n `nexus-spawned codex MCP context (${NEXUS_MCP_DEPTH_ENV}=${String(depth)}). ` +\n `This breaks the recursive codex↔nexus MCP spawn loop (#3350). If you ` +\n `intentionally configured codex to launch nexus-agents as an MCP ` +\n `server, remove that '[mcp_servers.nexus-agents]' entry from ~/.codex/config.toml.`\n );\n }\n return String(depth + 1);\n}\n\n/**\n * MCP tool call result structure.\n */\nexport interface McpToolResult {\n content?: Array<{ type: string; text?: string }>;\n isError?: boolean;\n}\n\n// -----------------------------------------------------------------------------\n// Error Handling\n// -----------------------------------------------------------------------------\n\n/**\n * Checks if an error code is retryable. Kept exported for backward\n * compatibility with callers that imported from this module; delegates\n * to the canonical helper (#2181).\n */\nexport function isRetryableErrorCode(code: CliError['code']): boolean {\n return sharedIsRetryableErrorCode(code);\n}\n\n/**\n * Creates a CLI error object with the canonical retryable-flag logic.\n * Kept exported for backward compatibility (#2181).\n */\nexport function createCliError(\n code: CliError['code'],\n message: string,\n cli: CliName,\n cause?: Error\n): CliError {\n return sharedCreateCliError(code, message, cli, cause);\n}\n\n// -----------------------------------------------------------------------------\n// Content Extraction\n// -----------------------------------------------------------------------------\n\n/** Extracts text from MCP content array. */\nexport function extractTextFromContent(\n content?: Array<{ type: string; text?: string }>\n): string | null {\n if (content === undefined || content.length === 0) {\n return null;\n }\n\n const textContents = content\n .filter((c): c is { type: string; text: string } => c.type === 'text' && c.text !== undefined)\n .map((c) => c.text);\n\n return textContents.length > 0 ? textContents.join('\\n') : null;\n}\n\n// Re-export from canonical source for backward compatibility\nexport { delay } from '../../utils/async-utils.js';\n\n/** Creates a timeout promise that resolves to null. */\nexport function createTimeout(ms: number): Promise<null> {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(null);\n }, ms);\n });\n}\n\n/**\n * Determines error code from error message.\n *\n * The terminal/actionable readings are checked first: a missing binary or a\n * timeout is a better answer than \"rate limited\" even when the text mentions a\n * rate limit, because a rate-limit reading routes the caller into a retry that\n * can never succeed.\n */\nexport function determineErrorCode(message: string): CliError['code'] {\n if (message.includes('ENOENT') || message.includes('not found')) {\n return 'NOT_FOUND';\n }\n\n if (message.includes('timeout') || message.includes('ETIMEDOUT')) {\n return 'TIMEOUT';\n }\n\n if (message.includes('connection') || message.includes('disconnect')) {\n return 'CONNECTION_ERROR';\n }\n\n // #4373: this check was missing entirely. Every other adapter extends\n // SubprocessCliAdapter and inherits it; CodexMcpAdapter extends\n // BaseCliAdapter and classified on its own, so a quota-dead codex-mcp came\n // back as a generic EXECUTION_ERROR and never registered as a serving failure\n // with the circuit breaker the voter serving-gate reads (#4330).\n // Reuses the shared pattern set rather than adding a second taxonomy.\n if (isRateLimitText(message)) {\n return 'RATE_LIMITED';\n }\n\n return 'EXECUTION_ERROR';\n}\n\n/** Parses version string from codex --version output. */\nexport function parseVersionFromOutput(output: string): string {\n const match = /(\\d+\\.\\d+\\.\\d+)/.exec(output.trim());\n return match?.[1] ?? '0.0.0';\n}\n","/**\n * nexus-agents/cli-adapters - OpenCode CLI Adapter\n *\n * Subprocess-based adapter for OpenCode CLI.\n * Uses `opencode run --format json` for stable parsing.\n *\n * (Source: Issue #1124, opencode.ai/docs/cli/)\n */\n\nimport { execFile } from 'node:child_process';\n\nimport type {\n ICliResponseParser,\n CliTask,\n CliModelInfo,\n ModelInfo,\n CliName,\n BaseAdapterOptions,\n} from '../types.js';\nimport {\n SubprocessCliAdapter,\n type CommandConfig,\n type TransientRetryConfig,\n} from '../subprocess-adapter.js';\nimport { OpenCodeResponseParser } from '../parsers/opencode-parser.js';\nimport { createCallerInputCliError } from '../cli-error-helpers.js';\nimport { isDynamicModelsEnabled } from '../../config/register-model-sources.js';\nimport { getAvailabilityCache } from '../../config/model-availability.js';\nimport type { ModelId } from '../../config/model-capabilities-types.js';\nimport type { Result } from '../../core/index.js';\nimport { ok, err } from '../../core/index.js';\nimport type { CliResponse, CliError } from '../types-core.js';\nimport type { ExecutionOptions, ResolvedExecutionOptions } from '../types-capability.js';\nimport {\n getDefaultModelForCli,\n getCliModelName,\n buildModelInfo,\n findInTreeByCli,\n findCanonicalModel,\n FALLBACK_CONTEXT_WINDOW,\n FALLBACK_MAX_OUTPUT,\n} from '../../config/model-config-helpers.js';\nimport { createLogger } from '../../core/index.js';\n\nconst logger = createLogger({ component: 'opencode-adapter' });\n\n/** Strict allowlist for OpenCode --variant flag values. */\nconst ALLOWED_VARIANTS = ['high', 'max', 'minimal'];\n\n/**\n * Maps internal model names to OpenCode CLI --model values.\n * OpenCode uses `provider/model-name` format (e.g., `anthropic/claude-sonnet-4-6`).\n * Built from canonical registry + common alias fallbacks (#1402).\n */\nconst MODEL_TO_CLI_NAME: Record<string, string> = buildOpenCodeAliasMap();\n\nfunction buildOpenCodeAliasMap(): Record<string, string> {\n const map: Record<string, string> = {};\n for (const model of findInTreeByCli('opencode')) {\n if (model.cliModelName === undefined) continue;\n // Map internal ID → CLI model name\n map[model.id] = model.cliModelName;\n // Map CLI alias → CLI model name\n if (model.cliAlias !== undefined) {\n map[model.cliAlias] = model.cliModelName;\n }\n // Pass through cliModelName itself\n map[model.cliModelName] = model.cliModelName;\n }\n return map;\n}\n\n/** Resolves an internal model name to OpenCode CLI format. */\nfunction resolveOpenCodeModel(model: string): string {\n return MODEL_TO_CLI_NAME[model] ?? model;\n}\n\n/**\n * Provider prefix opencode puts on gateway models: the registry and callers\n * say `qwen/qwen3-coder`, `opencode models` lists `openrouter/qwen/qwen3-coder`.\n */\nconst OPENROUTER_PREFIX = 'openrouter/';\n\n/**\n * Candidate opencode ids for a requested model, in preference order (#6599):\n * the name as given, then its registry mapping, each also tried under the\n * `openrouter/` prefix.\n */\nfunction openCodeCandidates(requested: string): string[] {\n const mapped = resolveOpenCodeModel(requested);\n const bases = mapped === requested ? [requested] : [requested, mapped];\n return bases.flatMap((b) => (b.startsWith(OPENROUTER_PREFIX) ? [b] : [b, OPENROUTER_PREFIX + b]));\n}\n\n/**\n * The id a response reports for `cliId`, and so the id cost is priced by: the\n * canonical registry id when one names this model (with or without the\n * `openrouter/` prefix), else the opencode id itself — which an unpriced\n * lookup then reports as unknown rather than at the default's price.\n */\nfunction reportedModelId(requested: string, cliId: string): string {\n const bare = cliId.startsWith(OPENROUTER_PREFIX) ? cliId.slice(OPENROUTER_PREFIX.length) : cliId;\n const entry =\n findCanonicalModel('opencode', requested) ??\n findCanonicalModel('opencode', cliId) ??\n findCanonicalModel('opencode', bare);\n return entry?.id ?? cliId;\n}\n\n/** A requested model resolved against the local opencode install (#6599). */\ninterface ResolvedOpenCodeModel {\n /** The id passed as `--model`. */\n readonly cliId: string;\n /** The id the response reports, which cost is priced by. */\n readonly reportedAs: string;\n}\n\n/** Timeout for `opencode models` probe (ms). */\nconst PROBE_TIMEOUT_MS = 10_000;\n\n/**\n * Probes available models by running `opencode models`.\n * Returns a Set of model IDs (e.g., \"opencode/big-pickle\").\n * Caches result in a module-level variable for the process lifetime.\n */\nlet cachedModels: Set<string> | undefined;\n/** Inflight probe promise for coalescing concurrent calls (Issue #1438). */\nlet probePromise: Promise<Set<string>> | undefined;\n\nfunction probeAvailableModels(): Promise<Set<string>> {\n if (cachedModels !== undefined) return Promise.resolve(cachedModels);\n if (probePromise !== undefined) return probePromise;\n\n probePromise = new Promise<Set<string>>((resolve) => {\n execFile('opencode', ['models'], { timeout: PROBE_TIMEOUT_MS }, (error, stdout) => {\n if (error !== null || stdout.trim() === '') {\n logger.debug('Failed to probe OpenCode models, will omit --model flag', {\n error: error?.message,\n });\n cachedModels = new Set();\n resolve(cachedModels);\n return;\n }\n const models = new Set(\n stdout\n .trim()\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => l.length > 0)\n );\n logger.debug('Probed OpenCode models', { count: models.size });\n cachedModels = models;\n resolve(cachedModels);\n });\n }).finally(() => {\n probePromise = undefined;\n });\n\n return probePromise;\n}\n\n/** Patterns indicating an Anthropic provider in OpenCode models list. */\nconst ANTHROPIC_MODEL_PATTERNS = ['anthropic/', 'custom/claude'];\n\n/**\n * Logs a warning if OpenCode has an Anthropic provider configured (#1429).\n * Claude Code subscription API keys must NOT be used with third-party tools.\n */\nfunction warnIfAnthropicProvider(models: Set<string>): void {\n const anthropicModels = [...models].filter((m) =>\n ANTHROPIC_MODEL_PATTERNS.some((p) => m.toLowerCase().includes(p))\n );\n if (anthropicModels.length > 0) {\n logger.warn(\n 'OpenCode has Anthropic/Claude models configured. ' +\n 'Ensure these use a SEPARATE API key from console.anthropic.com, ' +\n 'NOT a Claude Code subscription key (which is restricted to Claude Code only).',\n { detectedModels: anthropicModels }\n );\n }\n}\n\n/**\n * OpenCode CLI adapter using subprocess transport.\n * Executes: opencode run --format json \"<task>\"\n *\n * Probes available models on first use. The adapter's own default is passed\n * as --model only when available (#1402); an explicitly requested model is\n * resolved against the probe or returned as an error (#6599).\n */\nexport class OpenCodeCliAdapter extends SubprocessCliAdapter {\n readonly name: CliName = 'opencode';\n // opencode cannot run read-only analysis truthfully, so it refuses those\n // tasks (#6970, revisit in #6979). #6754 mapped the mode to an\n // `OPENCODE_PERMISSION` deny config. Observed live on 2026-10-02 with\n // opencode 1.15.13, under that config: MCP servers from the user's config\n // still started outside the permission rules (the nexus-agents server wrote\n // `.gitignore` into the tree); opencode itself rewrote the project's\n // `opencode.json` to insert `\"$schema\"` on every run; and it substitutes\n // `{env:}`/`{file:}` across the raw config text, comments and values\n // included, before parsing, so a config scan cannot list the servers it\n // will load (a reviewer reproduced a bypass of that scan).\n override readonly enforcesReadOnlyAnalysis = false;\n protected readonly parser: ICliResponseParser = new OpenCodeResponseParser();\n\n /** Enable transient-error retry for OpenCode (#1456). */\n protected override readonly transientRetry: TransientRetryConfig = { enabled: true };\n\n private readonly model: string;\n private availableModels: Set<string> | undefined;\n\n constructor(options?: BaseAdapterOptions) {\n super(options?.logger);\n this.model = options?.model ?? getCliModelName(getDefaultModelForCli('opencode'));\n }\n\n /**\n * Gets the implicit route's model information from the canonical registry.\n * After inventory probing, an unusable configured model runs the default.\n */\n getModelInfo(): ModelInfo {\n const model =\n this.availableModels !== undefined && !this.isModelUsable(resolveOpenCodeModel(this.model))\n ? getCliModelName(getDefaultModelForCli('opencode'))\n : this.model;\n const fromRegistry = buildModelInfo('opencode', model);\n if (fromRegistry !== undefined) return fromRegistry;\n\n return {\n id: model,\n name: `OpenCode (${model})`,\n contextWindow: FALLBACK_CONTEXT_WINDOW,\n maxOutput: FALLBACK_MAX_OUTPUT,\n // OpenCode pricing fallback is adapter-specific (not the Claude 5/25).\n costPerMillionInput: 3.0,\n costPerMillionOutput: 15.0,\n };\n }\n\n /**\n * Initializes the adapter — probes available models.\n * Warns if Anthropic provider is configured (#1429 — API key boundaries).\n */\n override async initialize(): Promise<void> {\n if (this.initialized) return;\n this.availableModels = await probeAvailableModels();\n warnIfAnthropicProvider(this.availableModels);\n await super.initialize();\n }\n\n /** Returns true if the model is available in the OpenCode installation. */\n private isModelAvailable(cliModel: string): boolean {\n if (this.availableModels === undefined || this.availableModels.size === 0) return false;\n return this.availableModels.has(cliModel);\n }\n\n /** #3408: true if the model is in rate-limit cooldown (recent 429). Opt-in. */\n private isCooled(cliModel: string): boolean {\n return (\n isDynamicModelsEnabled() && getAvailabilityCache().isKnownUnavailable(cliModel as ModelId)\n );\n }\n\n /** Usable = offered by the OpenCode install AND not in rate-limit cooldown. */\n private isModelUsable(cliModel: string): boolean {\n return this.isModelAvailable(cliModel) && !this.isCooled(cliModel);\n }\n\n /** The first candidate id for `requested` that this install lists. */\n private matchInventory(requested: string): string | undefined {\n const available = this.availableModels;\n if (available === undefined || available.size === 0) return undefined;\n return openCodeCandidates(requested).find((c) => available.has(c));\n }\n\n /**\n * Resolves an explicitly requested model (#6599). Unlike the adapter's own\n * default, an explicit request is never silently dropped: a model that is\n * not listed, or is in rate-limit cooldown, is an error rather than a run of\n * opencode's default under the requested model's name.\n */\n private resolveRequestedModel(requested: string): Result<ResolvedOpenCodeModel, CliError> {\n if (this.availableModels === undefined || this.availableModels.size === 0) {\n // No inventory to check against (`opencode models` failed): pass the\n // registry mapping through and let opencode reject it if it must.\n const cliId = resolveOpenCodeModel(requested);\n logger.warn('OpenCode model inventory unavailable; passing requested model unverified', {\n requested,\n cliId,\n });\n return ok({ cliId, reportedAs: reportedModelId(requested, cliId) });\n }\n const cliId = this.matchInventory(requested);\n if (cliId === undefined) {\n return err(\n createCallerInputCliError(\n `OpenCode cannot run requested model \"${requested}\": \\`opencode models\\` lists none of ` +\n `${openCodeCandidates(requested).join(', ')}. Refusing to run opencode's default in its place.`,\n this.name\n )\n );\n }\n if (this.isCooled(cliId)) {\n return err(\n createCallerInputCliError(\n `OpenCode requested model \"${requested}\" (${cliId}) is in rate-limit cooldown.`,\n this.name\n )\n );\n }\n return ok({ cliId, reportedAs: reportedModelId(requested, cliId) });\n }\n\n /**\n * #6599: an explicitly requested model is resolved to an opencode id before\n * the run, and the response reports the model that ran so cost and outcome\n * attribution price it rather than the adapter default. With no requested\n * model the path is unchanged.\n */\n override async execute(\n task: CliTask,\n options?: ExecutionOptions\n ): Promise<Result<CliResponse, CliError>> {\n if (task.model === undefined) {\n // Preserve the base adapter's refusal before the model inventory probe.\n const refusal = await this.accessModeRefusal(task);\n if (refusal !== undefined) return err(refusal);\n }\n if (!this.initialized) await this.initialize();\n if (task.model === undefined) {\n // Record the route actually selected: an unavailable configured model\n // omits --model and runs OpenCode's default, not that configured route.\n const cliModel = resolveOpenCodeModel(this.model);\n const effectiveTask = this.isModelUsable(cliModel) ? { ...task, model: cliModel } : task;\n return super.execute(effectiveTask, options);\n }\n const resolved = this.resolveRequestedModel(task.model);\n if (!resolved.ok) return resolved;\n const { cliId, reportedAs } = resolved.value;\n const result = await super.execute({ ...task, model: cliId }, options);\n if (!result.ok) return result;\n return ok({ ...result.value, model: reportedAs });\n }\n\n /** Appends --model if the resolved model is usable (#1402, #3407, #3408). */\n private appendModelArg(args: string[], task: CliTask): void {\n if (task.model !== undefined) {\n // Explicit request: already resolved by execute(). Never dropped — an\n // id opencode does not know fails loudly in opencode itself.\n args.push('--model', this.matchInventory(task.model) ?? resolveOpenCodeModel(task.model));\n return;\n }\n const cliModel = resolveOpenCodeModel(this.model);\n\n if (this.isModelUsable(cliModel)) {\n args.push('--model', cliModel);\n } else {\n logger.debug('Model not usable (unavailable or cooled), using OpenCode default', {\n requested: cliModel,\n available: this.availableModels?.size ?? 0,\n });\n }\n }\n\n /**\n * #3408: mark a model in rate-limit cooldown when a call returns RATE_LIMITED,\n * so subsequent selections skip it until the AvailabilityCache TTL recovers.\n * Wraps the base executeTask; opt-in + fail-open (no-op when discovery is off).\n * An explicitly requested model in cooldown is refused by execute() (#6599).\n */\n override async executeTask(\n task: CliTask,\n options: ResolvedExecutionOptions\n ): Promise<Result<CliResponse, CliError>> {\n const result = await super.executeTask(task, options);\n if (isDynamicModelsEnabled() && !result.ok && result.error.code === 'RATE_LIMITED') {\n const cliModel = resolveOpenCodeModel(task.model ?? this.model);\n getAvailabilityCache().markUnavailable(cliModel as ModelId, 'rate-limited (429)');\n logger.debug('Cooldown: marked model rate-limited (#3408)', { model: cliModel });\n }\n return result;\n }\n\n /** Appends optional task flags (workDir, variant, thinking). */\n private appendTaskFlags(args: string[], task: CliTask): void {\n const workDir = task.options?.['workDir'];\n if (typeof workDir === 'string' && workDir.length > 0) {\n args.push('--dir', workDir);\n }\n const variant = task.options?.['variant'];\n if (typeof variant === 'string' && ALLOWED_VARIANTS.includes(variant)) {\n args.push('--variant', variant);\n }\n if (task.options?.['thinking'] === true) {\n args.push('--thinking');\n }\n }\n\n /**\n * Gets CLI command and arguments for execution.\n * Uses `opencode run` with JSON format for stable parsing.\n * Omits --model when the adapter default isn't available (#1402).\n */\n protected getCommand(task: CliTask): CommandConfig {\n const args: string[] = ['run', '--format', 'json'];\n this.appendModelArg(args, task);\n this.appendTaskFlags(args, task);\n\n // Honor systemPrompt by prepending to stdin content (#1886).\n // OpenCode CLI has no --system-prompt or --policy equivalent, so\n // prepend is the only option. This loses the formal system-role\n // distinction, but satisfies the contract that systemPrompt\n // influences the call (far better than silently dropping it).\n const content =\n task.systemPrompt !== undefined && task.systemPrompt !== ''\n ? `${task.systemPrompt}\\n\\n---\\n\\n${task.content}`\n : task.content;\n\n return { command: 'opencode', args, stdin: content };\n }\n\n /**\n * (#2540) Lists models the local OpenCode installation can route to.\n * Wraps the existing `probeAvailableModels()` (cached for the process\n * lifetime — see `cachedModels` at the top of this file) and reshapes\n * the result into the CliModelInfo schema. Splits `provider/model` ids\n * when present.\n */\n async listModels(): Promise<readonly CliModelInfo[]> {\n const ids = await probeAvailableModels();\n const out: CliModelInfo[] = [];\n for (const raw of ids) {\n const slash = raw.indexOf('/');\n if (slash > 0 && slash < raw.length - 1) {\n out.push({ id: raw, provider: raw.slice(0, slash) });\n } else {\n out.push({ id: raw });\n }\n }\n return out;\n }\n}\n\n/** Resets model probe cache (for testing). */\nexport function resetOpenCodeModelCache(): void {\n cachedModels = undefined;\n}\n","/**\n * nexus-agents/cli-adapters - OpenCode CLI Response Parser\n *\n * Defensive parser for OpenCode CLI JSON output.\n * Handles `opencode run --format json` NDJSON event stream.\n *\n * Real opencode v1.2.x NDJSON format (verified via E2E testing):\n * {\"type\":\"step_start\",\"sessionID\":\"ses_...\",\"part\":{\"type\":\"step-start\",...}}\n * {\"type\":\"text\",\"sessionID\":\"ses_...\",\"part\":{\"type\":\"text\",\"text\":\"Hello!\",...}}\n * {\"type\":\"step_finish\",\"sessionID\":\"ses_...\",\"part\":{\"type\":\"step-finish\",\"tokens\":{...},...}}\n *\n * (Source: Issue #1124, #1244, opencode.ai/docs/cli/)\n */\n\nimport type { ICliResponseParser, TokenUsage } from '../types.js';\nimport { asRecord, extractNumberField } from '../../utils/type-coercion.js';\nimport { createLogger } from '../../core/index.js';\n\nconst logger = createLogger({ component: 'opencode-parser' });\n\n/**\n * OpenCode CLI NDJSON event types.\n * Includes both real v1.2.x types and legacy assumed types for compatibility.\n */\nexport type OpenCodeEventType =\n // Real opencode v1.2.x event types\n | 'step_start'\n | 'text'\n | 'tool_use'\n | 'step_finish'\n | 'error'\n // Legacy assumed types (maintained for backward compatibility)\n | 'session.start'\n | 'message.start'\n | 'message.delta'\n | 'message.complete'\n | 'session.complete';\n\n/**\n * Aggregated OpenCode response from NDJSON stream.\n */\nexport interface OpenCodeCliResponse {\n readonly sessionId?: string;\n readonly content: string;\n readonly usage?: TokenUsage;\n /**\n * Concatenated error-event messages emitted during the NDJSON stream.\n * Set whenever `{\"type\":\"error\",...}` events appeared. Independent of\n * whether `content` is empty — if both are populated the model produced\n * text and then errored, callers can decide what to do.\n * #2821: previously error events were folded into `content` (making\n * failures look like successful responses to consensus voters/routers).\n */\n readonly errorMessage?: string;\n}\n\n/** Internal state from processing NDJSON lines. */\ninterface NdjsonParseState {\n readonly sessionId: string | undefined;\n readonly contentParts: string[];\n readonly errorMessages: string[];\n readonly usage: TokenUsage | undefined;\n readonly hasStepEvents: boolean;\n readonly hasAnyRecognizedEvent: boolean;\n readonly finishReason: string | undefined;\n}\n\n/** Mutable collectors shared by event handlers. */\ninterface NdjsonCollectors {\n readonly contentParts: string[];\n readonly errorMessages: string[];\n finishReason: string | undefined;\n}\n\n/**\n * Parser for OpenCode CLI JSON output.\n * Handles NDJSON event stream from `opencode run --format json`.\n *\n * Supports both real opencode v1.2.x format and legacy assumed format.\n */\nexport class OpenCodeResponseParser implements ICliResponseParser<OpenCodeCliResponse> {\n readonly name = 'opencode-parser';\n readonly supportedVersionRange = '>=1.0.0 <2.0.0';\n\n /**\n * Parses complete OpenCode CLI NDJSON stream.\n */\n parse(raw: string): OpenCodeCliResponse | null {\n const lines = raw.trim().split('\\n');\n const state = this.processAllLines(lines);\n\n const errorMessage =\n state.errorMessages.length > 0\n ? state.errorMessages.join('; ')\n : state.hasAnyRecognizedEvent\n ? this.terminalError(state.finishReason, state.contentParts.join(''))\n : undefined;\n\n if (state.contentParts.length === 0) {\n // #2821: error-only streams must surface as failure. Empty content +\n // errorMessage set causes extractResponse() to return null, which the\n // subprocess-adapter then classifies as EXECUTION_ERROR — instead of\n // wrapping `[OpenCode error: ...]` in ok() and feeding it to voters.\n if (errorMessage !== undefined) {\n return this.buildResponse('', state.sessionId, state.usage, errorMessage);\n }\n return this.handleEmptyContent(raw, lines.length, state);\n }\n\n return this.buildResponse(\n state.contentParts.join(''),\n state.sessionId,\n state.usage,\n errorMessage\n );\n }\n\n /** AI SDK terminal reasons: unverified endings never authorize a successful turn (#7073). */\n private terminalError(reason: string | undefined, content: string): string | undefined {\n switch (reason) {\n case 'stop':\n return undefined;\n case 'length':\n // CliResponse has no truncation field; retain the produced partial text.\n return content.trim() !== '' ? undefined : 'OpenCode length ending produced no text';\n case 'content-filter':\n case 'error':\n case 'tool-calls':\n case 'other':\n case 'unknown':\n default:\n return `OpenCode turn did not finish successfully: ${reason ?? 'missing terminal reason'}`;\n }\n }\n\n /** Processes all NDJSON lines and returns aggregated state. */\n private processAllLines(lines: readonly string[]): NdjsonParseState {\n let sessionId: string | undefined;\n const contentParts: string[] = [];\n const errorMessages: string[] = [];\n const collectors: NdjsonCollectors = { contentParts, errorMessages, finishReason: undefined };\n let usage: TokenUsage | undefined;\n let hasStepEvents = false;\n let hasAnyRecognizedEvent = false;\n\n for (let idx = 0; idx < lines.length; idx++) {\n const line = lines[idx];\n if (line === undefined || line.trim() === '') continue;\n const hadEvent = this.processLine(\n line,\n collectors,\n (id) => (sessionId = id),\n (u) => (usage = u),\n idx\n );\n if (hadEvent) hasStepEvents = true;\n if (hadEvent || this.isRecognizedLegacyEvent(line)) hasAnyRecognizedEvent = true;\n }\n\n return {\n sessionId,\n contentParts,\n errorMessages,\n usage,\n hasStepEvents,\n hasAnyRecognizedEvent,\n finishReason: collectors.finishReason,\n };\n }\n\n /** Handles the case where no text content was extracted from NDJSON. */\n private handleEmptyContent(\n raw: string,\n lineCount: number,\n state: NdjsonParseState\n ): OpenCodeCliResponse | null {\n // Tool-only responses have step_start/step_finish but no text events.\n if (state.hasStepEvents && state.finishReason === 'stop') {\n return this.buildResponse(\n '[Tool-only response — no text output]',\n state.sessionId,\n state.usage\n );\n }\n // Fallback: try parsing as plain JSON (non-streaming mode)\n logger.debug('No NDJSON content extracted, trying JSON fallback', {\n rawLength: raw.length,\n lineCount,\n hasStepEvents: state.hasStepEvents,\n hasAnyRecognizedEvent: state.hasAnyRecognizedEvent,\n });\n return this.parsePlainJson(raw);\n }\n\n /** Builds an OpenCodeCliResponse from parsed components. */\n private buildResponse(\n content: string,\n sessionId: string | undefined,\n usage: TokenUsage | undefined,\n errorMessage?: string\n ): OpenCodeCliResponse {\n return {\n content,\n ...(sessionId !== undefined && { sessionId }),\n ...(usage !== undefined && { usage }),\n ...(errorMessage !== undefined && { errorMessage }),\n };\n }\n\n /**\n * Extracts just the response text.\n */\n extractResponse(raw: string): string | null {\n const parsed = this.parse(raw);\n if (parsed === null || parsed.content === '' || parsed.errorMessage !== undefined) {\n logger.debug('extractResponse returned null', {\n rawLength: raw.length,\n snippet: raw.slice(0, 100),\n parsedNull: parsed === null,\n });\n return null;\n }\n return parsed.content;\n }\n\n /**\n * Surfaces stream errors or an incomplete turn, including after partial\n * text. A terminal `stop`, or `length` with text, authorizes success. The subprocess adapter\n * consumes this when {@link extractResponse} returns `null`, so an upstream\n * 401 / rate-limit is classified by its message (NOT_AUTHENTICATED /\n * RATE_LIMITED with a remediation hint) instead of falling through to a\n * generic PARSE_ERROR.\n */\n extractErrorMessage(raw: string): string | null {\n return this.parse(raw)?.errorMessage ?? null;\n }\n\n /**\n * Extracts token usage from response.\n */\n extractUsage(raw: string): TokenUsage | null {\n const lines = raw.trim().split('\\n');\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n try {\n const event: unknown = JSON.parse(line);\n const record = asRecord(event);\n if (record === null) continue;\n\n // Real format: step_finish with nested part.tokens\n if (record.type === 'step_finish') {\n const usage = this.extractUsageFromPart(record);\n if (usage !== null) return usage;\n }\n\n // Legacy format: session.complete or message.complete with usage field\n if (record.type === 'session.complete' || record.type === 'message.complete') {\n const usage = this.extractUsageFromRecord(record);\n if (usage !== null) return usage;\n }\n } catch {\n continue;\n }\n }\n\n return null;\n }\n\n /**\n * Extracts session ID for resumption.\n */\n extractSessionId(raw: string): string | null {\n const lines = raw.trim().split('\\n');\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n const sid = this.extractSessionIdFromLine(line);\n if (sid !== null) return sid;\n }\n\n return null;\n }\n\n /** Extracts session ID from a single NDJSON line. */\n private extractSessionIdFromLine(line: string): string | null {\n try {\n const record = asRecord(JSON.parse(line) as unknown);\n if (record === null) return null;\n\n // Real format: sessionID at top level (step_start, text, step_finish)\n if (typeof record.sessionID === 'string') return record.sessionID;\n\n // Legacy format: session_id/sessionId in session events\n const sid = record.session_id ?? record.sessionId;\n if (typeof sid === 'string') return sid;\n\n return null;\n } catch {\n return null;\n }\n }\n\n /**\n * Processes a single NDJSON line.\n * Handles both real v1.2.x format and legacy assumed format.\n * Returns true if a real v1.2.x step event was processed (step_start/text/tool_use/step_finish).\n * Legacy events return false since they don't indicate tool-only responses.\n */\n private processLine(\n line: string,\n collectors: NdjsonCollectors,\n setSessionId: (id: string) => void,\n setUsage: (usage: TokenUsage) => void,\n lineIndex: number\n ): boolean {\n try {\n const record = asRecord(JSON.parse(line) as unknown);\n if (record === null) return false;\n\n const isReal = this.processRealEvent(record, collectors, setSessionId, setUsage);\n if (isReal) return true;\n\n this.processLegacyEvent(record, collectors, setSessionId, setUsage);\n return false;\n } catch {\n logger.debug('Skipped malformed NDJSON line', {\n lineNumber: lineIndex + 1,\n snippet: line.slice(0, 100),\n });\n return false;\n }\n }\n\n /** Processes real opencode v1.2.x event types. Returns true if handled. */\n private processRealEvent(\n record: Record<string, unknown>,\n collectors: NdjsonCollectors,\n setSessionId: (id: string) => void,\n setUsage: (usage: TokenUsage) => void\n ): boolean {\n switch (record.type) {\n case 'step_start':\n case 'tool_use':\n collectors.finishReason = undefined;\n this.handleRealSessionId(record, setSessionId);\n return true;\n case 'text':\n collectors.finishReason = undefined;\n this.handleRealSessionId(record, setSessionId);\n this.pushRealTextContent(record, collectors.contentParts);\n return true;\n case 'step_finish': {\n const reason = asRecord(record.part)?.reason;\n collectors.finishReason = typeof reason === 'string' ? reason : undefined;\n this.handleRealSessionId(record, setSessionId);\n this.emitRealUsage(record, setUsage);\n return true;\n }\n case 'error':\n this.handleRealSessionId(record, setSessionId);\n this.captureErrorMessage(record, collectors.errorMessages);\n return true;\n default:\n return false;\n }\n }\n\n /**\n * Captures an error-event message for the response's `errorMessage` field\n * (#2821). Previously this pushed `[OpenCode error: ...]` into `contentParts`,\n * which made error-only streams look like successful responses to consensus\n * voters and the routing learner.\n */\n private captureErrorMessage(record: Record<string, unknown>, errorMessages: string[]): void {\n const errorObj = asRecord(record.error);\n if (errorObj === null) {\n errorMessages.push('Unknown error');\n return;\n }\n\n const data = asRecord(errorObj.data);\n const message =\n data !== null && typeof data.message === 'string'\n ? data.message\n : typeof errorObj.name === 'string'\n ? errorObj.name\n : 'Unknown error';\n\n logger.warn('OpenCode returned error event', { message });\n errorMessages.push(message);\n }\n\n /** Processes legacy assumed event types. */\n private processLegacyEvent(\n record: Record<string, unknown>,\n collectors: NdjsonCollectors,\n setSessionId: (id: string) => void,\n setUsage: (usage: TokenUsage) => void\n ): void {\n switch (record.type) {\n case 'session.start':\n collectors.finishReason = undefined;\n this.handleLegacySessionStart(record, setSessionId);\n break;\n case 'message.start':\n collectors.finishReason = undefined;\n break;\n case 'message.delta':\n collectors.finishReason = undefined;\n this.pushLegacyTextContent(record, collectors.contentParts);\n break;\n case 'message.complete':\n this.pushLegacyTextContent(record, collectors.contentParts);\n collectors.finishReason = this.legacyFinishReason(record);\n this.emitLegacyUsage(record, setUsage);\n break;\n case 'session.complete':\n collectors.finishReason = this.legacyFinishReason(record);\n this.emitLegacyUsage(record, setUsage);\n break;\n }\n }\n\n /** Reads the terminal reason from legacy completion envelopes. */\n private legacyFinishReason(record: Record<string, unknown>): string | undefined {\n const reason = record.reason ?? record.finish_reason ?? record.finishReason;\n return typeof reason === 'string' ? reason : undefined;\n }\n\n // --- Real v1.2.x format handlers ---\n\n /** Extracts sessionID from top-level field (real format). */\n private handleRealSessionId(\n record: Record<string, unknown>,\n setSessionId: (id: string) => void\n ): void {\n if (typeof record.sessionID === 'string') setSessionId(record.sessionID);\n }\n\n /** Extracts text from nested part.text field (real format). */\n private pushRealTextContent(record: Record<string, unknown>, parts: string[]): void {\n const part = asRecord(record.part);\n if (part === null) return;\n\n if (typeof part.text === 'string') parts.push(part.text);\n }\n\n /** Extracts usage from nested part.tokens field (real format). */\n private emitRealUsage(\n record: Record<string, unknown>,\n setUsage: (usage: TokenUsage) => void\n ): void {\n const usage = this.extractUsageFromPart(record);\n if (usage !== null) setUsage(usage);\n }\n\n /** Extracts usage from part.tokens (real opencode v1.2.x format). */\n private extractUsageFromPart(record: Record<string, unknown>): TokenUsage | null {\n const part = asRecord(record.part);\n if (part === null) return null;\n\n const tokens = asRecord(part.tokens);\n if (tokens === null) return null;\n\n const inputTokens = extractNumberField(tokens, 'input');\n const outputTokens = extractNumberField(tokens, 'output');\n\n if (inputTokens === null || outputTokens === null) return null;\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n };\n }\n\n // --- Legacy format handlers ---\n\n /** Extracts session ID from a session event record (legacy format). */\n private handleLegacySessionStart(\n record: Record<string, unknown>,\n setSessionId: (id: string) => void\n ): void {\n const sid = record.session_id ?? record.sessionId;\n if (typeof sid === 'string') setSessionId(sid);\n }\n\n /** Pushes text content from a message event (legacy format). */\n private pushLegacyTextContent(record: Record<string, unknown>, parts: string[]): void {\n const text = record.content ?? record.delta ?? record.text;\n if (typeof text === 'string') parts.push(text);\n }\n\n /** Emits usage from a record (legacy format). */\n private emitLegacyUsage(\n record: Record<string, unknown>,\n setUsage: (usage: TokenUsage) => void\n ): void {\n const usage = this.extractUsageFromRecord(record);\n if (usage !== null) setUsage(usage);\n }\n\n /** Checks if a line contains a recognized legacy event type (without full parsing). */\n private isRecognizedLegacyEvent(line: string): boolean {\n try {\n const record = asRecord(JSON.parse(line) as unknown);\n if (record === null) return false;\n const t = record.type;\n return (\n t === 'session.start' ||\n t === 'message.start' ||\n t === 'message.delta' ||\n t === 'message.complete' ||\n t === 'session.complete'\n );\n } catch {\n return false;\n }\n }\n\n /** Reads inherited plain JSON fields without treating an unverified envelope as success. */\n private parsePlainJson(raw: string): OpenCodeCliResponse | null {\n try {\n const record = asRecord(JSON.parse(raw) as unknown);\n if (record === null) return null;\n const content = record.content ?? record.result ?? record.text ?? record.output;\n if (typeof content !== 'string') return null;\n const usage = this.extractUsageFromRecord(record);\n const sid = record.session_id ?? record.sessionId;\n return {\n content,\n errorMessage: 'OpenCode JSON envelope has no verified terminal event',\n ...(typeof sid === 'string' ? { sessionId: sid } : {}),\n ...(usage !== null ? { usage } : {}),\n };\n } catch {\n // #7073 supersedes #1402: --format json cannot authorize plaintext success.\n return null;\n }\n }\n\n /**\n * Extracts usage from a record with usage/token fields (legacy format).\n */\n private extractUsageFromRecord(record: Record<string, unknown>): TokenUsage | null {\n const usage = asRecord(record.usage);\n if (usage === null) return null;\n\n const inputTokens =\n extractNumberField(usage, 'input_tokens') ?? extractNumberField(usage, 'inputTokens');\n const outputTokens =\n extractNumberField(usage, 'output_tokens') ?? extractNumberField(usage, 'outputTokens');\n\n if (inputTokens === null || outputTokens === null) return null;\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n };\n }\n}\n","/**\n * nexus-agents/cli-adapters - `codex mcp-server` transport probe (#6119)\n *\n * codex-cli 0.154.0 removed the `mcp-server` subcommand: `codex --help` lists\n * only `mcp` (manage external MCP servers), and `codex mcp-server` forwards to\n * the interactive CLI, which dies with `stdin is not a terminal` under a pipe.\n * The MCP transport (`CodexMcpAdapter`) spawns exactly that, so every codex\n * voter seat errored while `doctor` still printed \"Ready (Codex mcp-server)\"\n * — a verdict inferred from the install, not measured.\n *\n * This probe measures. It runs `codex mcp-server --help` with stdin CLOSED\n * (`stdio: ['ignore', 'pipe', 'pipe']`) so a codex that forwards to the\n * interactive CLI cannot block on a terminal, and reports the subcommand\n * available only when the process exits 0 AND its stdout names `mcp-server`.\n * On 0.154.0 the forwarded `--help` exits 0 with the TOP-LEVEL help, which\n * lists `mcp` but never `mcp-server` — hence both conditions.\n *\n * The default exec's verdict is cached per process: the binary does not\n * change under a running server, and the factory is synchronous and called on\n * every adapter construction.\n *\n * @module cli-adapters/codex-mcp-server-probe\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { CLI_SUBPROCESS_TIMEOUTS } from '../config/timeouts.js';\n\n/** What the probe needs back from running a command: exit status and stdout. */\nexport interface CodexMcpServerProbeResult {\n /** Exit code, or `null` when the process could not be spawned or was killed. */\n readonly exitCode: number | null;\n readonly stdout: string;\n}\n\n/**\n * Synchronous command runner the probe is written against. Injectable so the\n * verdict can be tested against recorded help texts without a codex binary.\n */\nexport type CodexMcpServerProbeExec = (\n command: string,\n args: readonly string[]\n) => CodexMcpServerProbeResult;\n\n/** One-line cause, shared by the doctor line and the typed error. */\nexport const CODEX_MCP_SERVER_UNAVAILABLE_REASON = 'codex-cli ≥0.154 has no mcp-server subcommand';\n\n/**\n * Thrown when a caller demands the `mcp` codex transport explicitly and the\n * installed codex cannot serve it. Named so the cause is readable at the\n * throw site instead of surfacing later as a `stdin is not a terminal` exit\n * from a doomed `codex mcp-server` spawn.\n */\nexport class CodexMcpServerUnavailableError extends Error {\n constructor() {\n super(\n `Codex transport 'mcp' was requested but ${CODEX_MCP_SERVER_UNAVAILABLE_REASON}; ` +\n \"use transport 'subprocess' (codex exec) or leave the transport unset to auto-select\"\n );\n this.name = 'CodexMcpServerUnavailableError';\n }\n}\n\nconst PROBE_ARGS: readonly string[] = ['mcp-server', '--help'];\n/** Word-bounded so the sibling `mcp` subcommand in the top-level help cannot match. */\nconst SUBCOMMAND_PATTERN = /\\bmcp-server\\b/;\n\n/** Run the probe command synchronously; a spawn failure or a timeout is `exitCode: null`. */\nconst defaultExec: CodexMcpServerProbeExec = (command, args) => {\n try {\n const stdout = execFileSync(command, [...args], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: CLI_SUBPROCESS_TIMEOUTS.statusProbeMs,\n });\n return { exitCode: 0, stdout };\n } catch (error: unknown) {\n const status = (error as { status?: unknown }).status;\n const stdout = (error as { stdout?: unknown }).stdout;\n return {\n exitCode: typeof status === 'number' ? status : null,\n stdout: typeof stdout === 'string' ? stdout : '',\n };\n }\n};\n\nlet cachedDefaultVerdict: boolean | undefined;\n\n/**\n * Whether the installed codex serves the `mcp-server` subcommand.\n *\n * With no argument the default exec runs once per process and the verdict is\n * cached. An injected exec is run on every call and never cached — the caller\n * owns it.\n */\nexport function codexMcpServerAvailable(exec?: CodexMcpServerProbeExec): boolean {\n if (exec !== undefined) return probe(exec);\n cachedDefaultVerdict ??= probe(defaultExec);\n return cachedDefaultVerdict;\n}\n\nfunction probe(exec: CodexMcpServerProbeExec): boolean {\n const { exitCode, stdout } = exec('codex', PROBE_ARGS);\n return exitCode === 0 && SUBCOMMAND_PATTERN.test(stdout);\n}\n","/**\n * nexus-agents/cli-adapters - Adapter Factory\n *\n * Factory for creating CLI adapters based on configuration.\n * Supports optional caching of CLI health check results.\n *\n * (Source: cli-project_plan.md v2.1.0)\n * (Source: Issue #90 - Codex MCP adapter)\n * (Source: Issue #165 - CLI detection cache)\n */\n\nimport type { ICliAdapter, CliName, RoutingArmId, CliTransport } from './types.js';\nimport { isEndpointArmId } from './types.js';\nimport { getGlobalRegistry } from '../adapters/unified-registry.js';\nimport { readOpenAICompatEndpoint } from '../adapters/openai-compat-adapter.js';\nimport { parseBoolEnv } from '../config/defaults-env.js';\nimport { gatewayCostGap, resolveGatewayCostDeclaration } from '../adapters/sdk/gateway-cost.js';\nimport { createModelToCliAdapter } from './model-to-cli-adapter.js';\nimport { createLogger, getTimeProvider } from '../core/index.js';\nimport { collectApiRoutingArms } from '../adapters/auto-adapter.js';\nimport { ClaudeCliAdapter } from './adapters/claude-adapter.js';\nimport { GeminiCliAdapter } from './adapters/gemini-adapter.js';\nimport { CodexCliAdapter } from './adapters/codex-adapter.js';\nimport { CodexMcpAdapter } from './adapters/codex-mcp-adapter.js';\nimport { OpenCodeCliAdapter } from './adapters/opencode-adapter.js';\nimport type { ILogger } from '../core/index.js';\nimport type { ICliDetectionCache } from './cli-detection-cache.js';\nimport { CliDetectionCache, createCliDetectionCache } from './cli-detection-cache.js';\nimport { probeCli } from '../cli/cli-auth-probe.js';\nimport { cliAuthBlocks, isCliAdmitted } from './cli-admission.js';\nimport { getCliCircuitBreakerSnapshot } from './cli-circuit-breaker.js';\nimport { isCliDisabled } from './disabled-clis.js';\nimport { buildGatewaySlotRouterArm, gatewaySlotEndpointOf } from './gateway-slot-arm.js';\nimport {\n codexMcpServerAvailable,\n CodexMcpServerUnavailableError,\n CODEX_MCP_SERVER_UNAVAILABLE_REASON,\n} from './codex-mcp-server-probe.js';\n\nconst factoryLogger = createLogger({ component: 'cli-adapter-factory' });\n\n/**\n * Configuration for creating a CLI adapter.\n */\nexport interface CliAdapterConfig {\n /** Which CLI to use */\n readonly cli: CliName;\n /** Optional model override */\n readonly model?: string;\n /** Optional logger */\n readonly logger?: ILogger;\n /**\n * Transport for Codex: `'mcp'` or `'subprocess'`. Unset selects by probe\n * (#6119): `mcp` when the installed codex serves `mcp-server`, otherwise\n * `subprocess` (`codex exec`). An explicit `'mcp'` on a codex without the\n * subcommand throws {@link CodexMcpServerUnavailableError} at construction.\n */\n readonly transport?: CliTransport;\n}\n\n/**\n * Creates a CLI adapter based on configuration.\n *\n * @param config - Adapter configuration\n * @returns The configured CLI adapter\n * @throws Error if CLI name is not supported\n *\n * @example\n * ```typescript\n * const adapter = createCliAdapter({ cli: 'claude', model: 'claude-opus-4' });\n * const result = await adapter.execute({ content: 'Hello!' });\n * ```\n */\nexport function createCliAdapter(config: CliAdapterConfig): ICliAdapter {\n const options = {\n ...(config.model !== undefined && { model: config.model }),\n ...(config.logger !== undefined && { logger: config.logger }),\n };\n\n switch (config.cli) {\n case 'claude':\n return new ClaudeCliAdapter(options);\n\n case 'gemini':\n return new GeminiCliAdapter(options);\n\n case 'codex':\n return createCodexAdapter(config.transport, options);\n\n case 'opencode':\n return new OpenCodeCliAdapter(options);\n\n default: {\n const exhaustiveCheck: never = config.cli;\n throw new Error(`Unsupported CLI: ${String(exhaustiveCheck)}`);\n }\n }\n}\n\n/**\n * Creates a Codex adapter for the requested transport.\n *\n * The MCP transport was the default since #90. codex-cli 0.154 removed the\n * `mcp-server` subcommand it spawns (#6119), so an unset transport now follows\n * the probe: `mcp` only when the installed codex serves it, otherwise the\n * subprocess transport, which already carries the #6093 landlock flag and the\n * #6101 stderr capture. An explicit `'mcp'` that the probe refuses throws a\n * typed error naming the cause rather than spawning a process that dies with\n * `stdin is not a terminal`.\n *\n * @param transport - `'mcp'`, `'subprocess'`, or `undefined` to select by probe\n * @param options - Adapter options\n * @returns Codex CLI adapter\n * @throws CodexMcpServerUnavailableError when `'mcp'` is demanded but unavailable\n */\nfunction createCodexAdapter(\n transport: CliTransport | undefined,\n options: { model?: string; logger?: ILogger }\n): ICliAdapter {\n if (transport === 'subprocess') {\n return new CodexCliAdapter(options);\n }\n const mcpServerAvailable = codexMcpServerAvailable();\n if (transport === 'mcp') {\n if (!mcpServerAvailable) throw new CodexMcpServerUnavailableError();\n return new CodexMcpAdapter(options);\n }\n if (mcpServerAvailable) return new CodexMcpAdapter(options);\n (options.logger ?? factoryLogger).debug('Codex transport selected by probe: subprocess', {\n reason: CODEX_MCP_SERVER_UNAVAILABLE_REASON,\n });\n return new CodexCliAdapter(options);\n}\n\n/**\n * Creates all available routing-arm adapters.\n * Codex transport is selected by probe unless one is passed (#6119).\n *\n * The four CLI slots are registered under their slot key. In gateway mode a\n * vendor slot whose CLI is not available (`isCliAvailable`, the predicate\n * `createAutoAdapter` uses) is served by a gateway model of its family, and a\n * slot with neither a usable binary nor a family model is omitted (#6604,\n * `gateway-slot-arm.ts`). `NEXUS_DISABLED_CLIS` is transport-scoped (#6720):\n * a disabled CLI counts as \"not available\", so its family's gateway model\n * still serves the slot; without a gateway catalogue a disabled CLI's slot is\n * omitted (#6590), and every CLI disabled yields an empty map. When\n * `NEXUS_BILLING_MODE=api`, the direct-API adapters whose keys are present are\n * ALSO appended as distinct `api:<vendor>` routing arms (#3422) so the router /\n * bandit can score them separately from the CLI slots. DEFAULT (plan) mode\n * adds no endpoint arms. NEXUS_ROUTE_GATEWAY_ARMS explicitly opts in to\n * registered endpoint arms in either mode, with a required cost declaration.\n * Endpoints already reachable through family slots (even an undecided slot)\n * are omitted, avoiding duplicate endpoint history and breaker identities.\n * Construction never discovers endpoints or validates keys by calling out.\n *\n * @param logger - Optional shared logger\n * @param codexTransport - Transport for Codex; unset selects by probe\n * @returns Map of routing arm id to adapter\n */\nexport function createAllAdapters(\n logger?: ILogger,\n codexTransport?: CliTransport\n): Map<RoutingArmId, ICliAdapter> {\n const adapters = new Map<RoutingArmId, ICliAdapter>();\n const options = logger !== undefined ? { logger } : undefined;\n\n const slots: ReadonlyArray<readonly [CliName, () => ICliAdapter]> = [\n ['claude', () => new ClaudeCliAdapter(options)],\n ['gemini', () => new GeminiCliAdapter(options)],\n ['codex', () => createCodexAdapter(codexTransport, options ?? {})],\n ['opencode', () => new OpenCodeCliAdapter(options)],\n ];\n // #6720: NEXUS_DISABLED_CLIS is transport-scoped. A disabled CLI is \"CLI not\n // available\": its family's gateway model serves the slot when there is one,\n // and otherwise the slot has no arm. `create` is never called for it, so a\n // disabled codex is not even probed for its transport.\n const isAvailable = sharedSlotAvailability();\n for (const [cli, create] of slots) {\n const arm = buildGatewaySlotRouterArm(cli, create, isAvailable, logger);\n if (arm === 'unavailable') continue;\n adapters.set(cli, arm ?? create());\n }\n\n // API arms enter the router only in explicit api billing mode (#3422).\n if (process.env['NEXUS_BILLING_MODE'] === 'api') {\n for (const { armId, adapter } of collectApiRoutingArms(logger)) {\n adapters.set(armId, adapter);\n }\n }\n\n appendRegisteredEndpointArms(adapters, logger ?? factoryLogger);\n return adapters;\n}\n\n/** Admit declared endpoints only under operator opt-in; CLI slots remain raw (#5191). */\nfunction appendRegisteredEndpointArms(\n adapters: Map<RoutingArmId, ICliAdapter>,\n logger: ILogger\n): void {\n if (!parseBoolEnv('NEXUS_ROUTE_GATEWAY_ARMS', false)) return;\n const registry = getGlobalRegistry();\n const configuredArm = `api:${readOpenAICompatEndpoint(process.env, logger)}`;\n const slotEndpoints = new Set([...adapters.values()].map(gatewaySlotEndpointOf));\n for (const arm of registry.getSnapshot().cachedArms) {\n if (!isEndpointArmId(arm)) continue;\n if (slotEndpoints.has(arm)) {\n logger.debug('Gateway routing arm omitted: family slot already represents endpoint', { arm });\n continue;\n }\n if (resolveGatewayCostDeclaration(arm) === undefined) {\n logger.warn('Gateway routing arm excluded: NEXUS_GATEWAY_COST declaration required', {\n arm,\n reason: gatewayCostGap(arm),\n });\n continue;\n }\n const endpoint = registry.getAdapterForArm(arm);\n if (endpoint === undefined) continue;\n // The legacy single-model API arm reads the same configured URL/key.\n // Replace it only on successful admission; flag-off and exclusions retain it.\n if (arm === configuredArm) adapters.delete('api:custom-openai');\n adapters.set(arm, createModelToCliAdapter(endpoint, { name: arm }));\n }\n}\n\n/**\n * The availability predicate the gateway-mode router arms of ONE\n * `createAllAdapters` call share (#6604): `isCliAvailable`, the predicate\n * `createAutoAdapter` uses, over one detection cache created on first use;\n * `fresh` invalidates the cached answer for that CLI first.\n */\nfunction sharedSlotAvailability(): (cli: CliName, fresh: boolean) => Promise<boolean> {\n let cache: ICliDetectionCache | undefined;\n return (cli, fresh) => {\n cache ??= createCliDetectionCache();\n // A re-check after an availability failure must probe again, not read\n // the cached \"available\" that committed the arm to the CLI.\n if (fresh) cache.invalidate(cli);\n return isCliAvailable(cli, cache);\n };\n}\n\n/**\n * Checks if a CLI is available by running a health check.\n * Uses cache if provided to avoid repeated subprocess calls.\n *\n * @param cli - CLI name to check\n * @param cache - Optional cache to use\n * @returns True if CLI is healthy\n */\nexport async function isCliAvailable(cli: CliName, cache?: ICliDetectionCache): Promise<boolean> {\n // Check cache first\n if (cache !== undefined) {\n const cached = cache.get(cli);\n if (cached !== undefined) {\n return cached.healthy;\n }\n }\n\n try {\n const adapter = createCliAdapter({ cli });\n // Pre-#2725 only ran healthCheck() — which confirms the binary exists\n // and runs but does NOT probe authentication. Result: orchestrate listed\n // opencode as \"Available\" when the user wasn't logged in, and the next\n // call failed with an opaque subprocess error. Auth must agree with the\n // probe doctor already uses (cli-auth-probe.ts, #2447).\n const [health, auth] = await Promise.all([adapter.healthCheck(), probeCli(cli)]);\n const authBlocks = cliAuthBlocks(auth);\n const available = isCliAdmitted(health, auth);\n\n // Store in cache if provided. Synthesize a degraded health record when\n // the binary is healthy but auth failed, so downstream consumers see\n // \"unavailable\" without losing the version string.\n if (cache !== undefined) {\n if (available) {\n cache.set(cli, CliDetectionCache.fromHealthStatus(health));\n } else {\n cache.set(cli, {\n healthy: false,\n version: health.version,\n versionStatus: health.versionStatus,\n checkedAt: new Date(),\n message: authBlocks\n ? `auth: ${auth.state}` + ('reason' in auth ? ` (${auth.reason})` : '')\n : health.message,\n });\n }\n }\n\n return available;\n } catch (error: unknown) {\n // Closes #2952 (medium): pre-fix the bare `catch {}` dropped the error\n // entirely — operators saw `<cli>: unavailable` with no way to tell\n // whether the binary was missing, the probe timed out, or some other\n // failure occurred. Now include the message in the cached entry.\n cacheHealthCheckFailure(cache, cli, error);\n return false;\n }\n}\n\n/** Records a health-check exception in the cache with the error message preserved. */\nfunction cacheHealthCheckFailure(\n cache: ICliDetectionCache | undefined,\n cli: CliName,\n error: unknown\n): void {\n if (cache === undefined) return;\n const message = error instanceof Error ? error.message : String(error);\n cache.set(cli, {\n healthy: false,\n version: 'unknown',\n versionStatus: 'unsupported',\n checkedAt: new Date(getTimeProvider().now()),\n message: `Health check failed: ${message}`,\n });\n}\n\n/**\n * Gets all available CLIs by running health checks.\n * Uses cache if provided to avoid repeated subprocess calls. CLIs disabled by\n * `NEXUS_DISABLED_CLIS` are excluded (#6590); disabling every CLI yields `[]`.\n *\n * @param cache - Optional cache to use\n * @returns Array of available CLI names\n */\nexport async function getAvailableClis(cache?: ICliDetectionCache): Promise<CliName[]> {\n // #6590: disabled CLIs are dropped before probing, so none spends a probe.\n const clis = (['claude', 'gemini', 'codex', 'opencode'] as const).filter(\n (cli) => !isCliDisabled(cli)\n );\n\n // Check all CLIs in parallel to avoid sequential timeout penalties\n const results = await Promise.allSettled(\n clis.map(async (cli) => ({ cli, available: await isCliAvailable(cli, cache) }))\n );\n\n return results\n .filter(\n (r): r is PromiseFulfilledResult<{ cli: CliName; available: boolean }> =>\n r.status === 'fulfilled' && r.value.available\n )\n .filter((r) => isCliServingForVoters(r.value.cli))\n .map((r) => r.value.cli);\n}\n\nfunction isCliServingForVoters(cli: CliName): boolean {\n try {\n const snapshot = getCliCircuitBreakerSnapshot(cli);\n if (snapshot?.state !== 'open') {\n return true;\n }\n factoryLogger.warn('CLI excluded from voter availability because circuit is open', {\n cli,\n circuitState: snapshot.state,\n failureCount: snapshot.failureCount,\n });\n return false;\n } catch {\n return true;\n }\n}\n"],"mappings":"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","names":["Anthropic","Anthropic","logger","logger","logger","logger","z","join","logger","logger","result","logger","statSync","join","join","codexHome","join","join","statSync","join","resolve","execFile","logger","logger","resolve","execFile","cliId","defaultExec","probe","logger"]}