@iislee/opencodex 2.11.0 → 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 (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,563 @@
1
+ /**
2
+ * CL-04 read-only Compatibility Lab management API.
3
+ *
4
+ * - GET /api/lab/status
5
+ * - GET /api/lab/verdicts
6
+ * - GET /api/lab/subjects
7
+ * - GET /api/lab/subjects/:subjectId
8
+ * - GET /api/lab/observations
9
+ * - GET /api/lab/events
10
+ * - GET /api/lab/events/:eventId
11
+ * - GET /api/lab/artifacts
12
+ * - GET /api/lab/artifacts/:digest
13
+ * - GET /api/lab/catalog
14
+ */
15
+
16
+ import {
17
+ ARTIFACT_CLASSES,
18
+ EVIDENCE_LAYERS,
19
+ EXECUTION_MODES,
20
+ EVENT_KINDS,
21
+ OUTCOMES,
22
+ VERDICTS,
23
+ type EvidenceLayer,
24
+ type ExecutionMode,
25
+ type LabEventKind,
26
+ type ObservationOutcome,
27
+ type CompatibilityVerdict,
28
+ } from "../../lab/constants";
29
+ import {
30
+ InvalidCursorError,
31
+ LabProjectionIncompatibleError,
32
+ LabProjectionUnavailableError,
33
+ LAB_QUERY_MAX_PAGE_SIZE,
34
+ PASSIVE_PRODUCTION_MAX_LIMIT,
35
+ queryLabArtifactByDigest,
36
+ queryLabArtifacts,
37
+ queryLabCatalogEntries,
38
+ queryLabEventById,
39
+ queryLabEvents,
40
+ queryLabObservations,
41
+ queryLabStatus,
42
+ queryLabSubjectById,
43
+ queryLabSubjects,
44
+ queryLabVerdicts,
45
+ queryPassiveProductionSignals,
46
+ } from "../../lab/query";
47
+ import {
48
+ exportLocalPublicEvidence,
49
+ importCommunityEvidenceValue,
50
+ listCommunityEvidenceContext,
51
+ parseStrictPublicJson,
52
+ previewLocalPublicEvidence,
53
+ summarizePublicEvidenceVerification,
54
+ PublicEvidenceValidationError,
55
+ } from "../../lab/public";
56
+ import { jsonResponse } from "../auth-cors";
57
+ import type { ManagementContext } from "./context";
58
+
59
+ function parseQueryInt(raw: string | null): number | undefined | "invalid" {
60
+ if (raw === null) return undefined;
61
+ const trimmed = raw.trim();
62
+ if (trimmed.length === 0) return "invalid";
63
+ const value = Number(trimmed);
64
+ return Number.isInteger(value) ? value : "invalid";
65
+ }
66
+
67
+ function errorResponse(
68
+ code: string,
69
+ message: string,
70
+ status: number,
71
+ ctx: ManagementContext,
72
+ ): Response {
73
+ return jsonResponse({ error: { code, message } }, status, ctx.req, ctx.config);
74
+ }
75
+
76
+ function projectionErrorResponse(err: unknown, ctx: ManagementContext): Response | null {
77
+ if (err instanceof LabProjectionUnavailableError) {
78
+ return errorResponse("lab_projection_unavailable", "lab projection is not available", 503, ctx);
79
+ }
80
+ if (err instanceof LabProjectionIncompatibleError) {
81
+ return errorResponse("lab_projection_incompatible", "lab projection schema or spec version is incompatible", 503, ctx);
82
+ }
83
+ if (err instanceof InvalidCursorError) {
84
+ return errorResponse("invalid_cursor", "invalid cursor", 400, ctx);
85
+ }
86
+ return null;
87
+ }
88
+
89
+ function parseLimit(
90
+ raw: string | null,
91
+ ctx: ManagementContext,
92
+ max = LAB_QUERY_MAX_PAGE_SIZE,
93
+ ): number | undefined | Response {
94
+ const parsed = raw === null ? undefined : parseQueryInt(raw);
95
+ if (parsed === "invalid") {
96
+ return errorResponse(
97
+ "invalid_limit",
98
+ `limit must be an integer from 1 to ${max}`,
99
+ 400,
100
+ ctx,
101
+ );
102
+ }
103
+ if (parsed !== undefined && (parsed < 1 || parsed > max)) {
104
+ return errorResponse(
105
+ "invalid_limit",
106
+ `limit must be an integer from 1 to ${max}`,
107
+ 400,
108
+ ctx,
109
+ );
110
+ }
111
+ return parsed;
112
+ }
113
+
114
+ function parseRange(
115
+ fromRaw: string | null,
116
+ toRaw: string | null,
117
+ ctx: ManagementContext,
118
+ ): { from?: number; to?: number } | Response {
119
+ const fromParsed = parseQueryInt(fromRaw);
120
+ if (fromParsed === "invalid") {
121
+ return errorResponse("invalid_range", "from must be an integer timestamp", 400, ctx);
122
+ }
123
+ const toParsed = parseQueryInt(toRaw);
124
+ if (toParsed === "invalid") {
125
+ return errorResponse("invalid_range", "to must be an integer timestamp", 400, ctx);
126
+ }
127
+ if (fromParsed !== undefined && toParsed !== undefined && fromParsed > toParsed) {
128
+ return errorResponse("invalid_range", "from must not be after to", 400, ctx);
129
+ }
130
+ return { from: fromParsed, to: toParsed };
131
+ }
132
+
133
+ function parseLayer(raw: string | null, ctx: ManagementContext): EvidenceLayer | undefined | Response {
134
+ if (!raw) return undefined;
135
+ const trimmed = raw.trim();
136
+ if (!EVIDENCE_LAYERS.includes(trimmed as EvidenceLayer)) {
137
+ return errorResponse("invalid_layer", "layer must be a supported evidence layer", 400, ctx);
138
+ }
139
+ return trimmed as EvidenceLayer;
140
+ }
141
+
142
+ function parseVerdict(raw: string | null, ctx: ManagementContext): CompatibilityVerdict | undefined | Response {
143
+ if (!raw) return undefined;
144
+ const trimmed = raw.trim();
145
+ if (!VERDICTS.includes(trimmed as CompatibilityVerdict)) {
146
+ return errorResponse("invalid_verdict", "verdict must be a supported compatibility verdict", 400, ctx);
147
+ }
148
+ return trimmed as CompatibilityVerdict;
149
+ }
150
+
151
+ function parseEventKind(raw: string | null, ctx: ManagementContext): LabEventKind | undefined | Response {
152
+ if (!raw) return undefined;
153
+ const trimmed = raw.trim();
154
+ if (!EVENT_KINDS.includes(trimmed as LabEventKind)) {
155
+ return errorResponse("invalid_event_kind", "eventKind must be a supported lab event kind", 400, ctx);
156
+ }
157
+ return trimmed as LabEventKind;
158
+ }
159
+
160
+ function parseOutcome(raw: string | null, ctx: ManagementContext): ObservationOutcome | undefined | Response {
161
+ if (!raw) return undefined;
162
+ const trimmed = raw.trim();
163
+ if (!OUTCOMES.includes(trimmed as ObservationOutcome)) {
164
+ return errorResponse("invalid_outcome", "outcome must be a supported observation outcome", 400, ctx);
165
+ }
166
+ return trimmed as ObservationOutcome;
167
+ }
168
+
169
+ function parseExecutionMode(raw: string | null, ctx: ManagementContext): ExecutionMode | undefined | Response {
170
+ if (!raw) return undefined;
171
+ const trimmed = raw.trim();
172
+ if (!EXECUTION_MODES.includes(trimmed as ExecutionMode)) {
173
+ return errorResponse("invalid_execution_mode", "executionMode must be a supported lab execution mode", 400, ctx);
174
+ }
175
+ return trimmed as ExecutionMode;
176
+ }
177
+
178
+ function rejectUnsafeId(id: string, ctx: ManagementContext): Response | null {
179
+ if (id.includes("/") || id.includes("\\") || id.includes("%2f") || id.includes("%5c")) {
180
+ return errorResponse("not_found", "unknown resource", 404, ctx);
181
+ }
182
+ if (id.length === 0 || id.length > 256) {
183
+ return errorResponse("not_found", "unknown resource", 404, ctx);
184
+ }
185
+ return null;
186
+ }
187
+
188
+ function decodePathSegment(raw: string): string | null {
189
+ try {
190
+ return decodeURIComponent(raw);
191
+ } catch {
192
+ return null;
193
+ }
194
+ }
195
+
196
+ function paginatedEnvelope<T>(page: { items: T[]; nextCursor?: string; hasMore: boolean }, key: string) {
197
+ return {
198
+ [key]: page.items,
199
+ hasMore: page.hasMore,
200
+ ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),
201
+ };
202
+ }
203
+
204
+ const MAX_PUBLIC_REQUEST_BYTES = 2 * 1024 * 1024;
205
+
206
+ async function readBoundedPublicJson(req: Request): Promise<unknown> {
207
+ const lengthRaw = req.headers.get("content-length");
208
+ if (lengthRaw) {
209
+ const length = Number(lengthRaw);
210
+ if (!Number.isFinite(length) || length < 0 || length > MAX_PUBLIC_REQUEST_BYTES) {
211
+ throw new PublicEvidenceValidationError(
212
+ "public_request_too_large",
213
+ "public evidence request exceeds 2 MiB",
214
+ );
215
+ }
216
+ }
217
+ if (!req.body) {
218
+ throw new PublicEvidenceValidationError("public_request_body", "JSON body is required");
219
+ }
220
+ const reader = req.body.getReader();
221
+ const chunks: Uint8Array[] = [];
222
+ let total = 0;
223
+ while (true) {
224
+ const { done, value } = await reader.read();
225
+ if (done) break;
226
+ total += value.byteLength;
227
+ if (total > MAX_PUBLIC_REQUEST_BYTES) {
228
+ await reader.cancel();
229
+ throw new PublicEvidenceValidationError(
230
+ "public_request_too_large",
231
+ "public evidence request exceeds 2 MiB",
232
+ );
233
+ }
234
+ chunks.push(value);
235
+ }
236
+ const bytes = new Uint8Array(total);
237
+ let offset = 0;
238
+ for (const chunk of chunks) {
239
+ bytes.set(chunk, offset);
240
+ offset += chunk.byteLength;
241
+ }
242
+ return parseStrictPublicJson(bytes, "public evidence request");
243
+ }
244
+
245
+ function publicEventIds(raw: unknown): string[] {
246
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
247
+ throw new PublicEvidenceValidationError("public_request_body", "request body must be an object");
248
+ }
249
+ const keys = Object.keys(raw);
250
+ if (keys.length !== 1 || keys[0] !== "eventIds") {
251
+ throw new PublicEvidenceValidationError("public_request_body", "only eventIds is accepted");
252
+ }
253
+ const eventIds = (raw as { eventIds?: unknown }).eventIds;
254
+ if (!Array.isArray(eventIds) || !eventIds.every((value) => typeof value === "string")) {
255
+ throw new PublicEvidenceValidationError("public_request_body", "eventIds must be a string array");
256
+ }
257
+ return eventIds as string[];
258
+ }
259
+
260
+ function publicBundleValue(raw: unknown): unknown {
261
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
262
+ throw new PublicEvidenceValidationError("public_request_body", "request body must be an object");
263
+ }
264
+ const keys = Object.keys(raw);
265
+ if (keys.length !== 1 || keys[0] !== "bundle") {
266
+ throw new PublicEvidenceValidationError("public_request_body", "only bundle is accepted");
267
+ }
268
+ return (raw as { bundle?: unknown }).bundle;
269
+ }
270
+
271
+ function publicErrorResponse(err: unknown, ctx: ManagementContext): Response {
272
+ if (err instanceof PublicEvidenceValidationError) {
273
+ const status = err.code === "community_cache_busy" ? 503 : 400;
274
+ const response = errorResponse(err.code, err.message, status, ctx);
275
+ if (status === 503) response.headers.set("Retry-After", "1");
276
+ return response;
277
+ }
278
+ const projected = projectionErrorResponse(err, ctx);
279
+ if (projected) return projected;
280
+ return errorResponse("public_evidence_internal", "internal public evidence failure", 500, ctx);
281
+ }
282
+
283
+ export async function handleLabRoutes(ctx: ManagementContext): Promise<Response | null> {
284
+ const { url, req, config } = ctx;
285
+ if (!url.pathname.startsWith("/api/lab")) return null;
286
+
287
+ if (req.method === "GET" && url.pathname === "/api/lab/public/community") {
288
+ try {
289
+ return jsonResponse(listCommunityEvidenceContext(), 200, req, config);
290
+ } catch (err) {
291
+ return publicErrorResponse(err, ctx);
292
+ }
293
+ }
294
+
295
+ if (req.method === "POST") {
296
+ if (url.pathname === "/api/lab/public/preview") {
297
+ try {
298
+ const body = await readBoundedPublicJson(req);
299
+ return jsonResponse(
300
+ previewLocalPublicEvidence({ eventIds: publicEventIds(body) }),
301
+ 200,
302
+ req,
303
+ config,
304
+ );
305
+ } catch (err) {
306
+ return publicErrorResponse(err, ctx);
307
+ }
308
+ }
309
+ if (url.pathname === "/api/lab/public/export") {
310
+ try {
311
+ const body = await readBoundedPublicJson(req);
312
+ return jsonResponse(
313
+ exportLocalPublicEvidence({ eventIds: publicEventIds(body) }),
314
+ 200,
315
+ req,
316
+ config,
317
+ );
318
+ } catch (err) {
319
+ return publicErrorResponse(err, ctx);
320
+ }
321
+ }
322
+ if (url.pathname === "/api/lab/public/verify") {
323
+ try {
324
+ const body = await readBoundedPublicJson(req);
325
+ const result = summarizePublicEvidenceVerification(publicBundleValue(body));
326
+ return jsonResponse(
327
+ result,
328
+ result.status === "cryptographically_valid" ? 200 : 400,
329
+ req,
330
+ config,
331
+ );
332
+ } catch (err) {
333
+ return publicErrorResponse(err, ctx);
334
+ }
335
+ }
336
+ if (url.pathname === "/api/lab/public/community/import") {
337
+ try {
338
+ const body = await readBoundedPublicJson(req);
339
+ return jsonResponse(
340
+ importCommunityEvidenceValue(publicBundleValue(body)),
341
+ 200,
342
+ req,
343
+ config,
344
+ );
345
+ } catch (err) {
346
+ return publicErrorResponse(err, ctx);
347
+ }
348
+ }
349
+ return null;
350
+ }
351
+
352
+ if (req.method !== "GET") return null;
353
+
354
+ if (url.pathname === "/api/lab/status") {
355
+ return jsonResponse(queryLabStatus(), 200, req, config);
356
+ }
357
+
358
+ if (url.pathname === "/api/lab/production-signals") {
359
+ const subjectId = url.searchParams.get("subjectId")?.trim();
360
+ if (!subjectId) return errorResponse("invalid_subject", "subjectId is required", 400, ctx);
361
+ const limit = parseLimit(url.searchParams.get("limit"), ctx, PASSIVE_PRODUCTION_MAX_LIMIT);
362
+ if (limit instanceof Response) return limit;
363
+ try {
364
+ return jsonResponse(queryPassiveProductionSignals(subjectId, limit), 200, req, config);
365
+ } catch {
366
+ return errorResponse("invalid_subject", "subjectId must be an exact Lab route subject id", 400, ctx);
367
+ }
368
+ }
369
+
370
+ if (url.pathname === "/api/lab/catalog") {
371
+ const layerRaw = url.searchParams.get("layer");
372
+ const layerParsed = layerRaw ? parseLayer(layerRaw, ctx) : undefined;
373
+ if (layerParsed instanceof Response) return layerParsed;
374
+ const suiteId = url.searchParams.get("suiteId")?.trim() || url.searchParams.get("suite")?.trim() || undefined;
375
+ try {
376
+ const scenarios = queryLabCatalogEntries({ layer: layerParsed, suiteId });
377
+ return jsonResponse({ scenarios }, 200, req, config);
378
+ } catch (err) {
379
+ const mapped = projectionErrorResponse(err, ctx);
380
+ if (mapped) return mapped;
381
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
382
+ }
383
+ }
384
+
385
+ if (url.pathname === "/api/lab/verdicts") {
386
+ const limit = parseLimit(url.searchParams.get("limit"), ctx);
387
+ if (limit instanceof Response) return limit;
388
+ const range = parseRange(url.searchParams.get("from"), url.searchParams.get("to"), ctx);
389
+ if (range instanceof Response) return range;
390
+ const layer = parseLayer(url.searchParams.get("layer"), ctx);
391
+ if (layer instanceof Response) return layer;
392
+ const verdict = parseVerdict(url.searchParams.get("verdict"), ctx);
393
+ if (verdict instanceof Response) return verdict;
394
+ try {
395
+ const page = queryLabVerdicts({
396
+ subjectId: url.searchParams.get("subjectId")?.trim() || undefined,
397
+ layer,
398
+ suiteId: url.searchParams.get("suiteId")?.trim() || undefined,
399
+ verdict,
400
+ from: range.from,
401
+ to: range.to,
402
+ }, url.searchParams.get("cursor"), limit);
403
+ return jsonResponse(paginatedEnvelope(page, "verdicts"), 200, req, config);
404
+ } catch (err) {
405
+ const mapped = projectionErrorResponse(err, ctx);
406
+ if (mapped) return mapped;
407
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
408
+ }
409
+ }
410
+
411
+ if (url.pathname === "/api/lab/subjects") {
412
+ const limit = parseLimit(url.searchParams.get("limit"), ctx);
413
+ if (limit instanceof Response) return limit;
414
+ try {
415
+ const page = queryLabSubjects(url.searchParams.get("kind")?.trim() || undefined, url.searchParams.get("cursor"), limit);
416
+ return jsonResponse(paginatedEnvelope(page, "subjects"), 200, req, config);
417
+ } catch (err) {
418
+ const mapped = projectionErrorResponse(err, ctx);
419
+ if (mapped) return mapped;
420
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
421
+ }
422
+ }
423
+
424
+ const subjectMatch = url.pathname.match(/^\/api\/lab\/subjects\/([^/]+)$/);
425
+ if (subjectMatch) {
426
+ const subjectId = decodePathSegment(subjectMatch[1]!);
427
+ if (subjectId === null) return errorResponse("not_found", "unknown resource", 404, ctx);
428
+ const unsafe = rejectUnsafeId(subjectId, ctx);
429
+ if (unsafe) return unsafe;
430
+ try {
431
+ const subject = queryLabSubjectById(subjectId);
432
+ if (!subject) return errorResponse("not_found", "unknown subject", 404, ctx);
433
+ return jsonResponse({ subjectId, subject }, 200, req, config);
434
+ } catch (err) {
435
+ const mapped = projectionErrorResponse(err, ctx);
436
+ if (mapped) return mapped;
437
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
438
+ }
439
+ }
440
+
441
+ if (url.pathname === "/api/lab/observations") {
442
+ const limit = parseLimit(url.searchParams.get("limit"), ctx);
443
+ if (limit instanceof Response) return limit;
444
+ const range = parseRange(url.searchParams.get("from"), url.searchParams.get("to"), ctx);
445
+ if (range instanceof Response) return range;
446
+ const layer = parseLayer(url.searchParams.get("layer"), ctx);
447
+ if (layer instanceof Response) return layer;
448
+ const outcome = parseOutcome(url.searchParams.get("outcome"), ctx);
449
+ if (outcome instanceof Response) return outcome;
450
+ const executionMode = parseExecutionMode(url.searchParams.get("executionMode"), ctx);
451
+ if (executionMode instanceof Response) return executionMode;
452
+ try {
453
+ const page = queryLabObservations({
454
+ subjectId: url.searchParams.get("subjectId")?.trim() || undefined,
455
+ layer,
456
+ suiteId: url.searchParams.get("suiteId")?.trim() || undefined,
457
+ scenarioId: url.searchParams.get("scenarioId")?.trim() || undefined,
458
+ outcome,
459
+ executionMode,
460
+ from: range.from,
461
+ to: range.to,
462
+ }, url.searchParams.get("cursor"), limit);
463
+ return jsonResponse(paginatedEnvelope(page, "observations"), 200, req, config);
464
+ } catch (err) {
465
+ const mapped = projectionErrorResponse(err, ctx);
466
+ if (mapped) return mapped;
467
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
468
+ }
469
+ }
470
+
471
+ if (url.pathname === "/api/lab/events") {
472
+ const limit = parseLimit(url.searchParams.get("limit"), ctx);
473
+ if (limit instanceof Response) return limit;
474
+ const range = parseRange(url.searchParams.get("from"), url.searchParams.get("to"), ctx);
475
+ if (range instanceof Response) return range;
476
+ const eventKind = parseEventKind(url.searchParams.get("eventKind"), ctx);
477
+ if (eventKind instanceof Response) return eventKind;
478
+ const excludedRaw = url.searchParams.get("excluded");
479
+ if (excludedRaw !== null && excludedRaw !== "true" && excludedRaw !== "false") {
480
+ return errorResponse("invalid_excluded", "excluded must be true or false", 400, ctx);
481
+ }
482
+ const excluded = excludedRaw === "true" ? true : excludedRaw === "false" ? false : undefined;
483
+ try {
484
+ const page = queryLabEvents({
485
+ eventKind,
486
+ subjectId: url.searchParams.get("subjectId")?.trim() || undefined,
487
+ from: range.from,
488
+ to: range.to,
489
+ excluded,
490
+ }, url.searchParams.get("cursor"), limit);
491
+ return jsonResponse(paginatedEnvelope(page, "events"), 200, req, config);
492
+ } catch (err) {
493
+ const mapped = projectionErrorResponse(err, ctx);
494
+ if (mapped) return mapped;
495
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
496
+ }
497
+ }
498
+
499
+ const eventMatch = url.pathname.match(/^\/api\/lab\/events\/([^/]+)$/);
500
+ if (eventMatch) {
501
+ const eventId = decodePathSegment(eventMatch[1]!);
502
+ if (eventId === null) return errorResponse("not_found", "unknown resource", 404, ctx);
503
+ const unsafe = rejectUnsafeId(eventId, ctx);
504
+ if (unsafe) return unsafe;
505
+ try {
506
+ const event = queryLabEventById(eventId);
507
+ if (!event) return errorResponse("not_found", "unknown event", 404, ctx);
508
+ return jsonResponse({ event }, 200, req, config);
509
+ } catch (err) {
510
+ const mapped = projectionErrorResponse(err, ctx);
511
+ if (mapped) return mapped;
512
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
513
+ }
514
+ }
515
+
516
+ if (url.pathname === "/api/lab/artifacts") {
517
+ const limit = parseLimit(url.searchParams.get("limit"), ctx);
518
+ if (limit instanceof Response) return limit;
519
+ const statusRaw = url.searchParams.get("status")?.trim();
520
+ const artifactClass = url.searchParams.get("artifactClass")?.trim() || undefined;
521
+ if (statusRaw && !["present", "corrupt", "purged_unavailable"].includes(statusRaw)) {
522
+ return errorResponse("invalid_status", "status must be present, corrupt, or purged_unavailable", 400, ctx);
523
+ }
524
+ if (artifactClass && !ARTIFACT_CLASSES.includes(artifactClass as (typeof ARTIFACT_CLASSES)[number])) {
525
+ return errorResponse(
526
+ "invalid_artifact_class",
527
+ "artifactClass must be a supported artifact class",
528
+ 400,
529
+ ctx,
530
+ );
531
+ }
532
+ try {
533
+ const page = queryLabArtifacts({
534
+ status: statusRaw as "present" | "corrupt" | "purged_unavailable" | undefined,
535
+ artifactClass: artifactClass as import("../../lab/constants").ArtifactClass | undefined,
536
+ }, url.searchParams.get("cursor"), limit);
537
+ return jsonResponse(paginatedEnvelope(page, "artifacts"), 200, req, config);
538
+ } catch (err) {
539
+ const mapped = projectionErrorResponse(err, ctx);
540
+ if (mapped) return mapped;
541
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
542
+ }
543
+ }
544
+
545
+ const artifactMatch = url.pathname.match(/^\/api\/lab\/artifacts\/([^/]+)$/);
546
+ if (artifactMatch) {
547
+ const digest = decodePathSegment(artifactMatch[1]!);
548
+ if (digest === null) return errorResponse("not_found", "unknown resource", 404, ctx);
549
+ const unsafe = rejectUnsafeId(digest, ctx);
550
+ if (unsafe) return unsafe;
551
+ try {
552
+ const artifact = queryLabArtifactByDigest(digest);
553
+ if (!artifact) return errorResponse("not_found", "unknown artifact", 404, ctx);
554
+ return jsonResponse({ artifact }, 200, req, config);
555
+ } catch (err) {
556
+ const mapped = projectionErrorResponse(err, ctx);
557
+ if (mapped) return mapped;
558
+ return errorResponse("server_error", "internal lab read failure", 500, ctx);
559
+ }
560
+ }
561
+
562
+ return null;
563
+ }