@yansigit/opencodex 2.31.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 (826) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/LICENSE +21 -0
  3. package/README.md +303 -0
  4. package/assets/architecture.png +0 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/claude-code-models.gif +0 -0
  7. package/assets/codex-app-picker.png +0 -0
  8. package/bin/ocx.mjs +587 -0
  9. package/bin/package-main.mjs +9 -0
  10. package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
  11. package/gui/dist/assets/index-CGoDO3uO.css +1 -0
  12. package/gui/dist/favicon.png +0 -0
  13. package/gui/dist/icons.svg +24 -0
  14. package/gui/dist/index.html +25 -0
  15. package/gui/dist/logo.png +0 -0
  16. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  17. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  18. package/gui/dist/provider-icons/claude-color.svg +1 -0
  19. package/gui/dist/provider-icons/cline-color.svg +16 -0
  20. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  21. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  22. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  23. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  24. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  25. package/gui/dist/provider-icons/discord.svg +1 -0
  26. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  27. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  28. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  29. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  30. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  31. package/gui/dist/provider-icons/grok.svg +1 -0
  32. package/gui/dist/provider-icons/groq-color.svg +1 -0
  33. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  34. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  35. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  36. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  37. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  38. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  39. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  40. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  41. package/gui/dist/provider-icons/openai.svg +1 -0
  42. package/gui/dist/provider-icons/opencode.svg +2 -0
  43. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  44. package/gui/dist/provider-icons/pi.svg +21 -0
  45. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  46. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  47. package/gui/dist/provider-icons/telegram.svg +1 -0
  48. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  49. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  50. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  51. package/package.json +108 -0
  52. package/src/AGENTS.md +28 -0
  53. package/src/adapters/anthropic-image-guard.ts +251 -0
  54. package/src/adapters/anthropic-image-normalize.ts +518 -0
  55. package/src/adapters/anthropic-output-schema.ts +137 -0
  56. package/src/adapters/anthropic.ts +1327 -0
  57. package/src/adapters/azure.ts +36 -0
  58. package/src/adapters/base.ts +121 -0
  59. package/src/adapters/client-fingerprint.ts +65 -0
  60. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  61. package/src/adapters/command-code.ts +601 -0
  62. package/src/adapters/cursor/arg-codec.ts +38 -0
  63. package/src/adapters/cursor/arg-normalize.ts +104 -0
  64. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  65. package/src/adapters/cursor/cursor-errors.ts +288 -0
  66. package/src/adapters/cursor/discovery.ts +333 -0
  67. package/src/adapters/cursor/effort-map.ts +151 -0
  68. package/src/adapters/cursor/exec-policy.ts +88 -0
  69. package/src/adapters/cursor/framing.ts +250 -0
  70. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  71. package/src/adapters/cursor/h2-pool.ts +123 -0
  72. package/src/adapters/cursor/http1-bidi.ts +361 -0
  73. package/src/adapters/cursor/images.ts +704 -0
  74. package/src/adapters/cursor/kv-store.ts +52 -0
  75. package/src/adapters/cursor/live-models.ts +269 -0
  76. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  77. package/src/adapters/cursor/live-transport.ts +1653 -0
  78. package/src/adapters/cursor/mcp-config.ts +42 -0
  79. package/src/adapters/cursor/mcp-manager.ts +333 -0
  80. package/src/adapters/cursor/message-mapper.ts +49 -0
  81. package/src/adapters/cursor/native-exec-common.ts +76 -0
  82. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  83. package/src/adapters/cursor/native-exec-fs.ts +332 -0
  84. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  85. package/src/adapters/cursor/native-exec-network.ts +43 -0
  86. package/src/adapters/cursor/native-exec-shell.ts +547 -0
  87. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  88. package/src/adapters/cursor/native-exec.ts +663 -0
  89. package/src/adapters/cursor/protobuf-events.ts +1381 -0
  90. package/src/adapters/cursor/protobuf-request.ts +1032 -0
  91. package/src/adapters/cursor/request-builder.ts +461 -0
  92. package/src/adapters/cursor/thread-continuity.ts +67 -0
  93. package/src/adapters/cursor/tool-definitions.ts +735 -0
  94. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  95. package/src/adapters/cursor/transport-retry.ts +132 -0
  96. package/src/adapters/cursor/transport.ts +79 -0
  97. package/src/adapters/cursor/types.ts +79 -0
  98. package/src/adapters/cursor.ts +322 -0
  99. package/src/adapters/google-antigravity-hosts.ts +48 -0
  100. package/src/adapters/google-antigravity-replay.ts +827 -0
  101. package/src/adapters/google-antigravity-tools.ts +105 -0
  102. package/src/adapters/google-antigravity-wire.ts +141 -0
  103. package/src/adapters/google-errors.ts +92 -0
  104. package/src/adapters/google-http.ts +460 -0
  105. package/src/adapters/google-tool-schema.ts +238 -0
  106. package/src/adapters/google-truncation.ts +24 -0
  107. package/src/adapters/google-wire-compiler.ts +232 -0
  108. package/src/adapters/google.ts +1377 -0
  109. package/src/adapters/identity.ts +77 -0
  110. package/src/adapters/image.ts +23 -0
  111. package/src/adapters/kiro-constants.ts +16 -0
  112. package/src/adapters/kiro-errors.ts +208 -0
  113. package/src/adapters/kiro-events.ts +197 -0
  114. package/src/adapters/kiro-images.ts +129 -0
  115. package/src/adapters/kiro-retry.ts +312 -0
  116. package/src/adapters/kiro-thinking.ts +112 -0
  117. package/src/adapters/kiro-tool-fallback.ts +36 -0
  118. package/src/adapters/kiro-tools.ts +224 -0
  119. package/src/adapters/kiro-truncation.ts +33 -0
  120. package/src/adapters/kiro-wire.ts +129 -0
  121. package/src/adapters/kiro.ts +1936 -0
  122. package/src/adapters/mimo-free.ts +280 -0
  123. package/src/adapters/openai-chat-url.ts +11 -0
  124. package/src/adapters/openai-chat.ts +1980 -0
  125. package/src/adapters/openai-responses-url.ts +16 -0
  126. package/src/adapters/openai-responses.ts +1911 -0
  127. package/src/adapters/registry.ts +175 -0
  128. package/src/adapters/responses-tool-schema.ts +67 -0
  129. package/src/adapters/run-turn-queue.ts +114 -0
  130. package/src/adapters/tool-call-id.ts +119 -0
  131. package/src/adapters/tool-catalog-nudge.ts +154 -0
  132. package/src/adapters/upstream-http-error.ts +48 -0
  133. package/src/adapters/xai-web-search.ts +185 -0
  134. package/src/bridge.ts +1986 -0
  135. package/src/chat/inbound.ts +319 -0
  136. package/src/chat/outbound.ts +821 -0
  137. package/src/claude/agents-inject.ts +266 -0
  138. package/src/claude/alias.ts +149 -0
  139. package/src/claude/auth-detect.ts +229 -0
  140. package/src/claude/auth-mode-migration.ts +32 -0
  141. package/src/claude/auth-mode.ts +62 -0
  142. package/src/claude/context-windows.ts +205 -0
  143. package/src/claude/desktop-3p-guard.ts +35 -0
  144. package/src/claude/desktop-3p-paths.ts +84 -0
  145. package/src/claude/desktop-3p.ts +615 -0
  146. package/src/claude/desktop-health.ts +26 -0
  147. package/src/claude/desktop-profile.ts +263 -0
  148. package/src/claude/gateway-cache.ts +107 -0
  149. package/src/claude/inbound-debug.ts +163 -0
  150. package/src/claude/inbound.ts +578 -0
  151. package/src/claude/model-info.ts +174 -0
  152. package/src/claude/outbound.ts +926 -0
  153. package/src/cli/access.ts +108 -0
  154. package/src/cli/account-api.ts +302 -0
  155. package/src/cli/account-auth.ts +250 -0
  156. package/src/cli/account-catalog-refresh.ts +14 -0
  157. package/src/cli/account-extended.ts +737 -0
  158. package/src/cli/account-main.ts +317 -0
  159. package/src/cli/account.ts +299 -0
  160. package/src/cli/agent-driven.ts +70 -0
  161. package/src/cli/agent.ts +290 -0
  162. package/src/cli/catalog-prewarm.ts +27 -0
  163. package/src/cli/claude-agent-startup-sync.ts +73 -0
  164. package/src/cli/claude-desktop.ts +213 -0
  165. package/src/cli/claude.ts +355 -0
  166. package/src/cli/codex-log-guard-doctor.ts +103 -0
  167. package/src/cli/codex-shim-autorestore.ts +47 -0
  168. package/src/cli/codex-shim-readiness.ts +76 -0
  169. package/src/cli/combo.ts +127 -0
  170. package/src/cli/config-command.ts +209 -0
  171. package/src/cli/debug.ts +228 -0
  172. package/src/cli/dispatch.ts +585 -0
  173. package/src/cli/doctor.ts +1202 -0
  174. package/src/cli/ensure-desired-integrations.ts +152 -0
  175. package/src/cli/export-command.ts +213 -0
  176. package/src/cli/help.ts +101 -0
  177. package/src/cli/index.ts +973 -0
  178. package/src/cli/init.ts +211 -0
  179. package/src/cli/integrations.ts +260 -0
  180. package/src/cli/interactive-confirm.ts +133 -0
  181. package/src/cli/lab.ts +607 -0
  182. package/src/cli/launcher-context.ts +77 -0
  183. package/src/cli/minimax.ts +497 -0
  184. package/src/cli/models-runtime.ts +245 -0
  185. package/src/cli/models.ts +422 -0
  186. package/src/cli/observe.ts +206 -0
  187. package/src/cli/opencode.ts +588 -0
  188. package/src/cli/provider-replit.ts +232 -0
  189. package/src/cli/provider-runtime.ts +179 -0
  190. package/src/cli/provider.ts +492 -0
  191. package/src/cli/ready.ts +301 -0
  192. package/src/cli/registry.ts +422 -0
  193. package/src/cli/replit-gateway-key-input.ts +138 -0
  194. package/src/cli/root.ts +86 -0
  195. package/src/cli/route-policy.ts +92 -0
  196. package/src/cli/runtime-api.ts +328 -0
  197. package/src/cli/star-prompt.ts +211 -0
  198. package/src/cli/status-oauth.ts +78 -0
  199. package/src/cli/status.ts +328 -0
  200. package/src/cli/system-command.ts +112 -0
  201. package/src/cli/system-restart-client.ts +146 -0
  202. package/src/cli/tray-proxy.ts +199 -0
  203. package/src/cli/v2.ts +268 -0
  204. package/src/cli.ts +10 -0
  205. package/src/clients/config-export.ts +1704 -0
  206. package/src/codex/account-id.ts +34 -0
  207. package/src/codex/account-label.ts +47 -0
  208. package/src/codex/account-lifecycle.ts +172 -0
  209. package/src/codex/account-namespace-match.ts +63 -0
  210. package/src/codex/account-namespaces.ts +195 -0
  211. package/src/codex/account-pause.ts +20 -0
  212. package/src/codex/account-priority.ts +83 -0
  213. package/src/codex/account-runtime-state.ts +31 -0
  214. package/src/codex/account-store.ts +544 -0
  215. package/src/codex/account-usability.ts +43 -0
  216. package/src/codex/admission.ts +256 -0
  217. package/src/codex/affinity-debug.ts +162 -0
  218. package/src/codex/agent-roles-sync.ts +225 -0
  219. package/src/codex/agent-roles.ts +238 -0
  220. package/src/codex/app-server-processes.ts +1143 -0
  221. package/src/codex/app-server-restart-service.ts +232 -0
  222. package/src/codex/auth-api.ts +2147 -0
  223. package/src/codex/auth-collision.ts +109 -0
  224. package/src/codex/auth-context.ts +665 -0
  225. package/src/codex/autostart-health.ts +156 -0
  226. package/src/codex/catalog/account-models.ts +67 -0
  227. package/src/codex/catalog/aggregation.ts +436 -0
  228. package/src/codex/catalog/bundled.ts +549 -0
  229. package/src/codex/catalog/effort.ts +446 -0
  230. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  231. package/src/codex/catalog/kinds.ts +2 -0
  232. package/src/codex/catalog/metadata.ts +664 -0
  233. package/src/codex/catalog/native-models.ts +72 -0
  234. package/src/codex/catalog/parsing.ts +650 -0
  235. package/src/codex/catalog/provider-fetch.ts +2064 -0
  236. package/src/codex/catalog/sync.ts +1883 -0
  237. package/src/codex/catalog-admission.ts +199 -0
  238. package/src/codex/catalog-refresh-status.ts +105 -0
  239. package/src/codex/catalog-write-serialization.ts +242 -0
  240. package/src/codex/catalog.ts +14 -0
  241. package/src/codex/codex-write-lock.ts +384 -0
  242. package/src/codex/convergence-types.ts +614 -0
  243. package/src/codex/convergence.ts +651 -0
  244. package/src/codex/coordinator-doctor.ts +332 -0
  245. package/src/codex/custom-model-catalog-migration.ts +176 -0
  246. package/src/codex/data/upstream-models.json +830 -0
  247. package/src/codex/desired-state.ts +230 -0
  248. package/src/codex/exec-invocation.ts +22 -0
  249. package/src/codex/features.ts +1566 -0
  250. package/src/codex/generation.ts +202 -0
  251. package/src/codex/history-job.ts +407 -0
  252. package/src/codex/history-lock.ts +242 -0
  253. package/src/codex/history-migration-guardian.ts +108 -0
  254. package/src/codex/history-provider.ts +979 -0
  255. package/src/codex/history-transition.ts +105 -0
  256. package/src/codex/history-worker.ts +220 -0
  257. package/src/codex/home.ts +206 -0
  258. package/src/codex/inject-coordination.ts +290 -0
  259. package/src/codex/inject.ts +1733 -0
  260. package/src/codex/injected-marker.ts +106 -0
  261. package/src/codex/integration-record.ts +266 -0
  262. package/src/codex/internal/catalog-writer.ts +203 -0
  263. package/src/codex/internal/history-writer.ts +80 -0
  264. package/src/codex/journal.ts +225 -0
  265. package/src/codex/log-guard/inspect.ts +506 -0
  266. package/src/codex/log-guard/lock.ts +150 -0
  267. package/src/codex/log-guard/maintenance.ts +403 -0
  268. package/src/codex/log-guard/path-safety.ts +88 -0
  269. package/src/codex/log-guard/policy.ts +44 -0
  270. package/src/codex/log-guard/processes.ts +205 -0
  271. package/src/codex/log-guard/protection.ts +489 -0
  272. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  273. package/src/codex/main-account-cache.ts +56 -0
  274. package/src/codex/main-account.ts +68 -0
  275. package/src/codex/management-convergence.ts +167 -0
  276. package/src/codex/model-cache.ts +273 -0
  277. package/src/codex/model-entitlements.ts +353 -0
  278. package/src/codex/native-main-admission.ts +47 -0
  279. package/src/codex/native-main-auth-temp.ts +187 -0
  280. package/src/codex/native-main-claim.ts +178 -0
  281. package/src/codex/native-main-lock-file.ts +162 -0
  282. package/src/codex/native-main-owner.ts +329 -0
  283. package/src/codex/native-profile-api.ts +247 -0
  284. package/src/codex/native-profile-manager.ts +1531 -0
  285. package/src/codex/native-profile-processes.ts +121 -0
  286. package/src/codex/native-profile-recovery.ts +99 -0
  287. package/src/codex/native-profile-stage-store.ts +387 -0
  288. package/src/codex/native-profile-startup.ts +492 -0
  289. package/src/codex/native-profile-store.ts +855 -0
  290. package/src/codex/native-profile-types.ts +120 -0
  291. package/src/codex/native-residue.ts +682 -0
  292. package/src/codex/paths.ts +144 -0
  293. package/src/codex/plan-from-token.ts +140 -0
  294. package/src/codex/plan.ts +40 -0
  295. package/src/codex/plugins-doctor.ts +242 -0
  296. package/src/codex/pool-rotation.ts +295 -0
  297. package/src/codex/project-config-warnings.ts +425 -0
  298. package/src/codex/prompt-journal.ts +352 -0
  299. package/src/codex/prompt-layers.ts +967 -0
  300. package/src/codex/prompt-lock.ts +143 -0
  301. package/src/codex/quota-rejection.ts +298 -0
  302. package/src/codex/quota.ts +573 -0
  303. package/src/codex/refresh.ts +62 -0
  304. package/src/codex/reset-credit-recovery.ts +1044 -0
  305. package/src/codex/routing.ts +1888 -0
  306. package/src/codex/runtime.ts +659 -0
  307. package/src/codex/shim.ts +2170 -0
  308. package/src/codex/subagent-defaults.ts +550 -0
  309. package/src/codex/subagent-model-fallback.ts +784 -0
  310. package/src/codex/sync.ts +319 -0
  311. package/src/codex/transition-state.ts +612 -0
  312. package/src/codex/upstream-host-health.ts +368 -0
  313. package/src/codex/user-identity.ts +557 -0
  314. package/src/codex/warmup.ts +298 -0
  315. package/src/codex/websocket-registry.ts +100 -0
  316. package/src/codex/write-coordination.ts +114 -0
  317. package/src/combos/failover.ts +160 -0
  318. package/src/combos/index.ts +45 -0
  319. package/src/combos/request.ts +94 -0
  320. package/src/combos/resolve.ts +232 -0
  321. package/src/combos/types.ts +398 -0
  322. package/src/config/provider-name.ts +24 -0
  323. package/src/config.ts +4041 -0
  324. package/src/fork/register.ts +3 -0
  325. package/src/generated/compatibility-version.json +3116 -0
  326. package/src/generated/model-metadata.ts +106 -0
  327. package/src/github/star-state.ts +203 -0
  328. package/src/grok/inject.ts +530 -0
  329. package/src/grok/inspect.ts +45 -0
  330. package/src/grok/status.ts +121 -0
  331. package/src/grok/sync.ts +66 -0
  332. package/src/images/artifacts.ts +516 -0
  333. package/src/images/fulfill-video.ts +163 -0
  334. package/src/images/fulfill.ts +149 -0
  335. package/src/images/index.ts +4 -0
  336. package/src/images/loop.ts +955 -0
  337. package/src/images/plan.ts +143 -0
  338. package/src/images/synthetic-tool.ts +133 -0
  339. package/src/images/types.ts +41 -0
  340. package/src/images/xai-client.ts +141 -0
  341. package/src/images/xai-video-client.ts +163 -0
  342. package/src/index.ts +22 -0
  343. package/src/integrations/config-io.ts +269 -0
  344. package/src/integrations/journal.ts +315 -0
  345. package/src/integrations/merge.ts +135 -0
  346. package/src/integrations/mutation-flight.ts +71 -0
  347. package/src/integrations/native/ownership-preflight.ts +202 -0
  348. package/src/integrations/omp-yaml-source.ts +358 -0
  349. package/src/integrations/owned-refresh.ts +74 -0
  350. package/src/integrations/ownership.ts +111 -0
  351. package/src/integrations/registry.ts +159 -0
  352. package/src/integrations/serialize.ts +314 -0
  353. package/src/integrations/state.ts +361 -0
  354. package/src/integrations/store.ts +103 -0
  355. package/src/integrations/writer-lock.ts +98 -0
  356. package/src/integrations/writer.ts +691 -0
  357. package/src/lab/artifacts/sanitize.ts +586 -0
  358. package/src/lab/artifacts/secure-fs.ts +475 -0
  359. package/src/lab/artifacts/store.ts +310 -0
  360. package/src/lab/automation/budgets.ts +78 -0
  361. package/src/lab/automation/config-persistence.ts +256 -0
  362. package/src/lab/automation/constants.ts +39 -0
  363. package/src/lab/automation/cooldown.ts +103 -0
  364. package/src/lab/automation/dispatch.ts +211 -0
  365. package/src/lab/automation/index.ts +13 -0
  366. package/src/lab/automation/orchestrator.ts +499 -0
  367. package/src/lab/automation/persistence.ts +512 -0
  368. package/src/lab/automation/planner.ts +371 -0
  369. package/src/lab/automation/policy.ts +136 -0
  370. package/src/lab/automation/queue.ts +191 -0
  371. package/src/lab/automation/recovery.ts +24 -0
  372. package/src/lab/automation/route-context.ts +21 -0
  373. package/src/lab/automation/run-key.ts +44 -0
  374. package/src/lab/automation/runs-query.ts +34 -0
  375. package/src/lab/automation/types.ts +160 -0
  376. package/src/lab/conformance/assertion.ts +325 -0
  377. package/src/lab/conformance/digest.ts +22 -0
  378. package/src/lab/conformance/executor.ts +741 -0
  379. package/src/lab/conformance/fixture-provider.ts +27 -0
  380. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  381. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  382. package/src/lab/conformance/harness-budget.ts +47 -0
  383. package/src/lab/conformance/index.ts +5 -0
  384. package/src/lab/conformance/jcs.ts +64 -0
  385. package/src/lab/conformance/json-pointer.ts +39 -0
  386. package/src/lab/conformance/manifest.ts +180 -0
  387. package/src/lab/conformance/mcp-stub.ts +179 -0
  388. package/src/lab/conformance/negative-controls.ts +164 -0
  389. package/src/lab/conformance/observation.ts +355 -0
  390. package/src/lab/conformance/runner.ts +68 -0
  391. package/src/lab/conformance/sse-normalize.ts +59 -0
  392. package/src/lab/conformance/suite-manifest.ts +78 -0
  393. package/src/lab/conformance/types.ts +214 -0
  394. package/src/lab/constants.ts +126 -0
  395. package/src/lab/digest.ts +64 -0
  396. package/src/lab/events/errors.ts +9 -0
  397. package/src/lab/events/limits.ts +117 -0
  398. package/src/lab/events/types.ts +229 -0
  399. package/src/lab/events/validate.ts +781 -0
  400. package/src/lab/fabric/constants.ts +40 -0
  401. package/src/lab/fabric/executor.ts +492 -0
  402. package/src/lab/fabric/index.ts +80 -0
  403. package/src/lab/fabric/manifest.ts +222 -0
  404. package/src/lab/fabric/observe.ts +489 -0
  405. package/src/lab/fabric/patch.ts +79 -0
  406. package/src/lab/fabric/producer-child.ts +139 -0
  407. package/src/lab/fabric/producer-isolate.ts +276 -0
  408. package/src/lab/fabric/producer-protocol.ts +61 -0
  409. package/src/lab/fabric/scratch.ts +439 -0
  410. package/src/lab/fabric/subject.ts +106 -0
  411. package/src/lab/fabric/types.ts +134 -0
  412. package/src/lab/fabric/verifier.ts +98 -0
  413. package/src/lab/index.ts +54 -0
  414. package/src/lab/ledger/artifact-refs.ts +127 -0
  415. package/src/lab/ledger/invalidation.ts +136 -0
  416. package/src/lab/ledger/purge.ts +310 -0
  417. package/src/lab/ledger/store.ts +532 -0
  418. package/src/lab/live/credential-lease.ts +53 -0
  419. package/src/lab/live/destination.ts +155 -0
  420. package/src/lab/live/executor.ts +336 -0
  421. package/src/lab/live/inert-tools.ts +56 -0
  422. package/src/lab/live/manifest.ts +85 -0
  423. package/src/lab/live/mcp-loopback.ts +57 -0
  424. package/src/lab/live/runner.ts +19 -0
  425. package/src/lab/live/sandbox.ts +61 -0
  426. package/src/lab/live/suite-manifest.ts +41 -0
  427. package/src/lab/live/transport.ts +118 -0
  428. package/src/lab/live/types.ts +197 -0
  429. package/src/lab/observe/from-conformance.ts +301 -0
  430. package/src/lab/observe/from-live.ts +117 -0
  431. package/src/lab/paths.ts +153 -0
  432. package/src/lab/projection/rebuild.ts +495 -0
  433. package/src/lab/projection/schema.ts +135 -0
  434. package/src/lab/projection/verdicts.ts +474 -0
  435. package/src/lab/projection/verification.ts +412 -0
  436. package/src/lab/public/bundle.ts +217 -0
  437. package/src/lab/public/community-authority.ts +175 -0
  438. package/src/lab/public/community-files.ts +29 -0
  439. package/src/lab/public/community.ts +479 -0
  440. package/src/lab/public/file-safety.ts +155 -0
  441. package/src/lab/public/ids.ts +26 -0
  442. package/src/lab/public/index.ts +16 -0
  443. package/src/lab/public/mutation-lock.ts +424 -0
  444. package/src/lab/public/operator.ts +353 -0
  445. package/src/lab/public/origin-purge.ts +79 -0
  446. package/src/lab/public/origin.ts +203 -0
  447. package/src/lab/public/privacy.ts +143 -0
  448. package/src/lab/public/private-file.ts +261 -0
  449. package/src/lab/public/project.ts +124 -0
  450. package/src/lab/public/purge-test-fault.ts +21 -0
  451. package/src/lab/public/purge.ts +223 -0
  452. package/src/lab/public/registry.ts +44 -0
  453. package/src/lab/public/revocation.ts +252 -0
  454. package/src/lab/public/signature.ts +243 -0
  455. package/src/lab/public/storage.ts +105 -0
  456. package/src/lab/public/strict-json.ts +206 -0
  457. package/src/lab/public/time.ts +26 -0
  458. package/src/lab/public/types.ts +172 -0
  459. package/src/lab/public/validate.ts +391 -0
  460. package/src/lab/query/catalog.ts +101 -0
  461. package/src/lab/query/connection.ts +107 -0
  462. package/src/lab/query/constants.ts +4 -0
  463. package/src/lab/query/cursor.ts +132 -0
  464. package/src/lab/query/dto-map.ts +277 -0
  465. package/src/lab/query/errors.ts +22 -0
  466. package/src/lab/query/freshness.ts +53 -0
  467. package/src/lab/query/index.ts +45 -0
  468. package/src/lab/query/latest-observation.ts +59 -0
  469. package/src/lab/query/passive-production.ts +159 -0
  470. package/src/lab/query/queries.ts +444 -0
  471. package/src/lab/query/types.ts +266 -0
  472. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  473. package/src/lab/subject/installation-salt.ts +112 -0
  474. package/src/lab/subject/protocol-subject.ts +80 -0
  475. package/src/lab/subject/route-subject.ts +74 -0
  476. package/src/lib/abort.ts +146 -0
  477. package/src/lib/admin-secrets.ts +25 -0
  478. package/src/lib/admission.ts +83 -0
  479. package/src/lib/app-owned-memory-stores.ts +195 -0
  480. package/src/lib/app-owned-memory.ts +265 -0
  481. package/src/lib/bounded-body.ts +346 -0
  482. package/src/lib/bun-binary-validator.d.mts +3 -0
  483. package/src/lib/bun-binary-validator.mjs +18 -0
  484. package/src/lib/bun-runtime.ts +184 -0
  485. package/src/lib/bun-stream-caps.ts +130 -0
  486. package/src/lib/codex-restart-contract.ts +120 -0
  487. package/src/lib/config-ownership.ts +364 -0
  488. package/src/lib/crash-guard.ts +344 -0
  489. package/src/lib/debug-log-buffer.ts +83 -0
  490. package/src/lib/debug-settings.ts +108 -0
  491. package/src/lib/debug.ts +31 -0
  492. package/src/lib/destination-policy.ts +380 -0
  493. package/src/lib/errors.ts +406 -0
  494. package/src/lib/eventstream-decoder.ts +253 -0
  495. package/src/lib/fabric-task-execution-authority.ts +7 -0
  496. package/src/lib/fabric-task-host.ts +29 -0
  497. package/src/lib/gcp-adc.ts +341 -0
  498. package/src/lib/injection-debug-log.ts +58 -0
  499. package/src/lib/lab-activation.ts +223 -0
  500. package/src/lib/lab-live-execution-authority.ts +13 -0
  501. package/src/lib/lab-live-host.ts +30 -0
  502. package/src/lib/lab-live-pinned-sender.ts +56 -0
  503. package/src/lib/lab-live-route-production.ts +130 -0
  504. package/src/lib/lab-passive-linker-registration.ts +26 -0
  505. package/src/lib/local-management-attestation.ts +51 -0
  506. package/src/lib/local-management-capability.ts +100 -0
  507. package/src/lib/local-provider-reload-contract.ts +100 -0
  508. package/src/lib/open-url.ts +25 -0
  509. package/src/lib/optional-shutdown-hooks.ts +57 -0
  510. package/src/lib/pinned-http.ts +270 -0
  511. package/src/lib/privacy.ts +20 -0
  512. package/src/lib/process-control.ts +168 -0
  513. package/src/lib/provider-outbound.ts +210 -0
  514. package/src/lib/provider-url.ts +14 -0
  515. package/src/lib/proxy-env.ts +18 -0
  516. package/src/lib/redact.ts +521 -0
  517. package/src/lib/retry-after.ts +55 -0
  518. package/src/lib/self-launch-argv.ts +15 -0
  519. package/src/lib/server-resource-ownership.ts +71 -0
  520. package/src/lib/service-secrets.ts +25 -0
  521. package/src/lib/shadow-call.ts +61 -0
  522. package/src/lib/sidecar-tracker.ts +52 -0
  523. package/src/lib/sse-decoder.ts +364 -0
  524. package/src/lib/state-store-registrations.ts +119 -0
  525. package/src/lib/state-store-sweeper.ts +184 -0
  526. package/src/lib/system-restart-contract.ts +73 -0
  527. package/src/lib/test-home-guard.ts +90 -0
  528. package/src/lib/token-estimate.ts +86 -0
  529. package/src/lib/tool-argument-integers.ts +202 -0
  530. package/src/lib/translator-budget.ts +400 -0
  531. package/src/lib/upstream-http-version.ts +57 -0
  532. package/src/lib/upstream-reachability.ts +95 -0
  533. package/src/lib/upstream-retry.ts +392 -0
  534. package/src/lib/win-exec.ts +115 -0
  535. package/src/lib/win-paths.ts +68 -0
  536. package/src/lib/windows-atomic-replace.ts +156 -0
  537. package/src/lib/windows-elevation.ts +773 -0
  538. package/src/lib/windows-secret-acl.ts +854 -0
  539. package/src/lib/windows-service-wrappers.ts +72 -0
  540. package/src/lib/windows-text.ts +106 -0
  541. package/src/lib/windows-user-principal.ts +341 -0
  542. package/src/lib/winsw.ts +403 -0
  543. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  544. package/src/oauth/account-import/index.ts +15 -0
  545. package/src/oauth/account-import/parser.ts +83 -0
  546. package/src/oauth/account-import/registry.ts +18 -0
  547. package/src/oauth/account-import/service.ts +75 -0
  548. package/src/oauth/account-import/types.ts +91 -0
  549. package/src/oauth/anthropic-routing.ts +594 -0
  550. package/src/oauth/anthropic.ts +188 -0
  551. package/src/oauth/antigravity-routing.ts +151 -0
  552. package/src/oauth/callback-server.ts +300 -0
  553. package/src/oauth/chatgpt.ts +161 -0
  554. package/src/oauth/command-code.ts +239 -0
  555. package/src/oauth/cursor.ts +252 -0
  556. package/src/oauth/github-copilot.ts +428 -0
  557. package/src/oauth/google-antigravity.ts +262 -0
  558. package/src/oauth/health.ts +407 -0
  559. package/src/oauth/index.ts +1504 -0
  560. package/src/oauth/key-providers.ts +124 -0
  561. package/src/oauth/kimi.ts +227 -0
  562. package/src/oauth/kiro-credentials.ts +726 -0
  563. package/src/oauth/kiro.ts +621 -0
  564. package/src/oauth/local-token-detect.ts +130 -0
  565. package/src/oauth/log.ts +50 -0
  566. package/src/oauth/login-cli.ts +223 -0
  567. package/src/oauth/nous.ts +798 -0
  568. package/src/oauth/pkce.ts +15 -0
  569. package/src/oauth/store.ts +728 -0
  570. package/src/oauth/token-guardian.ts +309 -0
  571. package/src/oauth/types.ts +62 -0
  572. package/src/oauth/xai.ts +241 -0
  573. package/src/providers/alibaba-region-backup.ts +75 -0
  574. package/src/providers/alibaba-region-migration.ts +156 -0
  575. package/src/providers/alibaba-region-startup.ts +36 -0
  576. package/src/providers/antigravity-models.ts +695 -0
  577. package/src/providers/antigravity-quota.ts +216 -0
  578. package/src/providers/api-keys.ts +140 -0
  579. package/src/providers/base-url-choices.ts +74 -0
  580. package/src/providers/codex-capacity.ts +292 -0
  581. package/src/providers/command-code-efforts.ts +144 -0
  582. package/src/providers/context-cap.ts +82 -0
  583. package/src/providers/cursor-pool.ts +72 -0
  584. package/src/providers/derive.ts +586 -0
  585. package/src/providers/fastwire.ts +501 -0
  586. package/src/providers/free-directory.ts +187 -0
  587. package/src/providers/github-copilot-transport.ts +56 -0
  588. package/src/providers/google-vertex-location.ts +14 -0
  589. package/src/providers/key-failover.ts +271 -0
  590. package/src/providers/kiro-models.ts +67 -0
  591. package/src/providers/label.ts +19 -0
  592. package/src/providers/model-discovery-limits.ts +16 -0
  593. package/src/providers/model-discovery.ts +449 -0
  594. package/src/providers/model-rename-migration.ts +255 -0
  595. package/src/providers/model-rename-startup.ts +28 -0
  596. package/src/providers/openai-sidecar.ts +243 -0
  597. package/src/providers/openai-tier-startup.ts +56 -0
  598. package/src/providers/openai-tiers.ts +423 -0
  599. package/src/providers/openai-virtual-models.ts +83 -0
  600. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  601. package/src/providers/openrouter-routing.ts +102 -0
  602. package/src/providers/provider-id-rewrite.ts +185 -0
  603. package/src/providers/quota.ts +2345 -0
  604. package/src/providers/registry.ts +2918 -0
  605. package/src/providers/replit/constants.ts +27 -0
  606. package/src/providers/replit/derive.ts +85 -0
  607. package/src/providers/replit/headers.ts +28 -0
  608. package/src/providers/replit/origin.ts +55 -0
  609. package/src/providers/replit/pair-install-response.ts +72 -0
  610. package/src/providers/replit/probe.ts +199 -0
  611. package/src/providers/replit/setup.ts +350 -0
  612. package/src/providers/request-pacing.ts +310 -0
  613. package/src/providers/service-tier.ts +277 -0
  614. package/src/providers/slug-codec.ts +103 -0
  615. package/src/providers/static-model-discovery.ts +86 -0
  616. package/src/providers/xai-responses-opt-in.ts +15 -0
  617. package/src/providers/xai-transport.ts +148 -0
  618. package/src/reasoning-effort.ts +183 -0
  619. package/src/responses/compaction.ts +142 -0
  620. package/src/responses/custom-tool-compat.ts +266 -0
  621. package/src/responses/hosted-tool-policy.ts +9 -0
  622. package/src/responses/namespace-tool-compat.ts +355 -0
  623. package/src/responses/parser.ts +838 -0
  624. package/src/responses/provider-continuation.ts +98 -0
  625. package/src/responses/provider-opaque-metadata.ts +73 -0
  626. package/src/responses/reasoning-envelope.ts +60 -0
  627. package/src/responses/reasoning-replay-cache.ts +426 -0
  628. package/src/responses/schema.ts +165 -0
  629. package/src/responses/spill-store.ts +459 -0
  630. package/src/responses/state.ts +1433 -0
  631. package/src/responses/thought-signature-replay.ts +347 -0
  632. package/src/responses/tool-groups.ts +19 -0
  633. package/src/responses/tool-search-compat.ts +301 -0
  634. package/src/responses/truncated-stop-reason.ts +60 -0
  635. package/src/router.ts +761 -0
  636. package/src/routing/analytics.ts +378 -0
  637. package/src/routing/capability.ts +244 -0
  638. package/src/routing/compatibility/assemble.ts +73 -0
  639. package/src/routing/compatibility/behavior.ts +278 -0
  640. package/src/routing/compatibility/catalog.ts +99 -0
  641. package/src/routing/compatibility/endpoint.ts +52 -0
  642. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  643. package/src/routing/compatibility/policy.ts +181 -0
  644. package/src/routing/compatibility/provider-slot.ts +56 -0
  645. package/src/routing/compatibility/reader.ts +110 -0
  646. package/src/routing/compatibility/subject.ts +191 -0
  647. package/src/routing/compatibility/types.ts +64 -0
  648. package/src/routing/compatibility/version.ts +104 -0
  649. package/src/routing/cost.ts +77 -0
  650. package/src/routing/evaluator.ts +495 -0
  651. package/src/routing/health.ts +412 -0
  652. package/src/routing/history/cursor.ts +43 -0
  653. package/src/routing/history/indexer.ts +605 -0
  654. package/src/routing/history/schema.ts +72 -0
  655. package/src/routing/profile-namespace.ts +15 -0
  656. package/src/routing/profile.ts +547 -0
  657. package/src/routing/quota.ts +145 -0
  658. package/src/routing/request-evidence.ts +45 -0
  659. package/src/routing/trace.ts +776 -0
  660. package/src/server/adapter-resolve.ts +53 -0
  661. package/src/server/auth-cors.ts +751 -0
  662. package/src/server/background-lifecycle.ts +182 -0
  663. package/src/server/chat-completions.ts +442 -0
  664. package/src/server/chat-native-sse.ts +331 -0
  665. package/src/server/chat-native.ts +426 -0
  666. package/src/server/claude-messages.ts +1030 -0
  667. package/src/server/direct-local-http.ts +347 -0
  668. package/src/server/effort-policy.ts +190 -0
  669. package/src/server/github-copilot-responses-repair.ts +338 -0
  670. package/src/server/gui-static.ts +152 -0
  671. package/src/server/image-retry.ts +42 -0
  672. package/src/server/images.ts +568 -0
  673. package/src/server/index.ts +1813 -0
  674. package/src/server/lifecycle.ts +498 -0
  675. package/src/server/live.ts +717 -0
  676. package/src/server/local-management-read-client.ts +90 -0
  677. package/src/server/local-provider-reload-client.ts +137 -0
  678. package/src/server/management/agent-settings-routes.ts +1433 -0
  679. package/src/server/management/api-access.ts +141 -0
  680. package/src/server/management/api-key-usage.ts +193 -0
  681. package/src/server/management/body.ts +41 -0
  682. package/src/server/management/combo-routes.ts +263 -0
  683. package/src/server/management/config-routes.ts +835 -0
  684. package/src/server/management/context.ts +113 -0
  685. package/src/server/management/integration-routes.ts +498 -0
  686. package/src/server/management/lab-automation-routes.ts +206 -0
  687. package/src/server/management/lab-routes.ts +563 -0
  688. package/src/server/management/logs-usage-routes.ts +586 -0
  689. package/src/server/management/model-routes.ts +560 -0
  690. package/src/server/management/model-rows.ts +163 -0
  691. package/src/server/management/native-integration-routes.ts +769 -0
  692. package/src/server/management/oauth-account-routes.ts +637 -0
  693. package/src/server/management/provider-capability-config.ts +48 -0
  694. package/src/server/management/provider-routes.ts +1033 -0
  695. package/src/server/management/replit-provider-routes.ts +86 -0
  696. package/src/server/management/request-history-routes.ts +191 -0
  697. package/src/server/management/routing-analytics-routes.ts +74 -0
  698. package/src/server/management/routing-profile-routes.ts +385 -0
  699. package/src/server/management/shared.ts +286 -0
  700. package/src/server/management/sidebar-routes.ts +106 -0
  701. package/src/server/management/storage-log-guard-routes.ts +186 -0
  702. package/src/server/management/sync-response.ts +69 -0
  703. package/src/server/management/system-restart.ts +435 -0
  704. package/src/server/management/system-routes.ts +194 -0
  705. package/src/server/management/usage-summary-cache.ts +94 -0
  706. package/src/server/management/vision-sidecar-options.ts +167 -0
  707. package/src/server/management/web-search-sidecar-options.ts +120 -0
  708. package/src/server/management-api.ts +314 -0
  709. package/src/server/management-auth.ts +482 -0
  710. package/src/server/memory-watchdog.ts +156 -0
  711. package/src/server/passive-route-linker.ts +66 -0
  712. package/src/server/port-reclaim.ts +307 -0
  713. package/src/server/ports.ts +156 -0
  714. package/src/server/proxy-liveness.ts +328 -0
  715. package/src/server/readiness.ts +99 -0
  716. package/src/server/relay-eager.ts +353 -0
  717. package/src/server/relay.ts +1209 -0
  718. package/src/server/request-decompress.ts +239 -0
  719. package/src/server/request-log-conversation.ts +168 -0
  720. package/src/server/request-log.ts +1259 -0
  721. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  722. package/src/server/responses/agent-task-recovery.ts +465 -0
  723. package/src/server/responses/collaboration.ts +551 -0
  724. package/src/server/responses/compact.ts +771 -0
  725. package/src/server/responses/core.ts +5389 -0
  726. package/src/server/responses/empty-completion-guard.ts +276 -0
  727. package/src/server/responses/encrypted-payload.ts +331 -0
  728. package/src/server/responses/fetch-helpers.ts +232 -0
  729. package/src/server/responses/input-admission.ts +185 -0
  730. package/src/server/responses/pacing-overload.ts +13 -0
  731. package/src/server/responses/passthrough-error.ts +78 -0
  732. package/src/server/responses/policy-fallback.ts +178 -0
  733. package/src/server/responses/responses-field-backfill.ts +251 -0
  734. package/src/server/responses/terminal-guard.ts +251 -0
  735. package/src/server/responses/upstream-error.ts +53 -0
  736. package/src/server/responses/ws-upstream.ts +308 -0
  737. package/src/server/responses-custom-tool-repair.ts +282 -0
  738. package/src/server/responses-image-gen-repair.ts +132 -0
  739. package/src/server/responses-item-id-repair.ts +272 -0
  740. package/src/server/responses-json-events.ts +90 -0
  741. package/src/server/responses-model-rewrite.ts +29 -0
  742. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  743. package/src/server/responses-snapshot-repair.ts +621 -0
  744. package/src/server/responses-terminal-repair.ts +342 -0
  745. package/src/server/responses-tool-search-repair.ts +267 -0
  746. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  747. package/src/server/responses.ts +25 -0
  748. package/src/server/search.ts +201 -0
  749. package/src/server/sse-frame-buffer.ts +292 -0
  750. package/src/server/sse-payload-rewrite.ts +263 -0
  751. package/src/server/startup-action-control.ts +315 -0
  752. package/src/server/startup-health-cache.ts +131 -0
  753. package/src/server/system-env.ts +484 -0
  754. package/src/server/windows-tcp-drop.ts +184 -0
  755. package/src/server/windows-tray-control.ts +41 -0
  756. package/src/server/ws-bridge.ts +472 -0
  757. package/src/service-manager-probe.ts +892 -0
  758. package/src/service.ts +3575 -0
  759. package/src/sidecar/auth.ts +92 -0
  760. package/src/sidecar/candidates.ts +83 -0
  761. package/src/stall-timeout.ts +20 -0
  762. package/src/storage/cleanup-job.ts +57 -0
  763. package/src/storage/cleanup.ts +3085 -0
  764. package/src/storage/policy-job.ts +457 -0
  765. package/src/storage/policy-scheduler.ts +40 -0
  766. package/src/storage/policy-worker.ts +59 -0
  767. package/src/storage/policy.ts +527 -0
  768. package/src/storage/restore-job.ts +299 -0
  769. package/src/storage/restore-worker.ts +58 -0
  770. package/src/storage/scanner.ts +238 -0
  771. package/src/storage/storage-mutation-coordinator.ts +139 -0
  772. package/src/storage/worker-lifecycle.ts +215 -0
  773. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  774. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  775. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  776. package/src/tray/assets/opencodex-tray.png +0 -0
  777. package/src/tray/windows-tray.ps1 +364 -0
  778. package/src/tray/windows.ts +757 -0
  779. package/src/types/accounts.ts +37 -0
  780. package/src/types/config.ts +876 -0
  781. package/src/types/provider.ts +545 -0
  782. package/src/types/request.ts +384 -0
  783. package/src/types/tools.ts +131 -0
  784. package/src/types/wire.ts +80 -0
  785. package/src/types.ts +106 -0
  786. package/src/update/badge.ts +72 -0
  787. package/src/update/index.ts +415 -0
  788. package/src/update/job.ts +1887 -0
  789. package/src/update/notify.ts +263 -0
  790. package/src/update/npm-cache-preflight.d.mts +47 -0
  791. package/src/update/npm-cache-preflight.mjs +201 -0
  792. package/src/update/npm-invocation.d.mts +23 -0
  793. package/src/update/npm-invocation.mjs +94 -0
  794. package/src/update/transactional-install.d.mts +22 -0
  795. package/src/update/transactional-install.mjs +259 -0
  796. package/src/update/tray-update-plan.d.mts +18 -0
  797. package/src/update/tray-update-plan.mjs +38 -0
  798. package/src/usage/cost.ts +625 -0
  799. package/src/usage/debug.ts +97 -0
  800. package/src/usage/expected-prices.ts +416 -0
  801. package/src/usage/log.ts +1223 -0
  802. package/src/usage/summary.ts +753 -0
  803. package/src/usage/totals.ts +14 -0
  804. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  805. package/src/usage/user-cost-overlays.ts +314 -0
  806. package/src/vision/anthropic-describe.ts +189 -0
  807. package/src/vision/backends.ts +97 -0
  808. package/src/vision/describe.ts +131 -0
  809. package/src/vision/eligibility.ts +250 -0
  810. package/src/vision/index.ts +681 -0
  811. package/src/vision/reasoning.ts +55 -0
  812. package/src/vision/routed-describe.ts +175 -0
  813. package/src/vision/timeout-bounds.ts +9 -0
  814. package/src/web-search/anthropic-executor.ts +195 -0
  815. package/src/web-search/backends.ts +108 -0
  816. package/src/web-search/exa-executor.ts +88 -0
  817. package/src/web-search/executor.ts +113 -0
  818. package/src/web-search/format-result.ts +89 -0
  819. package/src/web-search/gemini-executor.ts +141 -0
  820. package/src/web-search/index.ts +331 -0
  821. package/src/web-search/loop.ts +896 -0
  822. package/src/web-search/parse.ts +315 -0
  823. package/src/web-search/progress-stream.ts +342 -0
  824. package/src/web-search/sources.ts +60 -0
  825. package/src/web-search/synthetic-tool.ts +47 -0
  826. package/src/web-search/xai-executor.ts +219 -0
@@ -0,0 +1,838 @@
1
+ import type {
2
+ OcxAssistantMessage,
3
+ OcxContentPart,
4
+ OcxContext,
5
+ OcxMessage,
6
+ OcxParsedRequest,
7
+ OcxRequestOptions,
8
+ OcxTextContent,
9
+ OcxThinkingContent,
10
+ OcxTool,
11
+ OcxToolCall,
12
+ OcxReasoningReplayScopeRef,
13
+ } from "../types";
14
+ import { namespacedToolName, toolChoiceCandidates } from "../types";
15
+ import { responsesRequestSchema } from "./schema";
16
+ import { providerMetadataFromResponsesFunctionCall } from "./provider-opaque-metadata";
17
+ import { lookupReplayThoughtSignature } from "./thought-signature-replay";
18
+ import { compactionItemToText, isCompactionItemType } from "./compaction";
19
+ import { previousResponseReplayPrefixLength } from "./state";
20
+ import { decodeReasoningEnvelope } from "./reasoning-envelope";
21
+ import { extractHostedWebSearch, WEB_SEARCH_TOOL_NAME } from "../web-search/synthetic-tool";
22
+ import { extractHostedImageGeneration, IMAGE_GEN_TOOL_NAME } from "../images/synthetic-tool";
23
+ import { toolSearchDescription, toolSearchParameters } from "./tool-search-compat";
24
+
25
+ function isObj(v: unknown): v is Record<string, unknown> {
26
+ return typeof v === "object" && v !== null && !Array.isArray(v);
27
+ }
28
+
29
+ /**
30
+ * Wrap a remembered proxy-side signature as provider metadata for a replayed tool call.
31
+ *
32
+ * The scope is REQUIRED for a hit. `parseRequest` runs before the route and account are
33
+ * chosen, so a caller that has not yet bound a replay scope gets nothing rather than a
34
+ * signature belonging to some other thread that happened to reuse the same `call_id`.
35
+ */
36
+ function replayThoughtSignatureMetadata(
37
+ callId: string,
38
+ scope: OcxReasoningReplayScopeRef | undefined,
39
+ ): { google: { thoughtSignature: string } } | undefined {
40
+ const signature = lookupReplayThoughtSignature(callId, scope);
41
+ return signature ? { google: { thoughtSignature: signature } } : undefined;
42
+ }
43
+
44
+ type InputBlock =
45
+ | { type: "input_text"; text: string }
46
+ | { type: "text"; text: string }
47
+ | { type: "input_image"; image_url?: string; file_id?: string; detail?: string }
48
+ | { type: "input_file"; file_id?: string; filename?: string; file_data?: string };
49
+
50
+ /** A usable reference string, or undefined. Empty strings and non-strings are not references. */
51
+ function nonEmptyString(value: unknown): string | undefined {
52
+ return typeof value === "string" && value.length > 0 ? value : undefined;
53
+ }
54
+
55
+ function inputContentParts(blocks: unknown): string | OcxContentPart[] {
56
+ if (typeof blocks === "string") return blocks;
57
+ // The catch-all can also hand back a non-array `content` (an object, a number), which would
58
+ // throw at the loop below before any per-block guard runs.
59
+ if (!Array.isArray(blocks)) return [];
60
+ const parts: OcxContentPart[] = [];
61
+ for (const raw of blocks) {
62
+ // A malformed message item fails its strict schema and falls through to inputItemSchema's
63
+ // permissive catch-all, so blocks reaching here are NOT guaranteed to match the declared
64
+ // shape. Validate each field before use, as outputToToolResultContent already does.
65
+ if (!isObj(raw)) continue;
66
+ const block = raw as InputBlock;
67
+ if (block.type === "input_text" || block.type === "text") {
68
+ if (typeof raw.text === "string") parts.push({ type: "text", text: raw.text });
69
+ } else if (block.type === "input_image") {
70
+ const b = block as { image_url?: string; file_id?: string; detail?: string };
71
+ const imageUrl = nonEmptyString(b.image_url);
72
+ const fileId = nonEmptyString(b.file_id);
73
+ const detail = nonEmptyString(b.detail);
74
+ if (imageUrl) {
75
+ // Preserve the image as a structured part — adapters send it as a native image block.
76
+ // NEVER inline the (often base64 data-URL) image_url as text: that explodes the token count.
77
+ parts.push({ type: "image", imageUrl, ...(detail ? { detail: normalizeImageDetail(detail) } : {}) });
78
+ } else if (fileId) {
79
+ parts.push({ type: "text", text: `[image: ${fileId}]` }); // file_id ref → no inline data
80
+ }
81
+ // No usable reference: omit the block. A "[image: ?]" marker would claim an attachment
82
+ // the request never carried, which is worse than dropping malformed input.
83
+ } else if (block.type === "input_file") {
84
+ const b = block as { file_id?: string; filename?: string; file_data?: string };
85
+ const fileId = nonEmptyString(b.file_id);
86
+ const fileData = nonEmptyString(b.file_data);
87
+ const filename = nonEmptyString(b.filename);
88
+ if (fileId) {
89
+ parts.push({ type: "text", text: `[file: ${fileId}]` });
90
+ } else if (fileData) {
91
+ // Inline file_data is often large base64. Preserve only its presence and name, never bytes.
92
+ parts.push({ type: "text", text: filename ? `[file: ${filename}]` : "[file: inline data]" });
93
+ }
94
+ // A bare filename is not a file resource in the Responses schema, so omit it rather than
95
+ // fabricating a "[file: ...]" marker for an attachment that was never sent.
96
+ }
97
+ }
98
+ // Collapse to a plain string only for a single TEXT part; images must stay structured.
99
+ if (parts.length === 1 && parts[0].type === "text") return parts[0].text;
100
+ return parts;
101
+ }
102
+
103
+ type OutputBlock = { type: "output_text"; text: string } | { type: "text"; text: string } | { type: "refusal"; refusal: string };
104
+
105
+ function outputTextOf(blocks: unknown): OcxTextContent[] {
106
+ if (typeof blocks === "string") return blocks.length > 0 ? [{ type: "text", text: blocks }] : [];
107
+ if (!Array.isArray(blocks)) return [];
108
+ const out: OcxTextContent[] = [];
109
+ for (const raw of blocks) {
110
+ // Same catch-all caveat as inputContentParts: validate before use.
111
+ if (!isObj(raw)) continue;
112
+ const b = raw as OutputBlock;
113
+ if (b.type === "output_text" || b.type === "text") {
114
+ if (typeof raw.text === "string") out.push({ type: "text", text: raw.text });
115
+ } else if (b.type === "refusal") {
116
+ if (typeof raw.refusal === "string") out.push({ type: "text", text: `[refusal: ${raw.refusal}]` });
117
+ }
118
+ }
119
+ return out;
120
+ }
121
+
122
+ function mapToolChoice(value: unknown): OcxRequestOptions["toolChoice"] {
123
+ if (value === undefined || value === null) return undefined;
124
+ if (value === "auto" || value === "none" || value === "required") return value;
125
+ if (isObj(value) && "type" in value) {
126
+ const t = (value as { type: string }).type;
127
+ if ((t === "function" || t === "custom") && "name" in value) {
128
+ return { name: (value as { name: string }).name };
129
+ }
130
+ // Hosted image tool types (with or without a name) map to the synthetic image_gen wire name.
131
+ if (t === "image_generation" || t === "image_gen") {
132
+ return { name: IMAGE_GEN_TOOL_NAME };
133
+ }
134
+ if (t === "allowed_tools" && Array.isArray(value.tools)) {
135
+ const names = value.tools
136
+ .map(allowedToolName)
137
+ .filter((name): name is string => Boolean(name));
138
+ return names.length > 0
139
+ ? { allowedTools: [...new Set(names)], mode: value.mode === "required" ? "required" : "auto" }
140
+ : "none";
141
+ }
142
+ return "auto";
143
+ }
144
+ return undefined;
145
+ }
146
+
147
+ function allowedToolName(tool: unknown): string | undefined {
148
+ if (!isObj(tool)) return undefined;
149
+ if (typeof tool.name === "string" && tool.name.length > 0) return tool.name;
150
+ if (tool.type === "web_search" || tool.type === "web_search_preview") return WEB_SEARCH_TOOL_NAME;
151
+ if (tool.type === "image_generation" || tool.type === "image_gen") return IMAGE_GEN_TOOL_NAME;
152
+ if (tool.type === "tool_search") return "tool_search";
153
+ return undefined;
154
+ }
155
+
156
+ function buildTools(tools: unknown[] | undefined): OcxTool[] | undefined {
157
+ if (!tools) return undefined;
158
+ const out: OcxTool[] = [];
159
+ const normalizeParameters = (raw: unknown): Record<string, unknown> => {
160
+ if (isObj(raw) && raw.type === "object") return raw;
161
+ return { ...(isObj(raw) ? raw : {}), type: "object" };
162
+ };
163
+ const pushFn = (t: Record<string, unknown>, namespace?: string) => {
164
+ const tool: OcxTool = {
165
+ name: t.name as string,
166
+ description: (t.description as string) ?? "",
167
+ parameters: normalizeParameters(t.parameters),
168
+ };
169
+ if (t.strict !== undefined) tool.strict = t.strict as boolean;
170
+ if (namespace) tool.namespace = namespace;
171
+ out.push(tool);
172
+ };
173
+ const pushCustom = (t: Record<string, unknown>, namespace?: string) => {
174
+ // Freeform custom tools are lowered to a single string `input` because chat models cannot
175
+ // emit Responses grammar payloads directly. Keep tool-specific input guidance scoped to the
176
+ // tool that owns it: leaking apply_patch syntax into `exec` or another freeform tool teaches
177
+ // routed models that the nested helper name is itself a callable top-level tool.
178
+ const inputDescription = t.name === "apply_patch"
179
+ ? "Raw tool input. For apply_patch, begin exactly with `*** Begin Patch` (no trailing `***`), then use its standard patch envelope."
180
+ : "Raw freeform input for this tool.";
181
+ const tool: OcxTool = {
182
+ name: t.name as string,
183
+ description: (t.description as string) ?? "",
184
+ parameters: { type: "object", properties: { input: { type: "string", description: inputDescription } }, required: ["input"] },
185
+ freeform: true,
186
+ };
187
+ if (namespace) tool.namespace = namespace;
188
+ out.push(tool);
189
+ };
190
+ for (const t of tools) {
191
+ if (!isObj(t)) continue;
192
+ if (t.type === "function" && isObj(t.function) && typeof t.function.name === "string" && t.function.name.length > 0) {
193
+ pushFn(t.function as Record<string, unknown>);
194
+ continue;
195
+ }
196
+ if (t.type === "function" && typeof t.name === "string") {
197
+ pushFn(t);
198
+ } else if (t.type === "namespace" && Array.isArray(t.tools)) {
199
+ // Codex 0.147 groups its ordinary client tools under the reserved `functions` namespace,
200
+ // including freeform custom tools such as code-mode `exec`. Those children are still
201
+ // top-level Responses tools, so flatten them without a namespace. Other namespace groups
202
+ // are MCP-style and keep their namespace for round-trip routing.
203
+ const builtinFunctions = t.name === "functions";
204
+ const ns = typeof t.name === "string" && !builtinFunctions ? t.name : undefined;
205
+ for (const inner of t.tools as unknown[]) {
206
+ if (isObj(inner) && inner.type === "function" && typeof inner.name === "string") pushFn(inner, ns);
207
+ else if (isObj(inner) && inner.type === "custom" && typeof inner.name === "string") pushCustom(inner, ns);
208
+ }
209
+ }
210
+ else if (t.type === "custom" && typeof t.name === "string") {
211
+ pushCustom(t);
212
+ }
213
+ else if (t.type === "tool_search") {
214
+ // Client-executed tool discovery — the gateway to deferred tools (subagents, extra MCP tools).
215
+ // Expose as a function so chat models can call it; the bridge relays it as a tool_search_call.
216
+ out.push({
217
+ name: "tool_search",
218
+ description: toolSearchDescription(t),
219
+ parameters: normalizeParameters(toolSearchParameters(t)),
220
+ toolSearch: true,
221
+ });
222
+ }
223
+ else if (typeof t.name === "string" && t.type !== "web_search" && t.type !== "image_generation") {
224
+ // Any OTHER named tool (e.g. a native/computer-use tool type opencodex doesn't explicitly
225
+ // model) is client-executed — pass it through as a function so the routed model can read and
226
+ // call it naturally; the bridge relays its call as a function_call. Previously such tools were
227
+ // silently dropped, so the model never saw them.
228
+ pushFn(t);
229
+ }
230
+ // Only the OpenAI-hosted server-side tools (web_search, image_generation) are intentionally
231
+ // dropped — they're executed by OpenAI and can't be relayed to a routed chat model.
232
+ }
233
+ return out.length > 0 ? out : undefined;
234
+ }
235
+
236
+ function ensureAssistantPlaceholder(messages: OcxMessage[], modelId: string, now: number): OcxAssistantMessage {
237
+ const last = messages[messages.length - 1];
238
+ if (last && last.role === "assistant") return last;
239
+ const placeholder: OcxAssistantMessage = { role: "assistant", content: [], model: modelId, timestamp: now };
240
+ messages.push(placeholder);
241
+ return placeholder;
242
+ }
243
+
244
+ /**
245
+ * Tool-call output content. Preserves images (e.g. Codex `view_image` returns
246
+ * `input_image` items): returns content parts when any image is present, else a plain joined string.
247
+ * Never inlines an image_url as text (that would explode the token count).
248
+ */
249
+ function outputToToolResultContent(output: string | unknown[] | undefined): string | OcxContentPart[] {
250
+ if (typeof output === "string") return output;
251
+ if (!Array.isArray(output)) return "";
252
+ const parts: OcxContentPart[] = [];
253
+ let hasImage = false;
254
+ for (const raw of output) {
255
+ if (!isObj(raw)) continue;
256
+ if (raw.type === "output_text" || raw.type === "text" || raw.type === "input_text") {
257
+ if (typeof raw.text === "string") parts.push({ type: "text", text: raw.text });
258
+ } else if (raw.type === "refusal" && typeof raw.refusal === "string") {
259
+ parts.push({ type: "text", text: `[refusal: ${raw.refusal}]` });
260
+ } else if (raw.type === "input_image" && typeof raw.image_url === "string") {
261
+ parts.push({ type: "image", imageUrl: raw.image_url, ...(typeof raw.detail === "string" ? { detail: normalizeImageDetail(raw.detail) } : {}) });
262
+ hasImage = true;
263
+ } else if (raw.type === "encrypted_content") {
264
+ // codex-rs FunctionCallOutputContentItem::EncryptedContent — opaque to routed models.
265
+ parts.push({ type: "text", text: "[encrypted content omitted]" });
266
+ }
267
+ }
268
+ if (!hasImage) return parts.map(p => (p.type === "text" ? p.text : "")).join("");
269
+ return parts;
270
+ }
271
+
272
+ function toolOutputContainsEncryptedContent(output: string | unknown[] | undefined): boolean {
273
+ return Array.isArray(output) && output.some(raw => isObj(raw) && raw.type === "encrypted_content");
274
+ }
275
+
276
+ /**
277
+ * codex-rs ImageDetail allows "original", but chat-completions providers only accept
278
+ * auto|low|high on image_url.detail — degrade "original" to "high" (the codex default).
279
+ */
280
+ function normalizeImageDetail(detail: string): string {
281
+ return detail === "original" ? "high" : detail;
282
+ }
283
+
284
+ function findToolById(messages: OcxMessage[], callId: string): { name: string; namespace?: string } {
285
+ for (let i = messages.length - 1; i >= 0; i--) {
286
+ const m = messages[i];
287
+ if (m.role !== "assistant") continue;
288
+ for (const part of m.content) {
289
+ if (part.type === "toolCall" && part.id === callId) return { name: part.name, namespace: part.namespace };
290
+ }
291
+ }
292
+ return { name: "" };
293
+ }
294
+
295
+ /**
296
+ * Attach pending reasoning to the assistant turn that owns the given call id.
297
+ * Reconstructed histories (resume/retry/synthetic) can order a `reasoning`
298
+ * item AFTER the `function_call` it belongs to; without this, the pending
299
+ * buffer is cleared at the tool output and the turn serializes without
300
+ * `reasoning_content`, which DeepSeek thinking mode rejects with HTTP 400
301
+ * (issue #950).
302
+ */
303
+ function attachPendingReasoningToCallOwner(
304
+ messages: OcxMessage[],
305
+ callId: string,
306
+ pendingReasoning: Array<{ part: OcxThinkingContent; envelopeSigned: boolean }>,
307
+ ): void {
308
+ if (pendingReasoning.length === 0 || !callId) return;
309
+ for (let i = messages.length - 1; i >= 0; i--) {
310
+ const m = messages[i];
311
+ if (m.role !== "assistant") continue;
312
+ for (const part of m.content) {
313
+ if (part.type === "toolCall" && part.id === callId) {
314
+ // Prepend so thinking still precedes tool_use for adapters that require
315
+ // that ordering (Anthropic-style replay).
316
+ m.content = [...pendingReasoning.map(entry => entry.part), ...m.content];
317
+ return;
318
+ }
319
+ }
320
+ }
321
+ }
322
+
323
+ const REASONING_EFFORTS = new Set(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);
324
+
325
+ /**
326
+ * Namespace a custom tool was declared under, by its bare name.
327
+ *
328
+ * A `custom_tool_call` echoed back by the client carries only the bare name — the bridge
329
+ * emits `{"type":"custom_tool_call","name":"exec"}` even when the tool was declared as
330
+ * `mcp__functions__exec`. Without this lookup the namespace is lost on the return trip,
331
+ * and the adapters replay history through `namespacedToolName(namespace, name)`, which
332
+ * then produces a bare `exec` the provider may not have. Ordinary `function_call` items
333
+ * do not need this: they carry `namespace` on the wire.
334
+ */
335
+ function customToolNamespaces(tools: unknown): Map<string, string> {
336
+ const out = new Map<string, string>();
337
+ if (!Array.isArray(tools)) return out;
338
+ for (const spec of tools) {
339
+ if (!isObj(spec) || spec.type !== "namespace" || !Array.isArray(spec.tools)) continue;
340
+ const namespace = typeof spec.name === "string" ? spec.name : undefined;
341
+ // Codex 0.147 groups ordinary client tools under the reserved `functions` namespace and
342
+ // buildTools deliberately flattens those without a namespace. Mirror that here, or the
343
+ // reconstruction would invent a namespace the request never advertised.
344
+ if (!namespace || namespace === "functions") continue;
345
+ for (const inner of spec.tools) {
346
+ if (!isObj(inner) || inner.type !== "custom" || typeof inner.name !== "string") continue;
347
+ // Ambiguous bare names are already rejected upstream, so first declaration wins.
348
+ if (!out.has(inner.name)) out.set(inner.name, namespace);
349
+ }
350
+ }
351
+ return out;
352
+ }
353
+
354
+ export function parseRequest(
355
+ body: unknown,
356
+ parseOptions?: { replayCacheScope?: OcxReasoningReplayScopeRef },
357
+ ): OcxParsedRequest {
358
+ const replayCacheScope = parseOptions?.replayCacheScope;
359
+ const replayedInputPrefixLength = previousResponseReplayPrefixLength(body);
360
+ const parsed = responsesRequestSchema.safeParse(body);
361
+ if (!parsed.success) {
362
+ throw new Error(`responses parse error: ${parsed.error.message}`);
363
+ }
364
+ const data = parsed.data;
365
+ const now = Date.now();
366
+ const messages: OcxMessage[] = [];
367
+ // Built before the item loop: a custom_tool_call echoed back in `input` needs the
368
+ // namespace from the request's own tool catalog to survive the round trip.
369
+ const customToolNamespacesByName = customToolNamespaces(data.tools);
370
+ const systemPrompt: string[] = [];
371
+ // Responses reasoning siblings belong to the following assistant, including across call items.
372
+ // Keep them off the message list until that assistant arrives; turn boundaries clear the array.
373
+ const pendingReasoning: Array<{ part: OcxThinkingContent; envelopeSigned: boolean }> = [];
374
+ // Assistant placeholder that first folds any pending reasoning into the same turn (official
375
+ // grok-build preserves reasoning across call items; Anthropic replay requires thinking to
376
+ // precede tool_use inside one assistant message).
377
+ const assistantHolderWithReasoning = (): OcxAssistantMessage => {
378
+ const holder = ensureAssistantPlaceholder(messages, data.model, now);
379
+ if (pendingReasoning.length > 0) {
380
+ holder.content.push(...pendingReasoning.map(entry => entry.part));
381
+ pendingReasoning.length = 0;
382
+ }
383
+ return holder;
384
+ };
385
+ // Tool specs surfaced by a prior tool_search (deferred tools, e.g. subagents). Codex does not
386
+ // re-list these in `tools`, but chat models can only call listed tools — so we re-inject them.
387
+ const loadedToolSpecs: unknown[] = [];
388
+ // Remote compaction v2: the input tail carries `{type:"compaction_trigger"}` and Codex expects a
389
+ // synthetic `{type:"compaction"}` output item (src/responses/compaction.ts). Flagged for the server.
390
+ let compactionRequest = false;
391
+ let contextCompactionBoundary = false;
392
+ let continuationConversationMessageIndex: number | undefined;
393
+
394
+ if (typeof data.instructions === "string" && data.instructions.length > 0) {
395
+ systemPrompt.push(data.instructions);
396
+ }
397
+
398
+ if (typeof data.input === "string") {
399
+ if (data.previous_response_id) continuationConversationMessageIndex = messages.length;
400
+ messages.push({ role: "user", content: data.input, timestamp: now });
401
+ } else if (data.input) {
402
+ for (let inputIndex = 0; inputIndex < data.input.length; inputIndex++) {
403
+ const item = data.input[inputIndex];
404
+ const effectiveType = (item as { type?: string }).type ?? ("role" in item ? "message" : undefined);
405
+ const itemRole = (item as { role?: string }).role;
406
+ // Raw protocol items do not map one-to-one onto context messages. Capture the boundary while
407
+ // both representations are available so later metadata can stay before conversation in both.
408
+ if (
409
+ data.previous_response_id
410
+ && inputIndex >= replayedInputPrefixLength
411
+ && continuationConversationMessageIndex === undefined
412
+ && (
413
+ effectiveType === "agent_message"
414
+ || (effectiveType === "message" && (itemRole === "user" || itemRole === "assistant"))
415
+ )
416
+ ) {
417
+ continuationConversationMessageIndex = messages.length;
418
+ }
419
+
420
+ if (effectiveType === "compaction_trigger") {
421
+ compactionRequest = true;
422
+ continue;
423
+ }
424
+
425
+ if (effectiveType === "additional_tools") {
426
+ // Codex Desktop responses_lite WS path: tools ride INSIDE input as an
427
+ // `additional_tools` item ({type, role, tools:[...]}) instead of body.tools.
428
+ // Same spec wire shapes (function/namespace/custom/tool_search) — collect and
429
+ // merge through the exact buildTools path so surface detection (collabSurface)
430
+ // and chat-model tool listing see them. The item itself never becomes a message;
431
+ // the native passthrough keeps it verbatim in _rawBody.
432
+ const at = item as { tools?: unknown[] };
433
+ if (Array.isArray(at.tools)) loadedToolSpecs.push(...at.tools);
434
+ continue;
435
+ }
436
+
437
+ if (isCompactionItemType(effectiveType)) {
438
+ // A stored summary from a previous compaction. Decode our ocx1 envelope into plain text so
439
+ // the routed model keeps the compacted context; real OpenAI-encrypted blobs degrade to a note.
440
+ // `context_compaction` (encrypted_content optional) is codex-rs's local-compaction marker;
441
+ // with no payload it is a pure marker (the summary follows as its own user message), so it
442
+ // is dropped silently. It must NOT flag _compactionRequest. Only a marker newly appended in
443
+ // this request starts a provider-private context epoch; markers inside the prefix restored by
444
+ // previous_response_id were already acknowledged on the turn that introduced them.
445
+ if (inputIndex >= replayedInputPrefixLength) contextCompactionBoundary = true;
446
+ const encrypted = (item as { encrypted_content?: unknown }).encrypted_content;
447
+ if (effectiveType === "context_compaction" && typeof encrypted !== "string") continue;
448
+ pendingReasoning.length = 0;
449
+ messages.push({
450
+ role: "user",
451
+ content: compactionItemToText(typeof encrypted === "string" ? encrypted : undefined),
452
+ timestamp: now,
453
+ });
454
+ continue;
455
+ }
456
+
457
+ if (effectiveType === "agent_message") {
458
+ const agentMessage = item as {
459
+ author?: string;
460
+ recipient?: string;
461
+ content?: unknown;
462
+ };
463
+
464
+ const content = inputContentParts(agentMessage.content);
465
+
466
+ const hasContent =
467
+ typeof content === "string"
468
+ ? content.trim().length > 0
469
+ : content.length > 0;
470
+
471
+ // An agent_message is external input delivered to the parent agent.
472
+ // Preserve it as a user-role turn so signed Anthropic thinking blocks
473
+ // on either side are never merged into one modified assistant response.
474
+ pendingReasoning.length = 0;
475
+ messages.push({
476
+ role: "user",
477
+ content: hasContent ? content : "(sub-agent message received)",
478
+ timestamp: now,
479
+ });
480
+
481
+ continue;
482
+ }
483
+
484
+ if (effectiveType === "message") {
485
+ const msg = item as { role?: string; content?: unknown; phase?: "commentary" | "final_answer" };
486
+ switch (msg.role) {
487
+ case "system": {
488
+ pendingReasoning.length = 0;
489
+ const text = inputContentParts(msg.content);
490
+ const flat = typeof text === "string" ? text : text.map(p => (p.type === "text" ? p.text : "")).join("");
491
+ if (flat.length > 0) systemPrompt.push(flat);
492
+ break;
493
+ }
494
+ case "user":
495
+ case "developer": {
496
+ pendingReasoning.length = 0;
497
+ const content = inputContentParts(msg.content);
498
+ messages.push({ role: msg.role, content, timestamp: now });
499
+ break;
500
+ }
501
+ case "assistant": {
502
+ const parts = outputTextOf(msg.content);
503
+ messages.push({
504
+ role: "assistant",
505
+ content: pendingReasoning.length > 0
506
+ ? [...pendingReasoning.map(entry => entry.part), ...parts]
507
+ : parts,
508
+ ...(msg.phase ? { phase: msg.phase } : {}),
509
+ model: data.model,
510
+ timestamp: now,
511
+ });
512
+ pendingReasoning.length = 0;
513
+ break;
514
+ }
515
+ }
516
+ continue;
517
+ }
518
+
519
+ if (effectiveType === "reasoning") {
520
+ const reasoning = item as { id?: string; summary?: { text: string }[]; content?: { text: string }[]; encrypted_content?: string };
521
+ const fromSummary = (reasoning.summary ?? []).map(c => c.text).join("");
522
+ const text = fromSummary || (reasoning.content ?? []).map(c => c.text).join("");
523
+ const envelope = typeof reasoning.encrypted_content === "string"
524
+ ? decodeReasoningEnvelope(reasoning.encrypted_content)
525
+ : null;
526
+ const thinkingText = envelope?.txt || text;
527
+
528
+ // Kiro reasoning round-trip: a krc-only item carries nothing renderable — it is provider
529
+ // state for the assistant turn that ALREADY closed, because Kiro emits its
530
+ // reasoningContentEvent at the END of a turn (after content AND tool calls, verified
531
+ // against kiro-cli 2.14.1/2.16.0). Folding it into the FOLLOWING turn like ordinary
532
+ // reasoning would attach turn N's blob to turn N+1, so attach it backwards instead. With
533
+ // no assistant turn to own it the blob is dropped rather than mis-paired.
534
+ if (envelope?.krc && thinkingText.length === 0) {
535
+ const previous = messages[messages.length - 1];
536
+ if (previous?.role === "assistant") previous.kiroRedactedReasoning = envelope.krc;
537
+ continue;
538
+ }
539
+
540
+ // Native/non-ocxr1 encrypted-only reasoning is opaque here. Do not create a detached
541
+ // assistant turn or invent replayable plaintext/signatures from the encrypted payload.
542
+ if (thinkingText.length > 0) {
543
+ const part: OcxThinkingContent = {
544
+ type: "thinking",
545
+ thinking: thinkingText,
546
+ signature: envelope?.sig ?? JSON.stringify(reasoning),
547
+ ...(envelope?.red ? { redacted: envelope.red } : {}),
548
+ ...(reasoning.id ? { itemId: reasoning.id } : {}),
549
+ };
550
+ const envelopeSigned = typeof envelope?.sig === "string";
551
+ const previous = pendingReasoning[pendingReasoning.length - 1];
552
+
553
+ if (!envelopeSigned && previous && !previous.envelopeSigned) {
554
+ previous.part = {
555
+ ...part,
556
+ thinking: `${previous.part.thinking}\n${part.thinking}`,
557
+ };
558
+ } else {
559
+ pendingReasoning.push({ part, envelopeSigned });
560
+ }
561
+ }
562
+ continue;
563
+ }
564
+
565
+ if (effectiveType === "function_call") {
566
+ const call = item as { id?: string; call_id: string; name: string; arguments?: string; namespace?: string; extra_content?: unknown };
567
+ // Tolerate empty/non-JSON arguments (e.g. a no-arg tool call serialized as "") instead of
568
+ // throwing — a single poisoned history item would otherwise 400 every subsequent turn.
569
+ let args: Record<string, unknown> = {};
570
+ const rawArgs = call.arguments?.trim();
571
+ if (rawArgs) {
572
+ try {
573
+ const parsed: unknown = JSON.parse(rawArgs);
574
+ if (isObj(parsed)) args = parsed;
575
+ } catch {
576
+ console.warn(`[parser] function_call ${call.call_id} has non-JSON arguments; defaulting to {}`);
577
+ }
578
+ }
579
+ // Do NOT map Responses item `id` (fc_/ctc_/…) onto `thoughtSignature`. That field is
580
+ // reserved for Gemini/Antigravity opaque thought tokens; forwarding item ids as
581
+ // thoughtSignature 400s Antigravity (Base64 / TYPE_BYTES). Continuity for CCA comes from
582
+ // the in-process replay cache (and any already-real signature stored on the tool call).
583
+ const toolCall: OcxToolCall = {
584
+ type: "toolCall", id: call.call_id, name: call.name, arguments: args,
585
+ ...(call.namespace ? { namespace: call.namespace } : {}),
586
+ };
587
+ // Provider-opaque metadata (e.g. a Gemini thought signature) travels with the call so a
588
+ // history-replayed or previous_response_id turn rebuilds the same signed part instead of
589
+ // depending on the same-process replay cache (issue #1735). Real clients do not echo
590
+ // extra_content on replay, so fall back to the proxy-side store keyed by call_id.
591
+ const providerMetadata = providerMetadataFromResponsesFunctionCall(call)
592
+ ?? (typeof call.call_id === "string"
593
+ ? replayThoughtSignatureMetadata(call.call_id, replayCacheScope)
594
+ : undefined);
595
+ if (providerMetadata) toolCall.providerMetadata = providerMetadata;
596
+ assistantHolderWithReasoning().content.push(toolCall);
597
+ continue;
598
+ }
599
+
600
+ if (effectiveType === "custom_tool_call") {
601
+ const call = item as { id?: string; call_id: string; name: string; input: string };
602
+ const remembered = typeof call.call_id === "string" ? replayThoughtSignatureMetadata(call.call_id, replayCacheScope) : undefined;
603
+ // Reconstruct the namespace the request declared this tool under. The wire item
604
+ // carries only the bare name, so without this the round trip loses it and adapters
605
+ // replay the call as an unnamespaced tool the provider may not expose.
606
+ const customNamespace = customToolNamespacesByName.get(call.name);
607
+ const toolCall: OcxToolCall = {
608
+ type: "toolCall", id: call.call_id, name: call.name,
609
+ arguments: { input: call.input ?? "" },
610
+ customWireName: call.name,
611
+ ...(customNamespace ? { namespace: customNamespace } : {}),
612
+ ...(remembered ? { providerMetadata: remembered } : {}),
613
+ };
614
+ assistantHolderWithReasoning().content.push(toolCall);
615
+ continue;
616
+ }
617
+
618
+ if (effectiveType === "local_shell_call") {
619
+ // codex-rs LocalShellCall replay: pair it as an assistant toolCall so the subsequent
620
+ // function_call_output (same call_id) doesn't become an orphaned tool result.
621
+ const call = item as { id?: string; call_id?: string; action?: { type?: string; command?: string[] } };
622
+ const callId = call.call_id ?? call.id;
623
+ if (callId) {
624
+ const command = Array.isArray(call.action?.command) ? call.action.command : [];
625
+ const remembered = replayThoughtSignatureMetadata(callId, replayCacheScope);
626
+ assistantHolderWithReasoning().content.push({
627
+ type: "toolCall", id: callId, name: "shell",
628
+ arguments: command.length > 0 ? { command } : {},
629
+ ...(remembered ? { providerMetadata: remembered } : {}),
630
+ });
631
+ }
632
+ continue;
633
+ }
634
+
635
+ if (effectiveType === "web_search_call") {
636
+ // Replayed hosted web-search evidence has no paired result payload that routed providers can
637
+ // consume. Keep it out of assistant-visible text: the old marker was useful as an internal
638
+ // loop hint, but when no sidecar is available the model can echo it as a fake answer.
639
+ pendingReasoning.length = 0;
640
+ continue;
641
+ }
642
+
643
+ if (effectiveType === "tool_search_call") {
644
+ // Preserve the model's prior tool_search call as an assistant tool call so multi-turn
645
+ // history stays complete (otherwise the model re-issues tool_search forever).
646
+ const call = item as { id?: string; call_id?: string; arguments?: unknown };
647
+ const callId = call.call_id ?? call.id ?? "";
648
+ const remembered = callId ? replayThoughtSignatureMetadata(callId, replayCacheScope) : undefined;
649
+ assistantHolderWithReasoning().content.push({
650
+ type: "toolCall", id: callId, name: "tool_search",
651
+ arguments: isObj(call.arguments) ? call.arguments : {},
652
+ ...(remembered ? { providerMetadata: remembered } : {}),
653
+ });
654
+ continue;
655
+ }
656
+
657
+ if (effectiveType === "tool_search_output") {
658
+ pendingReasoning.length = 0;
659
+ // Pair the tool_search call with its result so the model sees what was loaded.
660
+ const out = item as { call_id?: string; status?: string; tools?: unknown[] };
661
+ const specs = Array.isArray(out.tools) ? (out.tools as Record<string, unknown>[]) : [];
662
+ loadedToolSpecs.push(...specs);
663
+ // List the EXACT wire names the model must call (flattened for namespaced specs), matching
664
+ // how buildTools exposes them — otherwise the model guesses wrong names (e.g. the bare namespace).
665
+ const wireNames: string[] = [];
666
+ for (const spec of specs) {
667
+ if (spec.type === "namespace" && Array.isArray(spec.tools)) {
668
+ for (const inner of spec.tools as Record<string, unknown>[]) {
669
+ if (typeof inner.name === "string") wireNames.push(namespacedToolName(spec.name as string, inner.name));
670
+ }
671
+ } else if (typeof spec.name === "string") {
672
+ wireNames.push(spec.name);
673
+ }
674
+ }
675
+ const failed = typeof out.status === "string" && out.status !== "completed" && out.status !== "success";
676
+ messages.push({
677
+ role: "toolResult", toolCallId: out.call_id ?? "", toolName: "tool_search",
678
+ content: failed && wireNames.length === 0
679
+ ? `Tool search failed (status: ${out.status}).`
680
+ : wireNames.length
681
+ ? `Tool search loaded these tools — they are now in your available tools. Call one by its EXACT name: ${wireNames.join(", ")}.`
682
+ : "Tool search returned no tools.",
683
+ isError: failed && wireNames.length === 0, timestamp: now,
684
+ });
685
+ continue;
686
+ }
687
+
688
+ if (effectiveType === "function_call_output") {
689
+ const output = item as { call_id: string; output?: string | unknown[] };
690
+ attachPendingReasoningToCallOwner(messages, output.call_id, pendingReasoning);
691
+ pendingReasoning.length = 0;
692
+ const toolInfo = findToolById(messages, output.call_id);
693
+ messages.push({
694
+ role: "toolResult", toolCallId: output.call_id,
695
+ toolName: toolInfo.name, toolNamespace: toolInfo.namespace,
696
+ content: outputToToolResultContent(output.output), isError: false, timestamp: now,
697
+ ...(toolOutputContainsEncryptedContent(output.output) ? { containsEncryptedContent: true } : {}),
698
+ });
699
+ continue;
700
+ }
701
+
702
+ if (effectiveType === "custom_tool_call_output") {
703
+ const output = item as { call_id: string; output: string | unknown[] };
704
+ attachPendingReasoningToCallOwner(messages, output.call_id, pendingReasoning);
705
+ pendingReasoning.length = 0;
706
+ const toolInfo = findToolById(messages, output.call_id);
707
+ messages.push({
708
+ role: "toolResult", toolCallId: output.call_id,
709
+ toolName: toolInfo.name, toolNamespace: toolInfo.namespace,
710
+ // Same payload shape as function_call_output (codex-rs FunctionCallOutputPayload):
711
+ // string or content items — normalize arrays instead of leaking raw wire blocks.
712
+ content: outputToToolResultContent(output.output), isError: false, timestamp: now,
713
+ ...(toolOutputContainsEncryptedContent(output.output) ? { containsEncryptedContent: true } : {}),
714
+ });
715
+ }
716
+ }
717
+ }
718
+ if (data.previous_response_id && continuationConversationMessageIndex === undefined) {
719
+ continuationConversationMessageIndex = messages.length;
720
+ }
721
+
722
+ const declaredTools = buildTools(data.tools as unknown[] | undefined) ?? [];
723
+ const loadedTools = buildTools(loadedToolSpecs) ?? [];
724
+ const loadedToolNames = new Set(loadedTools.map(t => namespacedToolName(t.namespace, t.name)));
725
+ const wireOwners = new Map<string, OcxTool>();
726
+ for (const tool of [...declaredTools, ...loadedTools]) {
727
+ const wireName = namespacedToolName(tool.namespace, tool.name);
728
+ const previous = wireOwners.get(wireName);
729
+ if (previous && (previous.namespace !== tool.namespace || previous.name !== tool.name || previous.freeform !== tool.freeform || previous.toolSearch !== tool.toolSearch)) {
730
+ throw new Error(`ambiguous tool catalog: multiple logical tools map to wire name ${wireName}`);
731
+ }
732
+ wireOwners.set(wireName, tool);
733
+ }
734
+ const seenTools = new Set<string>();
735
+ const mergedTools = [...declaredTools, ...loadedTools]
736
+ .filter(t => {
737
+ const k = namespacedToolName(t.namespace, t.name);
738
+ if (seenTools.has(k)) return false;
739
+ seenTools.add(k);
740
+ return true;
741
+ })
742
+ .map(t => loadedToolNames.has(namespacedToolName(t.namespace, t.name))
743
+ ? { ...t, loadedFromToolSearch: true }
744
+ : t);
745
+ const context: OcxContext = {
746
+ ...(systemPrompt.length > 0 ? { systemPrompt } : {}),
747
+ messages,
748
+ ...(mergedTools.length > 0 ? { tools: mergedTools } : {}),
749
+ };
750
+
751
+ const options: OcxRequestOptions = {};
752
+ if (data.max_output_tokens !== undefined) options.maxOutputTokens = data.max_output_tokens;
753
+ if (data.temperature !== undefined) options.temperature = data.temperature;
754
+ if (data.top_p !== undefined) options.topP = data.top_p;
755
+ if (data.stop !== undefined && data.stop !== null) {
756
+ options.stopSequences = typeof data.stop === "string" ? [data.stop] : data.stop;
757
+ }
758
+ const tc = mapToolChoice(data.tool_choice);
759
+ if (tc && typeof tc === "object") {
760
+ const selectors = "allowedTools" in tc ? tc.allowedTools : [tc.name];
761
+ for (const selector of selectors) {
762
+ if (toolChoiceCandidates(mergedTools, selector).length > 1) {
763
+ throw new Error(`ambiguous tool_choice name: ${selector}`);
764
+ }
765
+ }
766
+ }
767
+ if (tc !== undefined) options.toolChoice = tc;
768
+ if (data.parallel_tool_calls !== undefined) options.parallelToolCalls = data.parallel_tool_calls;
769
+ // Upstream codex-rs converts "ultra" to "max" at the inference boundary (core/src/client.rs
770
+ // `reasoning_effort_for_request`), so current clients never send it — but a catalog that
771
+ // advertises ultra plus an older/direct caller can. Degrade it to max like upstream instead of
772
+ // silently dropping reasoning altogether.
773
+ const requestedEffort = data.reasoning?.effort === "ultra" ? "max" : data.reasoning?.effort;
774
+ if (requestedEffort && REASONING_EFFORTS.has(requestedEffort)) {
775
+ options.reasoning = requestedEffort;
776
+ }
777
+ const summaryMode = data.reasoning?.summary;
778
+ if (!summaryMode || summaryMode === "none") options.hideThinkingSummary = true;
779
+ if (data.presence_penalty !== undefined) options.presencePenalty = data.presence_penalty;
780
+ if (data.frequency_penalty !== undefined) options.frequencyPenalty = data.frequency_penalty;
781
+ if (data.service_tier !== undefined) options.serviceTier = data.service_tier;
782
+ if (data.prompt_cache_key !== undefined) options.promptCacheKey = data.prompt_cache_key;
783
+
784
+ // Stash the hosted web_search config (if Codex enabled it) so the proxy can run searches via the
785
+ // gpt-mini sidecar for routed providers. buildTools still drops the hosted tool; the sidecar path
786
+ // re-injects a synthetic function tool only when it will actually handle the call.
787
+ const webSearch = extractHostedWebSearch(data.tools as unknown[] | undefined);
788
+ const imageGen = extractHostedImageGeneration([
789
+ ...(data.tools as unknown[] ?? []),
790
+ ...loadedToolSpecs,
791
+ ]);
792
+ // Capture structured-output mode (Responses `text.format`): the format object rides
793
+ // options.textFormat for adapters whose wire has an equivalent (openai-chat response_format),
794
+ // while the `_structuredOutput` flag keeps the web-search sidecar rendering its tool_result
795
+ // as JSON rather than prose that could corrupt the model's schema-constrained answer.
796
+ const textFormat = parseTextFormat(data.text);
797
+ if (textFormat) options.textFormat = textFormat;
798
+
799
+ return {
800
+ modelId: data.model,
801
+ ...(data.previous_response_id ? { previousResponseId: data.previous_response_id } : {}),
802
+ context,
803
+ stream: data.stream === true,
804
+ options,
805
+ _rawBody: body,
806
+ ...(replayedInputPrefixLength > 0 ? { _replayPrefixLen: replayedInputPrefixLength } : {}),
807
+ ...(continuationConversationMessageIndex !== undefined
808
+ ? { _continuationConversationMessageIndex: continuationConversationMessageIndex }
809
+ : {}),
810
+ ...(webSearch ? { _webSearch: webSearch } : {}),
811
+ ...(imageGen ? { _imageGeneration: imageGen } : {}),
812
+ ...(textFormat ? { _structuredOutput: true } : {}),
813
+ ...(compactionRequest ? { _compactionRequest: true } : {}),
814
+ ...(contextCompactionBoundary ? { _contextCompactionBoundary: true } : {}),
815
+ };
816
+ }
817
+
818
+ /**
819
+ * The Responses `text.format` object when it requests structured output (json_schema or
820
+ * json_object), undefined otherwise. Acceptance is identical to the boolean detector this
821
+ * replaces; unknown or malformed formats are ignored, never rejected, so the native
822
+ * passthrough keeps forwarding whatever the caller sent via `_rawBody`.
823
+ */
824
+ function parseTextFormat(text: unknown): OcxRequestOptions["textFormat"] {
825
+ if (!isObj(text)) return undefined;
826
+ const format = (text as { format?: unknown }).format;
827
+ if (!isObj(format)) return undefined;
828
+ const f = format as { type?: unknown; name?: unknown; description?: unknown; schema?: unknown; strict?: unknown };
829
+ if (f.type === "json_object") return { type: "json_object" };
830
+ if (f.type !== "json_schema") return undefined;
831
+ return {
832
+ type: "json_schema",
833
+ ...(typeof f.name === "string" ? { name: f.name } : {}),
834
+ ...(typeof f.description === "string" ? { description: f.description } : {}),
835
+ ...(isObj(f.schema) ? { schema: f.schema as Record<string, unknown> } : {}),
836
+ ...(typeof f.strict === "boolean" ? { strict: f.strict } : {}),
837
+ };
838
+ }