@iislee/opencodex 2.11.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -1,9 +1,8 @@
1
1
  import type { OcxProviderConfig } from "../types";
2
- import { getValidAccessToken } from "../oauth";
2
+ import { getValidAccessToken, publicOAuthAuthenticationErrorMessage } from "../oauth";
3
3
  import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/anthropic";
4
4
  import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fingerprint";
5
5
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
6
- import { redactSecretString } from "../lib/redact";
7
6
  import { sidecarEnter } from "../lib/sidecar-tracker";
8
7
  import { fetchWithResetRetry } from "../lib/upstream-retry";
9
8
  import type { WebSearchSource } from "./parse";
@@ -127,7 +126,7 @@ export async function runAnthropicWebSearch(
127
126
  try {
128
127
  token = await getValidAccessToken(providerName);
129
128
  } catch (e) {
130
- return { text: "", sources: [], error: `anthropic sidecar auth failed: ${e instanceof Error ? e.message : String(e)}` };
129
+ return { text: "", sources: [], error: `anthropic sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(e)}` };
131
130
  }
132
131
  const headers: Record<string, string> = {
133
132
  "Content-Type": "application/json",
@@ -166,13 +165,20 @@ export async function runAnthropicWebSearch(
166
165
  () => fetch(url, { method: "POST", headers, body: JSON.stringify(body), signal: linkedSignal.signal }),
167
166
  { abortSignal: linkedSignal.signal, label: "web-search-sidecar-anthropic" },
168
167
  );
168
+ // Guard before any branch reads the body: the failure branch's `res.text()` ran ahead of
169
+ // the success-path guard, reopening the fetch-resolution-to-reader-attach race
170
+ // (found investigating #1419).
171
+ const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
169
172
  if (!res.ok) {
170
173
  const t = await res.text().catch(() => "");
174
+ detachBodyGuard();
171
175
  console.warn(`[web-search] anthropic sidecar HTTP ${res.status} for query "${query.slice(0, 80)}" (${Date.now() - t0}ms)`);
172
- // Redact before surfacing: the body can echo auth headers/tokens (#398 review).
173
- return { text: "", sources: [], error: `sidecar HTTP ${res.status}: ${redactSecretString(t.slice(0, 200))}` };
176
+ if (res.status === 401) {
177
+ return { text: "", sources: [], error: `anthropic sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(new Error(t))}` };
178
+ }
179
+ // Upstream bodies are untrusted and may contain credentials, paths, or provider diagnostics.
180
+ return { text: "", sources: [], error: `sidecar HTTP ${res.status}` };
174
181
  }
175
- const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
176
182
  try {
177
183
  return await parseAnthropicSidecarSSE(res);
178
184
  } finally {
@@ -181,7 +187,7 @@ export async function runAnthropicWebSearch(
181
187
  } catch (e) {
182
188
  const kind = e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error";
183
189
  console.warn(`[web-search] anthropic sidecar ${kind} for query "${query.slice(0, 80)}" (${Date.now() - t0}ms)`);
184
- return { text: "", sources: [], error: e instanceof Error ? e.message : String(e) };
190
+ return { text: "", sources: [], error: `anthropic sidecar ${kind}` };
185
191
  } finally {
186
192
  sidecarExit();
187
193
  linkedSignal.cleanup();
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Which backends may RUN a hosted web_search, and which candidate rows each
3
+ * can run (#2188 rule 2 for web-search: ∩ probed backend with an executor).
4
+ *
5
+ * A backend registers here only when BOTH hold:
6
+ * - an executor exists in this repository (src/web-search/executor.ts or
7
+ * anthropic-executor.ts today), and
8
+ * - its liveness probe passes. For the two shipped backends the probe IS
9
+ * auth presence — the ChatGPT forward path and the stored Anthropic OAuth
10
+ * path fail closed without a credential, so a live credential is the
11
+ * strongest pre-flight signal short of spending a search.
12
+ *
13
+ * Future backends (Gemini google_search, Grok web_search, Zen hosted search,
14
+ * Exa-class vendors) stay OUT of this table until a live probe and an
15
+ * executor land — the research and probe contracts are recorded in
16
+ * devlog/_plan/260820_sidecar_selection_unification/002 and 031. Documenting
17
+ * a tool is not the same as being able to run it.
18
+ */
19
+ import type { OcxConfig } from "../types";
20
+ import { AUTH_SLOT_MODELS, type SidecarAuthState } from "../sidecar/auth";
21
+ import type { SidecarCandidate } from "../sidecar/candidates";
22
+ import { getAccountSet } from "../oauth/store";
23
+ import type { WebSearchBackendId } from "./index";
24
+
25
+ export interface WebSearchBackendDescriptor {
26
+ backend: WebSearchBackendId;
27
+ /** Liveness signal for this backend (auth presence for the shipped two). */
28
+ isActive(auth: SidecarAuthState, config: OcxConfig): boolean;
29
+ /** Which candidate rows this backend's executor can actually run. */
30
+ eligibleModel(candidate: SidecarCandidate, auth: SidecarAuthState): boolean;
31
+ }
32
+
33
+ export const WEB_SEARCH_BACKENDS: readonly WebSearchBackendDescriptor[] = [
34
+ {
35
+ backend: "openai",
36
+ isActive: auth => auth.isCodexAuth,
37
+ // The ChatGPT forward executor runs BARE native slugs and the Codex auth
38
+ // slot — settings.model is POSTed verbatim to the forward /responses, so
39
+ // an account-bound "selector/slug" row (model-rows emits those as
40
+ // provider "openai", native true) or a custom openai-keyed row would
41
+ // persist an id the executor cannot run (review F1). The sidecar never
42
+ // calls routeModel; there is no prefix-stripping on this path.
43
+ eligibleModel: candidate => candidate.provider === "openai"
44
+ && (candidate.native === true || candidate.authSlot === true)
45
+ && !candidate.id.includes("/"),
46
+ },
47
+ {
48
+ backend: "anthropic",
49
+ isActive: auth => auth.isAnthropicAuth,
50
+ // The stored-OAuth Messages executor dispatches through exactly ONE
51
+ // provider — the one the shared auth module resolved. Same-adapter keyed
52
+ // rows are unreachable, mirroring visionBackendForCandidate's stance.
53
+ eligibleModel: (candidate, auth) => candidate.provider === auth.anthropicProviderName,
54
+ },
55
+ {
56
+ backend: "xai",
57
+ // Probe = stored Grok OAuth usable: enabled oauth-mode "xai" provider whose
58
+ // active account is not marked for reauth — the same predicate
59
+ // findXaiSidecarProvider applies at plan time (L7).
60
+ isActive: (_auth, config) => {
61
+ const provider = config.providers["xai"];
62
+ if (!provider || provider.disabled === true || provider.authMode !== "oauth") return false;
63
+ const set = getAccountSet("xai");
64
+ const active = set?.accounts.find(account => account.id === set.activeAccountId);
65
+ return !!active && active.needsReauth !== true;
66
+ },
67
+ eligibleModel: candidate => candidate.provider === "xai",
68
+ },
69
+ {
70
+ backend: "gemini",
71
+ // Probe = usable Antigravity OAuth + discovered projectId (findGeminiSidecarProvider's predicate).
72
+ isActive: (_auth, config) => {
73
+ const provider = config.providers["google-antigravity"];
74
+ if (!provider || provider.disabled === true || provider.authMode !== "oauth") return false;
75
+ const set = getAccountSet("google-antigravity");
76
+ const active = set?.accounts.find(account => account.id === set.activeAccountId);
77
+ if (!active || active.needsReauth === true) return false;
78
+ return !!(active.credential as { projectId?: string } | undefined)?.projectId;
79
+ },
80
+ eligibleModel: candidate => candidate.provider === "google-antigravity",
81
+ },
82
+ {
83
+ backend: "exa",
84
+ // Probe = operator key present. Exa is not an LLM: no candidate models ever
85
+ // match, so the GUI's model list stays untouched by this backend.
86
+ isActive: (_auth, config) => !!config.webSearchSidecar?.exaApiKey,
87
+ eligibleModel: () => false,
88
+ },
89
+ ];
90
+
91
+ /**
92
+ * (picker-visible ∪ auth slots) ∩ (active backend able to run the row).
93
+ * The auth slots always survive their own side's activation: a logged-in
94
+ * side keeps Luna/Haiku even when the picker hides them.
95
+ */
96
+ export function webSearchSidecarCandidates(
97
+ config: OcxConfig,
98
+ auth: SidecarAuthState,
99
+ all: readonly SidecarCandidate[],
100
+ ): SidecarCandidate[] {
101
+ const active = WEB_SEARCH_BACKENDS.filter(descriptor => descriptor.isActive(auth, config));
102
+ return all.filter(candidate => active.some(descriptor => descriptor.eligibleModel(candidate, auth)));
103
+ }
104
+
105
+ /** True when the id is one of the fixed auth-slot models (#2188 write-gate exception). */
106
+ export function isWebSearchAuthSlotModel(id: string): boolean {
107
+ return id === AUTH_SLOT_MODELS.codex || id === AUTH_SLOT_MODELS.anthropic;
108
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Execute ONE web search via the Exa Search API (#2188 L9) — the non-LLM lane.
3
+ *
4
+ * Exa returns ranked result JSON, not a prose answer: the outcome's text is a
5
+ * per-result digest the routed model synthesizes from. Probe-verified 2026-08-21
6
+ * (devlog 002): POST https://api.exa.ai/search with x-api-key returns
7
+ * {requestId, results[{title,url,publishedDate,text}], costDollars}.
8
+ * redirect: "manual" because Bun forwards custom headers across redirects.
9
+ * Never throws; every error string passes redactSecretString.
10
+ */
11
+ import { fetchWithResetRetry } from "../lib/upstream-retry";
12
+ import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
13
+ import { readBoundedResponseBytes } from "../lib/bounded-body";
14
+ import { sidecarEnter } from "../lib/sidecar-tracker";
15
+ import { redactSecretString } from "../lib/redact";
16
+ import { MAX_SIDECAR_RESPONSE_BYTES, type WebSearchSource } from "./parse";
17
+ import type { SidecarOutcome, SidecarSettings } from "./executor";
18
+
19
+ const EXA_SEARCH_URL = "https://api.exa.ai/search";
20
+ const EXA_NUM_RESULTS = 5;
21
+ const EXA_SNIPPET_CHARS = 1000;
22
+
23
+ function isRec(v: unknown): v is Record<string, unknown> {
24
+ return !!v && typeof v === "object" && !Array.isArray(v);
25
+ }
26
+
27
+ export async function runExaWebSearch(
28
+ query: string,
29
+ apiKey: string,
30
+ settings: SidecarSettings,
31
+ abortSignal?: AbortSignal,
32
+ ): Promise<SidecarOutcome> {
33
+ if (!apiKey) return { text: "", sources: [], error: "exa backend selected without an exaApiKey" };
34
+ // The executor KNOWS the secret — pattern-based redaction cannot be trusted to
35
+ // recognize an arbitrary operator key, so scrub the literal value explicitly.
36
+ const scrub = (s: string) => redactSecretString(s.split(apiKey).join("[redacted-exa-key]"));
37
+ const linkedSignal = signalWithTimeout(settings.timeoutMs, abortSignal);
38
+ const sidecarExit = sidecarEnter("web-search");
39
+ const t0 = Date.now();
40
+ try {
41
+ const res = await fetchWithResetRetry(
42
+ () => fetch(EXA_SEARCH_URL, {
43
+ method: "POST",
44
+ headers: { "Content-Type": "application/json", "x-api-key": apiKey },
45
+ body: JSON.stringify({ query, numResults: EXA_NUM_RESULTS, contents: { text: { maxCharacters: EXA_SNIPPET_CHARS } } }),
46
+ signal: linkedSignal.signal,
47
+ redirect: "manual",
48
+ }),
49
+ { abortSignal: linkedSignal.signal, label: "exa-web-search-sidecar" },
50
+ );
51
+ const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
52
+ try {
53
+ let bounded: Awaited<ReturnType<typeof readBoundedResponseBytes>> | null = null;
54
+ try {
55
+ bounded = await readBoundedResponseBytes(res, {
56
+ maxBytes: MAX_SIDECAR_RESPONSE_BYTES,
57
+ signal: linkedSignal.signal,
58
+ });
59
+ } catch {
60
+ const reason = linkedSignal.signal.reason;
61
+ if (linkedSignal.signal.aborted && reason instanceof Error && reason.name === "TimeoutError") {
62
+ throw reason;
63
+ }
64
+ // Preserve the previous status-only/shapeless fallback for body read
65
+ // failures; fetch/header failures are still classified by the outer catch.
66
+ }
67
+ if (bounded?.oversized) {
68
+ const prefix = res.ok ? "exa sidecar response" : `exa sidecar HTTP ${res.status} response`;
69
+ return { text: "", sources: [], error: `${prefix} exceeded byte bound` };
70
+ }
71
+ // Response.text()/json() replace malformed UTF-8, so preserve that
72
+ // behavior while moving the byte bound ahead of decoding and parsing.
73
+ const text = bounded ? new TextDecoder().decode(bounded.bytes) : "";
74
+ if (!res.ok) {
75
+ // Scrub BEFORE truncating: slicing first can cut the literal key at the
76
+ // boundary, leaving an unscrubbable key prefix in the surviving text.
77
+ return { text: "", sources: [], error: `exa sidecar HTTP ${res.status}: ${scrub(text).slice(0, 200)}` };
78
+ }
79
+ let payload: unknown = null;
80
+ try {
81
+ payload = JSON.parse(text);
82
+ } catch {
83
+ // The mapper owns the stable malformed/empty JSON outcome.
84
+ }
85
+ return mapExaSearchResponse(payload);
86
+ } finally {
87
+ detachBodyGuard();
88
+ }
89
+ } catch (e) {
90
+ const kind = e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error";
91
+ console.warn(`[web-search] exa sidecar ${kind} (${Date.now() - t0}ms)`);
92
+ return { text: "", sources: [], error: scrub(e instanceof Error ? e.message : String(e)) };
93
+ } finally {
94
+ sidecarExit();
95
+ linkedSignal.cleanup();
96
+ }
97
+ }
98
+
99
+ /** Map an Exa /search payload to a digest the routed model can synthesize from. */
100
+ export function mapExaSearchResponse(payload: unknown): SidecarOutcome {
101
+ if (!isRec(payload) || !Array.isArray(payload.results)) {
102
+ return { text: "", sources: [], error: "exa sidecar returned a non-JSON or shapeless body" };
103
+ }
104
+ const sources: WebSearchSource[] = [];
105
+ const lines: string[] = [];
106
+ const seen = new Set<string>();
107
+ for (const result of payload.results) {
108
+ if (!isRec(result) || typeof result.url !== "string" || result.url.length === 0) continue;
109
+ if (seen.has(result.url)) continue;
110
+ seen.add(result.url);
111
+ const title = typeof result.title === "string" && result.title.length > 0 ? result.title : result.url;
112
+ sources.push({ url: result.url, ...(title !== result.url ? { title } : {}) });
113
+ const snippet = typeof result.text === "string" ? result.text.trim().slice(0, EXA_SNIPPET_CHARS) : "";
114
+ const dated = typeof result.publishedDate === "string" ? ` (${result.publishedDate.slice(0, 10)})` : "";
115
+ lines.push(`- ${title}${dated}: ${snippet || "(no excerpt)"} [${result.url}]`);
116
+ }
117
+ if (lines.length === 0) return { text: "", sources: [], error: "exa sidecar returned no results" };
118
+ return { text: `Search results:\n${lines.join("\n")}`, sources };
119
+ }
@@ -62,8 +62,8 @@ export async function runWebSearch(
62
62
  tool_choice: "auto",
63
63
  reasoning: { effort: settings.reasoning },
64
64
  // NOTE: the ChatGPT (codex) backend rejects `max_output_tokens` ("Unsupported parameter") and
65
- // requires `store: false` — keep this body minimal. Answer length is capped downstream
66
- // (format-result clamps the injected tool_result), so no upstream cap is needed.
65
+ // requires `store: false` — keep this body minimal. The shared SSE parser bounds raw response
66
+ // bytes before format-result applies its smaller display clamp.
67
67
  store: false,
68
68
  stream: true,
69
69
  };
@@ -78,24 +78,39 @@ export async function runWebSearch(
78
78
  headers,
79
79
  body: JSON.stringify(body),
80
80
  signal: linkedSignal.signal,
81
+ // Credential-bearing: do not follow a cross-origin 3xx. Bun strips `Authorization`
82
+ // across origins but forwards nonstandard headers such as `chatgpt-account-id`,
83
+ // `session_id`, and `x-codex-turn-metadata` to the redirect target.
84
+ redirect: "manual",
81
85
  }),
82
86
  { abortSignal: linkedSignal.signal, label: "web-search-sidecar" },
83
87
  );
84
- recordOutcome?.(res.status);
88
+ // Attach the body guard before ANY branch reads it. The success path guarded itself below,
89
+ // but the failure branch's `res.text()` runs first, so a cancel landing between fetch
90
+ // resolution and reader attach orphaned the internal rejection (found investigating #1419).
91
+ const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
85
92
  if (!res.ok) {
93
+ recordOutcome?.(res.status);
86
94
  const t = await res.text().catch(() => "");
95
+ detachBodyGuard();
87
96
  console.warn(`[web-search] sidecar HTTP ${res.status} for query "${query.slice(0, 80)}" (${Date.now() - t0}ms)`);
88
97
  return { text: "", sources: [], error: `sidecar HTTP ${res.status}: ${redactSecretString(t.slice(0, 200))}` };
89
98
  }
90
- const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
91
99
  try {
92
- return await parseSidecarSSE(res);
100
+ const parsed = await parseSidecarSSE(res);
101
+ if (linkedSignal.signal.aborted) throw linkedSignal.signal.reason;
102
+ recordOutcome?.(res.status);
103
+ return parsed;
93
104
  } finally {
94
105
  detachBodyGuard();
95
106
  }
96
107
  } catch (e) {
97
- recordOutcome?.(e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error");
98
108
  const kind = e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error";
109
+ const callerAborted = abortSignal?.aborted === true
110
+ && linkedSignal.signal.aborted
111
+ && linkedSignal.signal.reason === abortSignal.reason
112
+ && e === linkedSignal.signal.reason;
113
+ recordOutcome?.(callerAborted ? "connect_neutral" : kind);
99
114
  console.warn(`[web-search] sidecar ${kind} for query "${query.slice(0, 80)}" (${Date.now() - t0}ms)`);
100
115
  return { text: "", sources: [], error: e instanceof Error ? e.message : String(e) };
101
116
  } finally {
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Execute ONE web search via Gemini google_search grounding on the Antigravity
3
+ * Cloud Code Assist transport (#2188 L8). Live-probed 2026-08-20/21 (devlog 002):
4
+ * the CCA envelope with tools [{google_search:{}}] returns a grounded answer
5
+ * plus groundingMetadata; a non-IDE User-Agent gets 404, so the request reuses
6
+ * the adapter's fingerprint constants. The OAuth bearer only ever travels to
7
+ * the REGISTRY-pinned endpoint — a config-level baseUrl override is never
8
+ * trusted for token transmission (same rule as src/server/images.ts).
9
+ * Never throws — returns {error} so the caller injects a graceful tool result.
10
+ */
11
+ import type { OcxProviderConfig } from "../types";
12
+ import { getValidAccessTokenSnapshot, publicOAuthAuthenticationErrorMessage } from "../oauth";
13
+ import { fetchWithResetRetry } from "../lib/upstream-retry";
14
+ import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
15
+ import { readBoundedResponseBytes } from "../lib/bounded-body";
16
+ import { sidecarEnter } from "../lib/sidecar-tracker";
17
+ import { redactSecretString } from "../lib/redact";
18
+ import { ANTIGRAVITY_REQUEST_UA } from "../adapters/google-antigravity-wire";
19
+ import { resolveAntigravityEffortWireModel } from "../providers/antigravity-models";
20
+ import { getProviderRegistryEntry } from "../providers/registry";
21
+ import { MAX_SIDECAR_RESPONSE_BYTES, type WebSearchSource } from "./parse";
22
+ import { BASE_INSTRUCTION, IMAGE_INSTRUCTION, type SidecarOutcome, type SidecarSettings } from "./executor";
23
+
24
+ const CCA_FALLBACK_BASE = "https://daily-cloudcode-pa.googleapis.com";
25
+
26
+ function isRec(v: unknown): v is Record<string, unknown> {
27
+ return !!v && typeof v === "object" && !Array.isArray(v);
28
+ }
29
+
30
+ export async function runGeminiWebSearch(
31
+ query: string,
32
+ providerName: string,
33
+ _provider: OcxProviderConfig,
34
+ settings: SidecarSettings,
35
+ abortSignal?: AbortSignal,
36
+ ): Promise<SidecarOutcome> {
37
+ let token: string;
38
+ let project: string | undefined;
39
+ try {
40
+ const snapshot = await getValidAccessTokenSnapshot(providerName);
41
+ token = snapshot.accessToken;
42
+ project = snapshot.projectId;
43
+ } catch (e) {
44
+ return { text: "", sources: [], error: `gemini sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(e)}` };
45
+ }
46
+ if (!project) {
47
+ return { text: "", sources: [], error: "gemini sidecar missing Cloud Code Assist project id — re-run ocx login google-antigravity" };
48
+ }
49
+ // Destination pinned to the registry endpoint (see module doc).
50
+ const base = getProviderRegistryEntry("google-antigravity")?.baseUrl ?? CCA_FALLBACK_BASE;
51
+ const { wireModelId, thinkingLevel } = resolveAntigravityEffortWireModel(settings.model, settings.reasoning, base);
52
+ const instruction = settings.describeImages ? BASE_INSTRUCTION + IMAGE_INSTRUCTION : BASE_INSTRUCTION;
53
+ const envelope = {
54
+ model: wireModelId,
55
+ userAgent: "antigravity",
56
+ requestType: "agent",
57
+ project,
58
+ requestId: `agent-${crypto.randomUUID()}`,
59
+ request: {
60
+ systemInstruction: { role: "user", parts: [{ text: instruction }] },
61
+ contents: [{ role: "user", parts: [{ text: query }] }],
62
+ tools: [{ google_search: {} }],
63
+ sessionId: crypto.randomUUID(),
64
+ ...(thinkingLevel ? { generationConfig: { thinkingConfig: { thinkingLevel } } } : {}),
65
+ },
66
+ };
67
+ const linkedSignal = signalWithTimeout(settings.timeoutMs, abortSignal);
68
+ const sidecarExit = sidecarEnter("web-search");
69
+ const t0 = Date.now();
70
+ try {
71
+ const res = await fetchWithResetRetry(
72
+ () => fetch(`${base}/v1internal:generateContent`, {
73
+ method: "POST",
74
+ headers: {
75
+ "Content-Type": "application/json",
76
+ "Authorization": `Bearer ${token}`,
77
+ "User-Agent": ANTIGRAVITY_REQUEST_UA,
78
+ },
79
+ body: JSON.stringify(envelope),
80
+ signal: linkedSignal.signal,
81
+ redirect: "manual",
82
+ }),
83
+ { abortSignal: linkedSignal.signal, label: "gemini-web-search-sidecar" },
84
+ );
85
+ const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
86
+ try {
87
+ const bounded = await readBoundedResponseBytes(res, {
88
+ maxBytes: MAX_SIDECAR_RESPONSE_BYTES,
89
+ signal: linkedSignal.signal,
90
+ });
91
+ if (bounded.oversized) {
92
+ const prefix = res.ok ? "gemini sidecar response" : `gemini sidecar HTTP ${res.status} response`;
93
+ return { text: "", sources: [], error: `${prefix} exceeded byte bound` };
94
+ }
95
+ const text = new TextDecoder("utf-8", { fatal: true }).decode(bounded.bytes);
96
+ if (!res.ok) {
97
+ return { text: "", sources: [], error: `gemini sidecar HTTP ${res.status}: ${redactSecretString(text.slice(0, 200))}` };
98
+ }
99
+ let payload: unknown = null;
100
+ try {
101
+ payload = JSON.parse(text);
102
+ } catch {
103
+ // The mapper owns the stable malformed/empty JSON outcome.
104
+ }
105
+ return mapCcaGroundedResponse(payload);
106
+ } finally {
107
+ detachBodyGuard();
108
+ }
109
+ } catch (e) {
110
+ const kind = e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error";
111
+ console.warn(`[web-search] gemini sidecar ${kind} (${Date.now() - t0}ms)`);
112
+ return { text: "", sources: [], error: redactSecretString(e instanceof Error ? e.message : String(e)) };
113
+ } finally {
114
+ sidecarExit();
115
+ linkedSignal.cleanup();
116
+ }
117
+ }
118
+
119
+ /** Map a CCA generateContent payload (possibly wrapped in {response}) to text + grounding sources. */
120
+ export function mapCcaGroundedResponse(payload: unknown): SidecarOutcome {
121
+ const root = isRec(payload) && isRec(payload.response) ? payload.response : payload;
122
+ if (!isRec(root)) return { text: "", sources: [], error: "gemini sidecar returned a non-JSON or empty body" };
123
+ const candidate = Array.isArray(root.candidates) && isRec(root.candidates[0]) ? root.candidates[0] : undefined;
124
+ if (!candidate) return { text: "", sources: [], error: "gemini sidecar returned no candidates" };
125
+ const parts = isRec(candidate.content) && Array.isArray(candidate.content.parts) ? candidate.content.parts : [];
126
+ const text = parts.map(p => (isRec(p) && typeof p.text === "string" ? p.text : "")).join("");
127
+ const sources: WebSearchSource[] = [];
128
+ const seen = new Set<string>();
129
+ const gm = isRec(candidate.groundingMetadata) ? candidate.groundingMetadata : undefined;
130
+ if (gm && Array.isArray(gm.groundingChunks)) {
131
+ for (const chunk of gm.groundingChunks) {
132
+ const web = isRec(chunk) && isRec(chunk.web) ? chunk.web : undefined;
133
+ const uri = web && typeof web.uri === "string" ? web.uri : undefined;
134
+ if (!uri || seen.has(uri)) continue;
135
+ seen.add(uri);
136
+ sources.push({ url: uri, ...(typeof web?.title === "string" && web.title.length > 0 ? { title: web.title } : {}) });
137
+ }
138
+ }
139
+ if (text.length === 0) return { text: "", sources, error: "gemini sidecar returned no text" };
140
+ return { text, sources };
141
+ }