@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,482 @@
1
+ import { randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
2
+ import {
3
+ chmodSync,
4
+ closeSync,
5
+ fsyncSync,
6
+ linkSync,
7
+ lstatSync,
8
+ mkdirSync,
9
+ openSync,
10
+ readFileSync,
11
+ unlinkSync,
12
+ writeFileSync,
13
+ } from "node:fs";
14
+ import { dirname, join } from "node:path";
15
+ import { adminApiTokenFilePath } from "../lib/admin-secrets";
16
+ import {
17
+ LOCAL_MANAGEMENT_CAPABILITY_HEADER,
18
+ LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER,
19
+ LOCAL_MANAGEMENT_EXPECTED_PID_HEADER,
20
+ LOCAL_MANAGEMENT_NONCE_HEADER,
21
+ parseExpectedLocalManagementPid,
22
+ verifyLocalManagementReadCapability,
23
+ } from "../lib/local-management-capability";
24
+ import {
25
+ SYSTEM_RESTART_CAPABILITY_HEADER,
26
+ SYSTEM_RESTART_EXPECTED_PID_HEADER,
27
+ SYSTEM_RESTART_NONCE_HEADER,
28
+ SYSTEM_RESTART_PATH,
29
+ parseExpectedSystemRestartPid,
30
+ verifySystemRestartCapability,
31
+ } from "../lib/system-restart-contract";
32
+ import {
33
+ LOCAL_PROVIDER_RELOAD_CAPABILITY_HEADER,
34
+ LOCAL_PROVIDER_RELOAD_EXPECTED_PID_HEADER,
35
+ LOCAL_PROVIDER_RELOAD_EXPIRES_AT_HEADER,
36
+ LOCAL_PROVIDER_RELOAD_NAME_HEADER,
37
+ LOCAL_PROVIDER_RELOAD_NONCE_HEADER,
38
+ LOCAL_PROVIDER_RELOAD_PATH,
39
+ parseExpectedLocalProviderReloadPid,
40
+ verifyLocalProviderReloadCapability,
41
+ } from "../lib/local-provider-reload-contract";
42
+ import { forgetEphemeralSecretPath, forgetHardenedSecretPath, hardenSecretDir, hardenSecretPath } from "../lib/windows-secret-acl";
43
+ import type { OcxConfig } from "../types";
44
+ import {
45
+ isAllowedManagementOrigin,
46
+ isApiAuthRequired,
47
+ isDataPlaneAdmissionSecret,
48
+ isLoopbackHostname,
49
+ managementRequestOrigin,
50
+ parseHttpHost,
51
+ } from "./auth-cors";
52
+
53
+ const GUI_SESSION_TTL_MS = 5 * 60_000;
54
+ const GUI_SESSION_LIMIT = 128;
55
+ const LOCAL_READ_REPLAY_LIMIT = 256;
56
+ const consumedLocalReadCapabilities = new Map<string, number>();
57
+ const admittedLocalReadRequests = new WeakSet<Request>();
58
+ const LOCAL_PROVIDER_RELOAD_REPLAY_LIMIT = 256;
59
+ const consumedLocalProviderReloadCapabilities = new Map<string, number>();
60
+ const admittedLocalProviderReloadRequests = new WeakSet<Request>();
61
+
62
+ interface GuiSessionRecord {
63
+ csrfToken: string;
64
+ origin: string;
65
+ expiresAt: number;
66
+ }
67
+
68
+ export interface GuiSessionBootstrap extends GuiSessionRecord {
69
+ token: string;
70
+ }
71
+
72
+ export type ManagementAuthState =
73
+ | {
74
+ available: true;
75
+ token: string;
76
+ source: "environment" | "file";
77
+ sessions: Map<string, GuiSessionRecord>;
78
+ }
79
+ | { available: false; reason: string };
80
+
81
+ function fail(reason: string): ManagementAuthState {
82
+ return { available: false, reason };
83
+ }
84
+
85
+ function assertSafeDirectory(path: string): void {
86
+ mkdirSync(path, { recursive: true, mode: 0o700 });
87
+ const stat = lstatSync(path);
88
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error("management token directory is not a regular directory");
89
+ chmodSync(path, 0o700);
90
+ let hardened: { ok: boolean };
91
+ try {
92
+ hardened = hardenSecretDir(path, { required: true });
93
+ } catch {
94
+ // required:true hardening now fails closed on genuine ACL timeouts too;
95
+ // keep the actionable guidance in the surfaced reason.
96
+ hardened = { ok: false };
97
+ }
98
+ if (!hardened.ok) {
99
+ throw new Error(
100
+ "management token directory ACL hardening did not complete; set OPENCODEX_ADMIN_AUTH_TOKEN to use an environment token instead of a file-backed token",
101
+ );
102
+ }
103
+ }
104
+
105
+ function readExistingToken(path: string): string {
106
+ const stat = lstatSync(path);
107
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 512) {
108
+ throw new Error("management token path is not a regular secret file");
109
+ }
110
+ chmodSync(path, 0o600);
111
+ let hardened: { ok: boolean };
112
+ try {
113
+ hardened = hardenSecretPath(path, { required: true });
114
+ } catch {
115
+ hardened = { ok: false };
116
+ }
117
+ if (!hardened.ok) {
118
+ throw new Error(
119
+ "management token file ACL hardening did not complete; set OPENCODEX_ADMIN_AUTH_TOKEN to use an environment token instead of a file-backed token",
120
+ );
121
+ }
122
+ const token = readFileSync(path, "utf8").trim();
123
+ if (!/^ocx_admin_[A-Za-z0-9_-]{43}$/.test(token)) throw new Error("management token file is invalid");
124
+ return token;
125
+ }
126
+
127
+ export function removeManagementTokenPathBestEffort(
128
+ path: string,
129
+ remove: (path: string) => void = unlinkSync,
130
+ options?: { ephemeral?: boolean },
131
+ ): void {
132
+ // Temps get the full ephemeral release (success + both timeout namespaces);
133
+ // stable token paths drop only the success memo — destination-keyed timeout
134
+ // memos are intentional anti-restall state.
135
+ const forget = options?.ephemeral ? forgetEphemeralSecretPath : forgetHardenedSecretPath;
136
+ try {
137
+ remove(path);
138
+ forget(path);
139
+ } catch (error) {
140
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") forget(path);
141
+ /* other failures retain fail-closed state for the caller */
142
+ }
143
+ }
144
+
145
+ function createTokenFile(path: string): string {
146
+ const directory = dirname(path);
147
+ const token = `ocx_admin_${randomBytes(32).toString("base64url")}`;
148
+ const temporary = join(directory, `.${randomUUID()}.admin-token.tmp`);
149
+ let linked = false;
150
+ let fd: number | null = null;
151
+ try {
152
+ fd = openSync(temporary, "wx", 0o600);
153
+ writeFileSync(fd, `${token}\n`, "utf8");
154
+ fsyncSync(fd);
155
+ closeSync(fd);
156
+ fd = null;
157
+ chmodSync(temporary, 0o600);
158
+ let temporaryHardened: { ok: boolean };
159
+ try {
160
+ // Destination-keyed timeout memo (the final token path), not the temp.
161
+ temporaryHardened = hardenSecretPath(temporary, { required: true, timeoutMemoKey: path });
162
+ } catch {
163
+ temporaryHardened = { ok: false };
164
+ }
165
+ if (!temporaryHardened.ok) {
166
+ throw new Error(
167
+ "management token temporary ACL hardening did not complete; set OPENCODEX_ADMIN_AUTH_TOKEN to use an environment token instead of a file-backed token",
168
+ );
169
+ }
170
+ try {
171
+ linkSync(temporary, path);
172
+ linked = true;
173
+ } catch (error) {
174
+ if ((error as NodeJS.ErrnoException).code === "EEXIST") return readExistingToken(path);
175
+ throw error;
176
+ }
177
+ let finalHardened: { ok: boolean };
178
+ try {
179
+ finalHardened = hardenSecretPath(path, { required: true });
180
+ } catch {
181
+ finalHardened = { ok: false };
182
+ }
183
+ if (!finalHardened.ok) {
184
+ throw new Error(
185
+ "management token file ACL hardening did not complete; set OPENCODEX_ADMIN_AUTH_TOKEN to use an environment token instead of a file-backed token",
186
+ );
187
+ }
188
+ return token;
189
+ } catch (error) {
190
+ if (linked) removeManagementTokenPathBestEffort(path);
191
+ throw error;
192
+ } finally {
193
+ if (fd !== null) {
194
+ try { closeSync(fd); } catch { /* best effort */ }
195
+ }
196
+ removeManagementTokenPathBestEffort(temporary, unlinkSync, { ephemeral: true });
197
+ }
198
+ }
199
+
200
+ function ready(token: string, source: "environment" | "file", config: OcxConfig): ManagementAuthState {
201
+ if (isDataPlaneAdmissionSecret(token, config)) {
202
+ return fail("management credential conflicts with a data-plane credential");
203
+ }
204
+ return { available: true, token, source, sessions: new Map() };
205
+ }
206
+
207
+ export function initializeManagementAuthState(config: OcxConfig): ManagementAuthState {
208
+ const environmentToken = process.env.OPENCODEX_ADMIN_AUTH_TOKEN?.trim();
209
+ if (environmentToken) {
210
+ return ready(environmentToken, "environment", config);
211
+ }
212
+ try {
213
+ const path = adminApiTokenFilePath();
214
+ assertSafeDirectory(dirname(path));
215
+ let token: string;
216
+ try {
217
+ token = readExistingToken(path);
218
+ } catch (error) {
219
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
220
+ token = createTokenFile(path);
221
+ }
222
+ return ready(token, "file", config);
223
+ } catch (error) {
224
+ return fail(error instanceof Error ? error.message : "management token initialization failed");
225
+ }
226
+ }
227
+
228
+ function equalSecret(actual: string, expected: string): boolean {
229
+ const encoder = new TextEncoder();
230
+ const left = encoder.encode(actual);
231
+ const right = encoder.encode(expected);
232
+ return left.length === right.length && timingSafeEqual(left, right);
233
+ }
234
+
235
+ function removeExpiredSessions(state: Extract<ManagementAuthState, { available: true }>, now = Date.now()): void {
236
+ for (const [token, session] of state.sessions) {
237
+ if (session.expiresAt <= now) state.sessions.delete(token);
238
+ }
239
+ }
240
+
241
+ function randomSessionSecret(prefix: "ocx_session_"): string {
242
+ return `${prefix}${randomBytes(32).toString("base64url")}`;
243
+ }
244
+
245
+ export function issueGuiSession(
246
+ req: Request,
247
+ config: OcxConfig,
248
+ state: ManagementAuthState,
249
+ ): GuiSessionBootstrap | null {
250
+ if (isApiAuthRequired(config) || !state.available || req.method !== "GET" || !isAllowedManagementOrigin(req, config)) return null;
251
+ const host = parseHttpHost(req.headers.get("Host"));
252
+ if (!host || !isLoopbackHostname(host.hostname)) return null;
253
+ const origin = managementRequestOrigin(req, config);
254
+ if (!origin) return null;
255
+ const now = Date.now();
256
+ removeExpiredSessions(state, now);
257
+ while (state.sessions.size >= GUI_SESSION_LIMIT) {
258
+ const oldest = state.sessions.keys().next().value as string | undefined;
259
+ if (!oldest) break;
260
+ state.sessions.delete(oldest);
261
+ }
262
+ const token = randomSessionSecret("ocx_session_");
263
+ const session: GuiSessionRecord = {
264
+ csrfToken: randomBytes(32).toString("base64url"),
265
+ origin,
266
+ expiresAt: now + GUI_SESSION_TTL_MS,
267
+ };
268
+ state.sessions.set(token, session);
269
+ return { token, ...session };
270
+ }
271
+
272
+ /**
273
+ * Which credential actually authorized a management request.
274
+ *
275
+ * `admin-token` is the raw token from disk/env: anything running as the user can
276
+ * read it, including a coding agent. `gui-session` is a session token this process
277
+ * minted for a browser, and it only authorizes a mutation after the origin and the
278
+ * per-session CSRF token match. Consent-bearing routes must key off this value
279
+ * rather than off request headers, which the token holder can forge freely.
280
+ * The capability principals are process-scoped HMACs bound to the current process
281
+ * PID and listening port. Local reads are accepted only for two exact GET paths;
282
+ * restart and provider reload remain separate wire contracts for their exact POSTs.
283
+ */
284
+ export type ManagementPrincipal =
285
+ | "admin-token"
286
+ | "gui-session"
287
+ | "local-read-capability"
288
+ | "local-provider-reload-capability"
289
+ | "system-restart-capability";
290
+
291
+ export interface LocalManagementAuthContext {
292
+ attestationSecret: string;
293
+ pid: number;
294
+ port: number;
295
+ }
296
+
297
+ function hasSystemRestartCapability(
298
+ req: Request,
299
+ local: LocalManagementAuthContext | undefined,
300
+ ): boolean {
301
+ if (!local || req.method !== "POST") return false;
302
+ let path: string;
303
+ try {
304
+ path = new URL(req.url).pathname;
305
+ } catch {
306
+ return false;
307
+ }
308
+ if (path !== SYSTEM_RESTART_PATH) return false;
309
+ const expectedPid = parseExpectedSystemRestartPid(
310
+ req.headers.get(SYSTEM_RESTART_EXPECTED_PID_HEADER),
311
+ );
312
+ if (expectedPid.kind !== "present" || expectedPid.pid !== local.pid) return false;
313
+ return verifySystemRestartCapability(
314
+ local.attestationSecret,
315
+ req.headers.get(SYSTEM_RESTART_NONCE_HEADER),
316
+ req.method,
317
+ path,
318
+ local.pid,
319
+ local.port,
320
+ req.headers.get(SYSTEM_RESTART_CAPABILITY_HEADER),
321
+ );
322
+ }
323
+
324
+ function hasLocalReadCapability(
325
+ req: Request,
326
+ local: LocalManagementAuthContext | undefined,
327
+ ): boolean {
328
+ // requireManagementAuth and managementPrincipal inspect the same Request in
329
+ // sequence. Preserve that one admission without accepting a replayed request.
330
+ if (admittedLocalReadRequests.has(req)) return true;
331
+ if (!local || req.method !== "GET") return false;
332
+ let url: URL;
333
+ try {
334
+ url = new URL(req.url);
335
+ } catch {
336
+ return false;
337
+ }
338
+ // Do not let a future query-bearing variant silently inherit this narrow grant.
339
+ if (url.search !== "") return false;
340
+ const expectedPid = parseExpectedLocalManagementPid(
341
+ req.headers.get(LOCAL_MANAGEMENT_EXPECTED_PID_HEADER),
342
+ );
343
+ if (expectedPid.kind !== "present" || expectedPid.pid !== local.pid) return false;
344
+ const expiresAtRaw = req.headers.get(LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER);
345
+ if (!expiresAtRaw || !/^[1-9]\d*$/.test(expiresAtRaw)) return false;
346
+ const expiresAt = Number(expiresAtRaw);
347
+ if (!Number.isSafeInteger(expiresAt)) return false;
348
+ const capability = req.headers.get(LOCAL_MANAGEMENT_CAPABILITY_HEADER);
349
+ const now = Date.now();
350
+ if (!verifyLocalManagementReadCapability(
351
+ local.attestationSecret,
352
+ req.headers.get(LOCAL_MANAGEMENT_NONCE_HEADER),
353
+ req.method,
354
+ url.pathname,
355
+ local.pid,
356
+ local.port,
357
+ expiresAt,
358
+ capability,
359
+ now,
360
+ )) return false;
361
+ for (const [consumed, retainedUntil] of consumedLocalReadCapabilities) {
362
+ if (retainedUntil <= now) consumedLocalReadCapabilities.delete(consumed);
363
+ }
364
+ if (!capability || consumedLocalReadCapabilities.has(capability)) return false;
365
+ if (consumedLocalReadCapabilities.size >= LOCAL_READ_REPLAY_LIMIT) return false;
366
+ consumedLocalReadCapabilities.set(capability, expiresAt);
367
+ admittedLocalReadRequests.add(req);
368
+ return true;
369
+ }
370
+
371
+ function hasLocalProviderReloadCapability(
372
+ req: Request,
373
+ local: LocalManagementAuthContext | undefined,
374
+ ): boolean {
375
+ if (admittedLocalProviderReloadRequests.has(req)) return true;
376
+ if (!local || req.method !== "POST") return false;
377
+ let url: URL;
378
+ try {
379
+ url = new URL(req.url);
380
+ } catch {
381
+ return false;
382
+ }
383
+ if (url.pathname !== LOCAL_PROVIDER_RELOAD_PATH || url.search !== "") return false;
384
+ const contentLength = req.headers.get("content-length");
385
+ if (contentLength !== "0" || req.headers.has("transfer-encoding")) return false;
386
+ const expectedPid = parseExpectedLocalProviderReloadPid(
387
+ req.headers.get(LOCAL_PROVIDER_RELOAD_EXPECTED_PID_HEADER),
388
+ );
389
+ if (expectedPid.kind !== "present" || expectedPid.pid !== local.pid) return false;
390
+ const expiresAtRaw = req.headers.get(LOCAL_PROVIDER_RELOAD_EXPIRES_AT_HEADER);
391
+ if (!expiresAtRaw || !/^[1-9]\d*$/.test(expiresAtRaw)) return false;
392
+ const expiresAt = Number(expiresAtRaw);
393
+ if (!Number.isSafeInteger(expiresAt)) return false;
394
+ const name = req.headers.get(LOCAL_PROVIDER_RELOAD_NAME_HEADER);
395
+ const capability = req.headers.get(LOCAL_PROVIDER_RELOAD_CAPABILITY_HEADER);
396
+ const now = Date.now();
397
+ if (!verifyLocalProviderReloadCapability(
398
+ local.attestationSecret,
399
+ req.headers.get(LOCAL_PROVIDER_RELOAD_NONCE_HEADER),
400
+ req.method,
401
+ url.pathname,
402
+ name,
403
+ local.pid,
404
+ local.port,
405
+ expiresAt,
406
+ capability,
407
+ now,
408
+ )) return false;
409
+ for (const [consumed, retainedUntil] of consumedLocalProviderReloadCapabilities) {
410
+ if (retainedUntil <= now) consumedLocalProviderReloadCapabilities.delete(consumed);
411
+ }
412
+ if (!capability || consumedLocalProviderReloadCapabilities.has(capability)) return false;
413
+ if (consumedLocalProviderReloadCapabilities.size >= LOCAL_PROVIDER_RELOAD_REPLAY_LIMIT) return false;
414
+ consumedLocalProviderReloadCapabilities.set(capability, expiresAt);
415
+ admittedLocalProviderReloadRequests.add(req);
416
+ return true;
417
+ }
418
+
419
+ /**
420
+ * The principal for a request that already passed `requireManagementAuth`. Kept as a
421
+ * separate resolution (rather than a changed return type) so every existing caller
422
+ * keeps its `Response | null` contract. Browser and admin principals are derived
423
+ * from the same session table and CSRF comparison the gate uses; the restart
424
+ * principal is derived from the same process-scoped capability check.
425
+ */
426
+ export function managementPrincipal(
427
+ req: Request,
428
+ state: ManagementAuthState,
429
+ config?: OcxConfig,
430
+ local?: LocalManagementAuthContext,
431
+ ): ManagementPrincipal | null {
432
+ if (hasSystemRestartCapability(req, local)) return "system-restart-capability";
433
+ if (hasLocalProviderReloadCapability(req, local)) return "local-provider-reload-capability";
434
+ if (hasLocalReadCapability(req, local)) return "local-read-capability";
435
+ if (!state.available) return null;
436
+ const actual = req.headers.get("x-opencodex-api-key")?.trim()
437
+ || req.headers.get("authorization")?.replace(/^Bearer\s+/i, "").trim();
438
+ if (!actual) return null;
439
+ if (equalSecret(actual, state.token)) return "admin-token";
440
+ if (!config) return null;
441
+ removeExpiredSessions(state);
442
+ return state.sessions.has(actual) ? "gui-session" : null;
443
+ }
444
+
445
+ export function requireManagementAuth(
446
+ req: Request,
447
+ state: ManagementAuthState,
448
+ config?: OcxConfig,
449
+ local?: LocalManagementAuthContext,
450
+ ): Response | null {
451
+ if (hasSystemRestartCapability(req, local)) return null;
452
+ if (hasLocalProviderReloadCapability(req, local)) return null;
453
+ if (hasLocalReadCapability(req, local)) return null;
454
+ if (!state.available) {
455
+ return Response.json({
456
+ error: "management API unavailable",
457
+ reason: state.reason,
458
+ hint: "Set OPENCODEX_ADMIN_AUTH_TOKEN to bypass file-backed admin token ACL hardening",
459
+ }, { status: 503 });
460
+ }
461
+ const actual = req.headers.get("x-opencodex-api-key")?.trim()
462
+ || req.headers.get("authorization")?.replace(/^Bearer\s+/i, "").trim();
463
+ if (actual && equalSecret(actual, state.token)) return null;
464
+ if (actual && config) {
465
+ removeExpiredSessions(state);
466
+ const session = state.sessions.get(actual);
467
+ if (session) {
468
+ const requestOrigin = managementRequestOrigin(req, config);
469
+ const claimedOrigin = req.headers.get("x-opencodex-gui-origin");
470
+ const browserOrigin = req.headers.get("Origin");
471
+ const sameOrigin = requestOrigin === session.origin
472
+ && claimedOrigin === session.origin
473
+ && (!browserOrigin || browserOrigin === session.origin);
474
+ const safeMethod = req.method === "GET" || req.method === "HEAD";
475
+ const csrf = req.headers.get("x-opencodex-csrf-token")?.trim();
476
+ if (sameOrigin && (safeMethod || (browserOrigin === session.origin && !!csrf && equalSecret(csrf, session.csrfToken)))) {
477
+ return null;
478
+ }
479
+ }
480
+ }
481
+ return Response.json({ error: "opencodex admin token required" }, { status: 401 });
482
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Memory watchdog (#314 WP3 / #509) — warn-only observability for the Windows
3
+ * native-memory growth reported upstream (Bun fetch buffers / socket handles).
4
+ *
5
+ * Samples process.memoryUsage() on an unref'd interval into a bounded ring and
6
+ * logs ONE rate-limited warning when observed memory crosses the threshold. It never
7
+ * restarts anything (threshold auto-restart is deliberately deferred; the
8
+ * service managers' crash-respawn already covers hard failures). The active
9
+ * instance is a module-level singleton so the management API can expose the
10
+ * snapshot without threading server state through route contexts.
11
+ *
12
+ * Privacy: samples are scalar numbers only; the warn line never interpolates
13
+ * paths, hostnames, or tokens.
14
+ */
15
+
16
+ export type MemorySampleBase = {
17
+ /** Epoch ms. */
18
+ at: number;
19
+ /** Resident set size in bytes. */
20
+ rss: number;
21
+ /** JS heap used in bytes (process.memoryUsage().heapUsed). */
22
+ heapUsed: number;
23
+ /** JS heap total in bytes. */
24
+ heapTotal: number;
25
+ /** External/native memory tracked by process.memoryUsage(). */
26
+ external: number;
27
+ /** ArrayBuffer memory tracked by process.memoryUsage(). */
28
+ arrayBuffers: number;
29
+ };
30
+
31
+ export type MemorySample = MemorySampleBase & {
32
+ /** Largest observed memory counter used for thresholding. */
33
+ observedBytes: number;
34
+ /** Counter that produced observedBytes. */
35
+ observedMetric: MemoryMetric;
36
+ };
37
+
38
+ export type MemoryMetric = "rss" | "external" | "arrayBuffers";
39
+
40
+ export type MemoryWatchdogState = {
41
+ samples: MemorySample[];
42
+ warnThresholdBytes: number;
43
+ lastWarnAt: number | null;
44
+ observedBytes: number;
45
+ observedMetric: MemoryMetric;
46
+ };
47
+
48
+ export type MemoryWatchdog = {
49
+ stop(): void;
50
+ snapshot(): MemoryWatchdogState;
51
+ };
52
+
53
+ const DEFAULT_INTERVAL_MS = 60_000;
54
+ const DEFAULT_WARN_THRESHOLD_BYTES = 4 * 1024 ** 3; // 4 GiB
55
+ const DEFAULT_RING_SIZE = 360; // ≈6h at 60s
56
+ const WARN_INTERVAL_MS = 30 * 60_000;
57
+ const DOCS_URL = "https://opencodex.me/troubleshooting/windows-memory/";
58
+
59
+ let active: MemoryWatchdog | null = null;
60
+
61
+ export function observedMemoryCounter(sample: Pick<MemorySampleBase, "rss" | "external" | "arrayBuffers">): {
62
+ observedBytes: number;
63
+ observedMetric: MemoryMetric;
64
+ } {
65
+ const values: Array<{ metric: MemoryMetric; bytes: number }> = [
66
+ { metric: "rss", bytes: sample.rss },
67
+ { metric: "external", bytes: sample.external },
68
+ { metric: "arrayBuffers", bytes: sample.arrayBuffers },
69
+ ];
70
+ const best = values.reduce((current, next) => next.bytes > current.bytes ? next : current, values[0]);
71
+ return { observedBytes: best.bytes, observedMetric: best.metric };
72
+ }
73
+
74
+ /** The running watchdog, if any — read by /api/system/memory. */
75
+ export function getActiveMemoryWatchdog(): MemoryWatchdog | null {
76
+ return active;
77
+ }
78
+
79
+ function defaultSample(now: () => number): MemorySample {
80
+ const usage = process.memoryUsage();
81
+ const base = {
82
+ at: now(),
83
+ rss: usage.rss,
84
+ heapUsed: usage.heapUsed,
85
+ heapTotal: usage.heapTotal,
86
+ external: usage.external,
87
+ arrayBuffers: usage.arrayBuffers,
88
+ };
89
+ return { ...base, ...observedMemoryCounter(base) };
90
+ }
91
+
92
+ function normalizeSample(sample: MemorySampleBase): MemorySample {
93
+ return { ...sample, ...observedMemoryCounter(sample) };
94
+ }
95
+
96
+ /**
97
+ * Start (or replace) the process-wide memory watchdog. Idempotent: a previous
98
+ * active instance is stopped first, so repeated startServer() calls in tests
99
+ * never accumulate intervals. The timer is unref'd; stop() is exposed for
100
+ * tests and clears the singleton.
101
+ */
102
+ export function startMemoryWatchdog(opts?: {
103
+ intervalMs?: number;
104
+ warnThresholdBytes?: number;
105
+ ringSize?: number;
106
+ now?: () => number;
107
+ sample?: () => MemorySampleBase;
108
+ warn?: (msg: string) => void;
109
+ }): MemoryWatchdog {
110
+ active?.stop();
111
+ const intervalMs = opts?.intervalMs ?? DEFAULT_INTERVAL_MS;
112
+ const warnThresholdBytes = opts?.warnThresholdBytes ?? DEFAULT_WARN_THRESHOLD_BYTES;
113
+ const ringSize = opts?.ringSize ?? DEFAULT_RING_SIZE;
114
+ const now = opts?.now ?? Date.now;
115
+ const sample = opts?.sample ?? (() => defaultSample(now));
116
+ const warn = opts?.warn ?? ((msg: string) => console.warn(msg));
117
+
118
+ const samples: MemorySample[] = [];
119
+ let lastWarnAt: number | null = null;
120
+ let observedBytes = 0;
121
+ let observedMetric: MemoryMetric = "rss";
122
+
123
+ const tick = () => {
124
+ let s: MemorySample;
125
+ try {
126
+ s = normalizeSample(sample());
127
+ } catch {
128
+ return; // sampling must never break the server
129
+ }
130
+ samples.push(s);
131
+ if (samples.length > ringSize) samples.splice(0, samples.length - ringSize);
132
+ observedBytes = s.observedBytes;
133
+ observedMetric = s.observedMetric;
134
+ if (s.observedBytes >= warnThresholdBytes && (lastWarnAt === null || now() - lastWarnAt >= WARN_INTERVAL_MS)) {
135
+ lastWarnAt = now();
136
+ const observedMb = Math.round(s.observedBytes / (1024 * 1024));
137
+ const thresholdMb = Math.round(warnThresholdBytes / (1024 * 1024));
138
+ warn(`⚠️ opencodex observed memory ${observedMb}MB (${s.observedMetric}) exceeds the ${thresholdMb}MB watch threshold. On Windows this is usually the upstream Bun runtime memory issue — see ${DOCS_URL}`);
139
+ }
140
+ };
141
+
142
+ const timer = setInterval(tick, intervalMs);
143
+ (timer as { unref?: () => void }).unref?.();
144
+
145
+ const instance: MemoryWatchdog = {
146
+ stop() {
147
+ clearInterval(timer);
148
+ if (active === instance) active = null;
149
+ },
150
+ snapshot() {
151
+ return { samples: [...samples], warnThresholdBytes, lastWarnAt, observedBytes, observedMetric };
152
+ },
153
+ };
154
+ active = instance;
155
+ return instance;
156
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Optional per-attempt route-identity linker.
3
+ *
4
+ * Compatibility Lab attaches an opaque route-subject digest to request attempts so its
5
+ * passive-production surface (CL-09) can correlate them later. That is an opt-in
6
+ * subsystem, so the core request path holds only a slot: null on installs that never
7
+ * activate Lab, which is every install without a routing profile.
8
+ *
9
+ * Contract for any registered implementation: synchronous, free of side effects with
10
+ * respect to the request, and non-throwing. The upstream request must never be delayed,
11
+ * retried, or altered by identity linkage. The try/catch lives here rather than at the
12
+ * call site so the guarantee belongs to the mechanism instead of being restated by every
13
+ * caller.
14
+ *
15
+ * See devlog/_fin/260814_lab_core_decoupling/020_request_path_gate.md
16
+ */
17
+ import type { OcxConfig, OcxProviderConfig } from "../types";
18
+ import type { InboundWire } from "../providers/registry";
19
+
20
+ export type PassiveRouteLinker = (
21
+ config: OcxConfig,
22
+ providerName: string,
23
+ modelId: string,
24
+ routed: OcxProviderConfig,
25
+ inboundWire: InboundWire,
26
+ ) => string | null;
27
+
28
+ let linker: PassiveRouteLinker | null = null;
29
+
30
+ /** Install the linker. Returns a detach function. */
31
+ export function setPassiveRouteLinker(next: PassiveRouteLinker): () => void {
32
+ linker = next;
33
+ return () => {
34
+ // Only detach our own registration: a later activation may have replaced it.
35
+ if (linker === next) linker = null;
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Resolve the attempt identity, or null when no subsystem is active.
41
+ * Never throws: linkage is best-effort metadata and must not affect the request.
42
+ */
43
+ export function resolvePassiveRouteSubjectId(
44
+ config: OcxConfig,
45
+ providerName: string,
46
+ modelId: string,
47
+ routed: OcxProviderConfig,
48
+ inboundWire: InboundWire,
49
+ ): string | null {
50
+ if (!linker) return null;
51
+ try {
52
+ return linker(config, providerName, modelId, routed, inboundWire);
53
+ } catch {
54
+ return null;
55
+ }
56
+ }
57
+
58
+ /** True when an optional subsystem has installed a linker. Test/diagnostic use. */
59
+ export function hasPassiveRouteLinker(): boolean {
60
+ return linker !== null;
61
+ }
62
+
63
+ /** Test-only reset. */
64
+ export function resetPassiveRouteLinkerForTests(): void {
65
+ linker = null;
66
+ }