@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,310 @@
1
+ import { MAX_BYTES_PER_ARTIFACT, MAX_AGGREGATE_ARTIFACT_BYTES, MAX_ARTIFACTS_PER_RUN, ARTIFACT_FILENAME_EXT, type ArtifactClass, type ContractArtifactClass } from "../constants";
2
+ import {
3
+ artifactBytesDigest,
4
+ claimSourceManifestDigest,
5
+ fixtureDigest,
6
+ isSha256Hex,
7
+ jcsStringify,
8
+ scenarioManifestDigest,
9
+ suiteManifestDigest,
10
+ } from "../digest";
11
+ import type { ArtifactRefV1, ClaimSourceManifestV1 } from "../events/types";
12
+ import { artifactClassMediaType, validateClaimSourceManifest } from "../events/validate";
13
+ import {
14
+ closeTrustedArtifactDir,
15
+ ArtifactFsError,
16
+ deleteArtifactBytes,
17
+ openTrustedArtifactDir,
18
+ putArtifactBytes,
19
+ putNamedDigestBytes,
20
+ readArtifactBytes,
21
+ type TrustedArtifactDir,
22
+ } from "./secure-fs";
23
+ import { redactForArtifact, sanitizeDiagnostic } from "./sanitize";
24
+
25
+ export { ArtifactFsError, openTrustedArtifactDir };
26
+ export type { TrustedArtifactDir };
27
+
28
+ export interface PutArtifactInput {
29
+ artifactClass: ArtifactClass;
30
+ /** Pre-redaction payload; sanitizer runs before hash/write. */
31
+ payload: Uint8Array | string | unknown;
32
+ mediaType?: string;
33
+ redactionPolicy?: string;
34
+ /** For contract artifacts whose digest uses a domain other than artifact-bytes. */
35
+ expectedDigest?: string;
36
+ }
37
+
38
+ export interface ArtifactReadOptions {
39
+ expectedByteCount?: number;
40
+ artifactClass?: ArtifactClass;
41
+ }
42
+
43
+ export interface ArtifactStore {
44
+ dir: TrustedArtifactDir;
45
+ put(input: PutArtifactInput): ArtifactRefV1;
46
+ get(digest: string, expectedByteCountOrOpts?: number | ArtifactReadOptions): Uint8Array;
47
+ getVerified(
48
+ digest: string,
49
+ expectedByteCountOrOpts?: number | ArtifactReadOptions,
50
+ ): { bytes: Uint8Array; digest: string };
51
+ remove(digest: string): void;
52
+ close(): void;
53
+ }
54
+
55
+ function toBytes(payload: Uint8Array | string | unknown): Uint8Array {
56
+ if (payload instanceof Uint8Array) return payload;
57
+ if (typeof payload === "string") return new TextEncoder().encode(payload);
58
+ return new TextEncoder().encode(jcsStringify(payload));
59
+ }
60
+
61
+ function normalizeReadOptions(value?: number | ArtifactReadOptions): ArtifactReadOptions {
62
+ return typeof value === "number" ? { expectedByteCount: value } : value ?? {};
63
+ }
64
+
65
+ function parseContractJson(bytes: Uint8Array): unknown {
66
+ return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
67
+ }
68
+
69
+ function jsonDigest(
70
+ digest: (value: Record<string, unknown>) => string,
71
+ ): (bytes: Uint8Array) => string {
72
+ return (bytes) => {
73
+ try {
74
+ return digest(parseContractJson(bytes) as Record<string, unknown>);
75
+ } catch (err) {
76
+ if (err instanceof ArtifactFsError) throw err;
77
+ throw new ArtifactFsError("artifact_mismatch", "artifact content is not valid contract JSON");
78
+ }
79
+ };
80
+ }
81
+
82
+ function digestForArtifactClass(artifactClass: ArtifactClass): (bytes: Uint8Array) => string {
83
+ switch (artifactClass) {
84
+ case "fixture":
85
+ return fixtureDigest;
86
+ case "scenario_manifest":
87
+ return jsonDigest(scenarioManifestDigest);
88
+ case "suite_manifest":
89
+ return jsonDigest(suiteManifestDigest);
90
+ case "claim_source_manifest":
91
+ return (bytes) => {
92
+ try {
93
+ const parsed = parseContractJson(bytes);
94
+ return claimSourceManifestDigest(validateClaimSourceManifest(parsed).manifest);
95
+ } catch (err) {
96
+ if (err instanceof ArtifactFsError) throw err;
97
+ throw new ArtifactFsError("artifact_mismatch", "claim-source artifact failed validation");
98
+ }
99
+ };
100
+ default:
101
+ return artifactBytesDigest;
102
+ }
103
+ }
104
+
105
+ export function createArtifactStore(artifactsDir: string): ArtifactStore {
106
+ const dir = openTrustedArtifactDir(artifactsDir);
107
+ let aggregateBytes = 0;
108
+ let putCount = 0;
109
+
110
+ const getVerified = (
111
+ digest: string,
112
+ expectedByteCountOrOpts?: number | ArtifactReadOptions,
113
+ ): { bytes: Uint8Array; digest: string } => {
114
+ const opts = normalizeReadOptions(expectedByteCountOrOpts);
115
+ const candidates = opts.artifactClass
116
+ ? [digestForArtifactClass(opts.artifactClass)]
117
+ : [
118
+ artifactBytesDigest,
119
+ fixtureDigest,
120
+ jsonDigest(scenarioManifestDigest),
121
+ jsonDigest(suiteManifestDigest),
122
+ digestForArtifactClass("claim_source_manifest"),
123
+ ];
124
+
125
+ let lastErr: unknown;
126
+ for (const contentDigest of candidates) {
127
+ try {
128
+ const got = readArtifactBytes(dir, digest, {
129
+ expectedByteCount: opts.expectedByteCount,
130
+ contentDigest,
131
+ });
132
+ return { bytes: got.bytes, digest: got.digest };
133
+ } catch (err) {
134
+ lastErr = err;
135
+ if (
136
+ err instanceof ArtifactFsError &&
137
+ err.code !== "artifact_mismatch" &&
138
+ !err.message.includes("mismatch")
139
+ ) {
140
+ throw err;
141
+ }
142
+ }
143
+ }
144
+ throw lastErr instanceof Error
145
+ ? lastErr
146
+ : new ArtifactFsError("artifact_mismatch", "artifact digest verification failed");
147
+ };
148
+
149
+ return {
150
+ dir,
151
+ put(input: PutArtifactInput): ArtifactRefV1 {
152
+ if (putCount >= MAX_ARTIFACTS_PER_RUN) {
153
+ throw new ArtifactFsError("budget_exhausted", "maximum artifacts per run exceeded");
154
+ }
155
+ if (input.payload instanceof Uint8Array && input.payload.byteLength > MAX_BYTES_PER_ARTIFACT) {
156
+ throw new ArtifactFsError("budget_exhausted", `artifact exceeds ${MAX_BYTES_PER_ARTIFACT} bytes`);
157
+ }
158
+ if (typeof input.payload === "string" && new TextEncoder().encode(input.payload).byteLength > MAX_BYTES_PER_ARTIFACT) {
159
+ throw new ArtifactFsError("budget_exhausted", `artifact exceeds ${MAX_BYTES_PER_ARTIFACT} bytes`);
160
+ }
161
+ const redacted = redactForArtifact(input.artifactClass, input.payload);
162
+ const bytes = toBytes(redacted);
163
+ if (bytes.byteLength > MAX_BYTES_PER_ARTIFACT) {
164
+ throw new ArtifactFsError("budget_exhausted", `artifact exceeds ${MAX_BYTES_PER_ARTIFACT} bytes`);
165
+ }
166
+ if (aggregateBytes + bytes.byteLength > MAX_AGGREGATE_ARTIFACT_BYTES) {
167
+ throw new ArtifactFsError("budget_exhausted", "aggregate artifact ceiling exceeded");
168
+ }
169
+
170
+ let stored;
171
+ if (isContractClass(input.artifactClass)) {
172
+ const contractClass = input.artifactClass;
173
+ let computedDigest: string;
174
+ try {
175
+ computedDigest = computeContractDigest(contractClass, bytes, redacted);
176
+ } catch (err) {
177
+ if (err instanceof ArtifactFsError) throw err;
178
+ throw new ArtifactFsError(
179
+ "artifact_mismatch",
180
+ err instanceof Error ? err.message : "contract artifact failed validation",
181
+ );
182
+ }
183
+ if (input.expectedDigest !== undefined && computedDigest !== input.expectedDigest) {
184
+ throw new ArtifactFsError("artifact_mismatch", "contract artifact digest mismatch");
185
+ }
186
+ stored = putNamedDigestBytes(
187
+ dir,
188
+ computedDigest,
189
+ bytes,
190
+ digestForArtifactClass(contractClass),
191
+ );
192
+ } else {
193
+ stored = putArtifactBytes(dir, bytes, input.expectedDigest);
194
+ }
195
+
196
+ putCount += 1;
197
+ aggregateBytes += stored.byteCount;
198
+ return {
199
+ digest: stored.digest,
200
+ mediaType: input.mediaType ?? artifactClassMediaType(input.artifactClass),
201
+ byteCount: stored.byteCount,
202
+ redactionPolicy: input.redactionPolicy ?? defaultRedactionPolicy(input.artifactClass),
203
+ relativePath: `${stored.digest}${ARTIFACT_FILENAME_EXT}`,
204
+ artifactClass: input.artifactClass,
205
+ };
206
+ },
207
+ get(digest: string, expectedByteCountOrOpts?: number | ArtifactReadOptions): Uint8Array {
208
+ return getVerified(digest, expectedByteCountOrOpts).bytes;
209
+ },
210
+ getVerified,
211
+ remove(digest: string): void {
212
+ deleteArtifactBytes(dir, digest);
213
+ },
214
+ close(): void {
215
+ closeTrustedArtifactDir(dir);
216
+ },
217
+ };
218
+ }
219
+
220
+ function isContractClass(c: ArtifactClass): c is ContractArtifactClass {
221
+ return (
222
+ c === "scenario_manifest" ||
223
+ c === "suite_manifest" ||
224
+ c === "fixture" ||
225
+ c === "claim_source_manifest"
226
+ );
227
+ }
228
+
229
+ function computeContractDigest(
230
+ artifactClass: ContractArtifactClass,
231
+ bytes: Uint8Array,
232
+ redacted: unknown,
233
+ ): string {
234
+ switch (artifactClass) {
235
+ case "fixture":
236
+ return fixtureDigest(bytes);
237
+ case "scenario_manifest":
238
+ return scenarioManifestDigest(
239
+ typeof redacted === "object" && redacted ? (redacted as Record<string, unknown>) : parseContractJson(bytes) as Record<string, unknown>,
240
+ );
241
+ case "suite_manifest":
242
+ return suiteManifestDigest(
243
+ typeof redacted === "object" && redacted ? (redacted as Record<string, unknown>) : parseContractJson(bytes) as Record<string, unknown>,
244
+ );
245
+ case "claim_source_manifest": {
246
+ const parsed = typeof redacted === "object" && redacted
247
+ ? redacted
248
+ : parseContractJson(bytes);
249
+ return claimSourceManifestDigest(validateClaimSourceManifest(parsed).manifest);
250
+ }
251
+ default: {
252
+ const _never: never = artifactClass;
253
+ return _never;
254
+ }
255
+ }
256
+ }
257
+
258
+ function defaultRedactionPolicy(artifactClass: ArtifactClass): string {
259
+ switch (artifactClass) {
260
+ case "scenario_manifest":
261
+ case "suite_manifest":
262
+ case "fixture":
263
+ case "claim_source_manifest":
264
+ return "contract_canonical_v1";
265
+ default:
266
+ // v2 marks the sanitizer that also redacts network and account
267
+ // identifiers. The field records which algorithm produced the bytes, so
268
+ // it moves whenever those semantics change.
269
+ return "sanitized_evidence_v2";
270
+ }
271
+ }
272
+
273
+ export function putClaimSourceManifest(
274
+ store: ArtifactStore,
275
+ manifest: ClaimSourceManifestV1,
276
+ ): ArtifactRefV1 {
277
+ const { manifest: validated, digest } = validateClaimSourceManifest(manifest);
278
+ return store.put({
279
+ artifactClass: "claim_source_manifest",
280
+ payload: validated,
281
+ expectedDigest: digest,
282
+ });
283
+ }
284
+
285
+ export type LoadClaimSourceManifestResult =
286
+ | { ok: true; manifest: ClaimSourceManifestV1; corruption?: undefined }
287
+ | { ok: false; manifest: ClaimSourceManifestV1 | null; corruption: string };
288
+
289
+ export function loadClaimSourceManifest(
290
+ store: ArtifactStore,
291
+ digest: string,
292
+ expected: { subjectId: string; capability: string },
293
+ ): LoadClaimSourceManifestResult {
294
+ if (!isSha256Hex(digest)) return { ok: false, manifest: null, corruption: "invalid digest" };
295
+ try {
296
+ const bytes = store.get(digest, { artifactClass: "claim_source_manifest" });
297
+ const parsed = parseContractJson(bytes);
298
+ const { manifest, digest: recomputed } = validateClaimSourceManifest(parsed);
299
+ if (recomputed !== digest) return { ok: false, manifest, corruption: "claim-source digest mismatch" };
300
+ if (manifest.subjectId !== expected.subjectId) return { ok: false, manifest, corruption: "claim-source subjectId mismatch" };
301
+ if (manifest.capability !== expected.capability) return { ok: false, manifest, corruption: "claim-source capability mismatch" };
302
+ return { ok: true, manifest };
303
+ } catch (err) {
304
+ return {
305
+ ok: false,
306
+ manifest: null,
307
+ corruption: sanitizeDiagnostic(err),
308
+ };
309
+ }
310
+ }
@@ -0,0 +1,78 @@
1
+ import { LAB_AUTOMATION_HARD_MAX } from "./constants";
2
+ import type { LabAutomationPolicyV1, LabAutomationStateV1 } from "./types";
3
+
4
+ export function rollBudgetWindow(state: LabAutomationStateV1, now: number): LabAutomationStateV1 {
5
+ if (now - state.budgetWindowStartedAt < LAB_AUTOMATION_HARD_MAX.budgetWindowMs) return state;
6
+ return {
7
+ ...state,
8
+ budgetWindowStartedAt: now,
9
+ runsThisHour: 0,
10
+ liveRequestsThisHour: 0,
11
+ };
12
+ }
13
+
14
+ function rollingStartedRuns(state: LabAutomationStateV1, now: number): number {
15
+ const cutoff = now - LAB_AUTOMATION_HARD_MAX.budgetWindowMs;
16
+ return state.runs.filter((run) => typeof run.startedAt === "number" && run.startedAt > cutoff && run.startedAt <= now).length;
17
+ }
18
+
19
+ function rollingStartedLiveRuns(state: LabAutomationStateV1, now: number): number {
20
+ const cutoff = now - LAB_AUTOMATION_HARD_MAX.budgetWindowMs;
21
+ return state.runs.filter((run) =>
22
+ run.evidenceLayer === "live_route_compatibility"
23
+ && typeof run.startedAt === "number"
24
+ && run.startedAt > cutoff
25
+ && run.startedAt <= now
26
+ ).length;
27
+ }
28
+
29
+ function legacyCounterActive(state: LabAutomationStateV1, now: number): boolean {
30
+ return now - state.budgetWindowStartedAt < LAB_AUTOMATION_HARD_MAX.budgetWindowMs;
31
+ }
32
+
33
+ export function runBudgetRemaining(
34
+ policy: LabAutomationPolicyV1,
35
+ state: LabAutomationStateV1,
36
+ now = Date.now(),
37
+ ): number {
38
+ const rolling = rollingStartedRuns(state, now);
39
+ const legacy = legacyCounterActive(state, now) ? state.runsThisHour : 0;
40
+ return Math.max(0, policy.maxRunsPerHour - Math.max(rolling, legacy));
41
+ }
42
+
43
+ export function liveRequestBudgetRemaining(
44
+ policy: LabAutomationPolicyV1,
45
+ state: LabAutomationStateV1,
46
+ now = Date.now(),
47
+ ): number {
48
+ const rolling = rollingStartedLiveRuns(state, now);
49
+ const legacy = legacyCounterActive(state, now) ? state.liveRequestsThisHour : 0;
50
+ return Math.max(0, policy.maxLiveRequestsPerHour - Math.max(rolling, legacy));
51
+ }
52
+
53
+ export function isRunBudgetExhausted(
54
+ policy: LabAutomationPolicyV1,
55
+ state: LabAutomationStateV1,
56
+ now = Date.now(),
57
+ ): boolean {
58
+ return runBudgetRemaining(policy, state, now) <= 0;
59
+ }
60
+
61
+ export function isLiveRequestBudgetExhausted(
62
+ policy: LabAutomationPolicyV1,
63
+ state: LabAutomationStateV1,
64
+ now = Date.now(),
65
+ ): boolean {
66
+ return liveRequestBudgetRemaining(policy, state, now) <= 0;
67
+ }
68
+
69
+ /** Legacy persisted counters remain for schema compatibility; startedAt records are rolling authority. */
70
+ export function recordRunBudgetUse(state: LabAutomationStateV1, liveRequest: boolean): LabAutomationStateV1 {
71
+ return {
72
+ ...state,
73
+ runsThisHour: Math.min(LAB_AUTOMATION_HARD_MAX.maxRunsPerHour, state.runsThisHour + 1),
74
+ liveRequestsThisHour: liveRequest
75
+ ? Math.min(LAB_AUTOMATION_HARD_MAX.maxLiveRequestsPerHour, state.liveRequestsThisHour + 1)
76
+ : state.liveRequestsThisHour,
77
+ };
78
+ }
@@ -0,0 +1,256 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import {
3
+ closeSync,
4
+ existsSync,
5
+ fsyncSync,
6
+ linkSync,
7
+ openSync,
8
+ readFileSync,
9
+ unlinkSync,
10
+ writeFileSync,
11
+ } from "node:fs";
12
+ import { dirname, join } from "node:path";
13
+ import { renameAtomicFile } from "../../lib/windows-atomic-replace";
14
+ import {
15
+ ensureLabDirs,
16
+ labAutomationPolicyPath,
17
+ } from "../paths";
18
+ import { normalizeLabAutomationPolicyV1 } from "./policy";
19
+ import {
20
+ loadLabAutomationPolicy,
21
+ loadLabAutomationRoutes,
22
+ normalizeLabAutomationRoutesV1,
23
+ } from "./persistence";
24
+ import type { LabAutomationPolicyV1, LabAutomationRoutesV1 } from "./types";
25
+ import { LabAutomationError } from "./types";
26
+
27
+ const CONFIG_SCHEMA_VERSION = 1 as const;
28
+ const CONFIG_KEYS = new Set(["schemaVersion", "policy", "routes"]);
29
+ const CONFIG_LOCK_WAIT_MS = 5_000;
30
+ const LOCK_SLEEP = new Int32Array(new SharedArrayBuffer(4));
31
+
32
+ interface ConfigLockMeta {
33
+ pid: number;
34
+ token: string;
35
+ }
36
+
37
+ export interface LabAutomationConfigV1 {
38
+ schemaVersion: typeof CONFIG_SCHEMA_VERSION;
39
+ policy: LabAutomationPolicyV1;
40
+ routes: LabAutomationRoutesV1;
41
+ }
42
+
43
+ type ConfigCommitFault = "before_publish" | null;
44
+ let configCommitFaultForTests: ConfigCommitFault = null;
45
+
46
+ function configPath(configDir?: string): string {
47
+ return join(dirname(labAutomationPolicyPath(configDir)), "automation-config.json");
48
+ }
49
+
50
+ function configLockPath(configDir?: string): string {
51
+ return `${configPath(configDir)}.lock`;
52
+ }
53
+
54
+ function sleepLockRetry(): void {
55
+ Atomics.wait(LOCK_SLEEP, 0, 0, 10);
56
+ }
57
+
58
+ function readLockMeta(lockPath: string): ConfigLockMeta | null {
59
+ try {
60
+ const parsed = JSON.parse(readFileSync(lockPath, "utf8")) as unknown;
61
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
62
+ const row = parsed as Record<string, unknown>;
63
+ if (!Number.isSafeInteger(row.pid) || (row.pid as number) <= 0) return null;
64
+ if (typeof row.token !== "string" || row.token.length < 16 || row.token.length > 128) return null;
65
+ return { pid: row.pid as number, token: row.token };
66
+ } catch {
67
+ return null;
68
+ }
69
+ }
70
+
71
+ function pidDefinitelyDead(pid: number): boolean {
72
+ try {
73
+ process.kill(pid, 0);
74
+ return false;
75
+ } catch (error) {
76
+ const code = error && typeof error === "object" && "code" in error
77
+ ? String((error as { code?: unknown }).code)
78
+ : undefined;
79
+ return code === "ESRCH";
80
+ }
81
+ }
82
+
83
+ function cleanupFile(path: string): void {
84
+ try {
85
+ unlinkSync(path);
86
+ } catch {
87
+ // Absent or already cleaned.
88
+ }
89
+ }
90
+
91
+ function releaseLock(lockPath: string, token: string): void {
92
+ try {
93
+ if (readLockMeta(lockPath)?.token === token) unlinkSync(lockPath);
94
+ } catch {
95
+ // Already released or replaced.
96
+ }
97
+ }
98
+
99
+ function reclaimDeadLock(lockPath: string): boolean {
100
+ const observed = readLockMeta(lockPath);
101
+ if (!observed || !pidDefinitelyDead(observed.pid)) return false;
102
+ const current = readLockMeta(lockPath);
103
+ if (!current || current.pid !== observed.pid || current.token !== observed.token) return false;
104
+ try {
105
+ unlinkSync(lockPath);
106
+ return true;
107
+ } catch {
108
+ return false;
109
+ }
110
+ }
111
+
112
+ function acquireConfigLock(configDir?: string): () => void {
113
+ ensureLabDirs(configDir);
114
+ const lockPath = configLockPath(configDir);
115
+ const deadline = Date.now() + CONFIG_LOCK_WAIT_MS;
116
+ while (true) {
117
+ const token = randomUUID();
118
+ const privatePath = `${lockPath}.${process.pid}.${token}.tmp`;
119
+ let publicationAttempted = false;
120
+ try {
121
+ const fd = openSync(privatePath, "wx", 0o600);
122
+ try {
123
+ writeFileSync(fd, JSON.stringify({ pid: process.pid, token }), { encoding: "utf8" });
124
+ fsyncSync(fd);
125
+ } finally {
126
+ closeSync(fd);
127
+ }
128
+ publicationAttempted = true;
129
+ linkSync(privatePath, lockPath);
130
+ cleanupFile(privatePath);
131
+ return () => releaseLock(lockPath, token);
132
+ } catch (error) {
133
+ cleanupFile(privatePath);
134
+ const code = error && typeof error === "object" && "code" in error
135
+ ? String((error as { code?: unknown }).code)
136
+ : undefined;
137
+ if (code === "EEXIST" && !publicationAttempted) continue;
138
+ if (code !== "EEXIST") {
139
+ throw new LabAutomationError("automation config lock failed", "state_lock_failed");
140
+ }
141
+ if (reclaimDeadLock(lockPath)) continue;
142
+ if (Date.now() >= deadline) {
143
+ throw new LabAutomationError("automation config is busy", "state_lock_busy");
144
+ }
145
+ sleepLockRetry();
146
+ }
147
+ }
148
+ }
149
+
150
+ function withConfigLock<T>(configDir: string | undefined, action: () => T): T {
151
+ const release = acquireConfigLock(configDir);
152
+ try {
153
+ return action();
154
+ } finally {
155
+ release();
156
+ }
157
+ }
158
+
159
+ function normalizeConfig(raw: unknown): LabAutomationConfigV1 {
160
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
161
+ throw new LabAutomationError("automation config must be an object", "invalid_state");
162
+ }
163
+ const row = raw as Record<string, unknown>;
164
+ for (const key of Object.keys(row)) {
165
+ if (!CONFIG_KEYS.has(key)) {
166
+ throw new LabAutomationError(`unknown automation config field ${key}`, "invalid_state");
167
+ }
168
+ }
169
+ if (row.schemaVersion !== CONFIG_SCHEMA_VERSION) {
170
+ throw new LabAutomationError("unsupported automation config schemaVersion", "invalid_state");
171
+ }
172
+ return Object.freeze({
173
+ schemaVersion: CONFIG_SCHEMA_VERSION,
174
+ policy: normalizeLabAutomationPolicyV1(row.policy),
175
+ routes: normalizeLabAutomationRoutesV1(row.routes),
176
+ });
177
+ }
178
+
179
+ function loadConfigUnlocked(configDir?: string): LabAutomationConfigV1 {
180
+ ensureLabDirs(configDir);
181
+ const path = configPath(configDir);
182
+ if (!existsSync(path)) {
183
+ return Object.freeze({
184
+ schemaVersion: CONFIG_SCHEMA_VERSION,
185
+ policy: loadLabAutomationPolicy(configDir),
186
+ routes: loadLabAutomationRoutes(configDir),
187
+ });
188
+ }
189
+ try {
190
+ return normalizeConfig(JSON.parse(readFileSync(path, "utf8")) as unknown);
191
+ } catch (error) {
192
+ if (error instanceof LabAutomationError) throw error;
193
+ throw new LabAutomationError("invalid automation config JSON", "invalid_state");
194
+ }
195
+ }
196
+
197
+ function writeConfigUnlocked(
198
+ policy: LabAutomationPolicyV1,
199
+ routes: LabAutomationRoutesV1,
200
+ configDir?: string,
201
+ ): LabAutomationConfigV1 {
202
+ ensureLabDirs(configDir);
203
+ const normalized = Object.freeze({
204
+ schemaVersion: CONFIG_SCHEMA_VERSION,
205
+ policy: normalizeLabAutomationPolicyV1(policy),
206
+ routes: normalizeLabAutomationRoutesV1(routes),
207
+ });
208
+ const path = configPath(configDir);
209
+ const tmp = join(dirname(path), `.automation-config.${process.pid}.${randomUUID()}.tmp`);
210
+ let fd: number | null = null;
211
+ try {
212
+ fd = openSync(tmp, "wx", 0o600);
213
+ writeFileSync(fd, JSON.stringify(normalized), { encoding: "utf8" });
214
+ fsyncSync(fd);
215
+ closeSync(fd);
216
+ fd = null;
217
+ if (configCommitFaultForTests === "before_publish") {
218
+ throw new LabAutomationError("synthetic automation config commit failure", "invalid_state");
219
+ }
220
+ renameAtomicFile(tmp, path, undefined, "lab-automation");
221
+ return normalized;
222
+ } finally {
223
+ if (fd !== null) closeSync(fd);
224
+ cleanupFile(tmp);
225
+ }
226
+ }
227
+
228
+ /** Load one coherent policy/routes generation. */
229
+ export function loadLabAutomationConfig(configDir?: string): LabAutomationConfigV1 {
230
+ return withConfigLock(configDir, () => loadConfigUnlocked(configDir));
231
+ }
232
+
233
+ /** Atomically publish one coherent policy/routes generation. */
234
+ export function saveLabAutomationConfig(
235
+ policy: LabAutomationPolicyV1,
236
+ routes: LabAutomationRoutesV1,
237
+ configDir?: string,
238
+ ): LabAutomationConfigV1 {
239
+ return withConfigLock(configDir, () => writeConfigUnlocked(policy, routes, configDir));
240
+ }
241
+
242
+ /** Update only policy while preserving routes from the same committed generation. */
243
+ export function saveLabAutomationPolicyConfig(
244
+ policy: LabAutomationPolicyV1,
245
+ configDir?: string,
246
+ ): LabAutomationConfigV1 {
247
+ return withConfigLock(configDir, () => {
248
+ const current = loadConfigUnlocked(configDir);
249
+ return writeConfigUnlocked(policy, current.routes, configDir);
250
+ });
251
+ }
252
+
253
+ /** Test-only fault injection before the atomic rename publication point. */
254
+ export function setLabAutomationConfigCommitFaultForTests(fault: ConfigCommitFault): void {
255
+ configCommitFaultForTests = fault;
256
+ }
@@ -0,0 +1,39 @@
1
+ /** CL-08 automation hard ceilings — callers cannot raise policy above these values. */
2
+
3
+ export const LAB_AUTOMATION_POLICY_SCHEMA_VERSION = 1 as const;
4
+
5
+ export const LAB_AUTOMATION_HARD_MAX = Object.freeze({
6
+ refreshBeforeStaleMs: 30 * 24 * 60 * 60 * 1000,
7
+ maxConcurrentRuns: 4,
8
+ maxConcurrentLiveRuns: 2,
9
+ maxConcurrentRunsPerRoute: 2,
10
+ maxRunsPerHour: 60,
11
+ maxLiveRequestsPerHour: 30,
12
+ failureCooldownMs: 24 * 60 * 60 * 1000,
13
+ blockedCooldownMs: 7 * 24 * 60 * 60 * 1000,
14
+ terminalRunRetentionMs: 7 * 24 * 60 * 60 * 1000,
15
+ maxQueuedRuns: 256,
16
+ maxPersistedRuns: 512,
17
+ maxAutomationRoutes: 64,
18
+ budgetWindowMs: 60 * 60 * 1000,
19
+ schedulerTickMs: 60 * 1000,
20
+ });
21
+
22
+ export const LAB_AUTOMATION_DEFAULT_POLICY = Object.freeze({
23
+ schemaVersion: LAB_AUTOMATION_POLICY_SCHEMA_VERSION,
24
+ enabled: false,
25
+ layers: Object.freeze({
26
+ protocolConformance: false,
27
+ liveRouteCompatibility: false,
28
+ taskEffectiveness: false,
29
+ }),
30
+ refreshBeforeStaleMs: 24 * 60 * 60 * 1000,
31
+ maxConcurrentRuns: 2,
32
+ maxConcurrentLiveRuns: 1,
33
+ maxConcurrentRunsPerRoute: 1,
34
+ maxRunsPerHour: 12,
35
+ maxLiveRequestsPerHour: 6,
36
+ failureCooldownMs: 5 * 60 * 1000,
37
+ blockedCooldownMs: 60 * 60 * 1000,
38
+ taskEffectivenessBackgroundEnabled: false,
39
+ });