@yansigit/opencodex 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (826) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/LICENSE +21 -0
  3. package/README.md +303 -0
  4. package/assets/architecture.png +0 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/claude-code-models.gif +0 -0
  7. package/assets/codex-app-picker.png +0 -0
  8. package/bin/ocx.mjs +587 -0
  9. package/bin/package-main.mjs +9 -0
  10. package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
  11. package/gui/dist/assets/index-CGoDO3uO.css +1 -0
  12. package/gui/dist/favicon.png +0 -0
  13. package/gui/dist/icons.svg +24 -0
  14. package/gui/dist/index.html +25 -0
  15. package/gui/dist/logo.png +0 -0
  16. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  17. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  18. package/gui/dist/provider-icons/claude-color.svg +1 -0
  19. package/gui/dist/provider-icons/cline-color.svg +16 -0
  20. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  21. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  22. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  23. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  24. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  25. package/gui/dist/provider-icons/discord.svg +1 -0
  26. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  27. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  28. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  29. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  30. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  31. package/gui/dist/provider-icons/grok.svg +1 -0
  32. package/gui/dist/provider-icons/groq-color.svg +1 -0
  33. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  34. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  35. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  36. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  37. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  38. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  39. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  40. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  41. package/gui/dist/provider-icons/openai.svg +1 -0
  42. package/gui/dist/provider-icons/opencode.svg +2 -0
  43. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  44. package/gui/dist/provider-icons/pi.svg +21 -0
  45. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  46. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  47. package/gui/dist/provider-icons/telegram.svg +1 -0
  48. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  49. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  50. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  51. package/package.json +108 -0
  52. package/src/AGENTS.md +28 -0
  53. package/src/adapters/anthropic-image-guard.ts +251 -0
  54. package/src/adapters/anthropic-image-normalize.ts +518 -0
  55. package/src/adapters/anthropic-output-schema.ts +137 -0
  56. package/src/adapters/anthropic.ts +1327 -0
  57. package/src/adapters/azure.ts +36 -0
  58. package/src/adapters/base.ts +121 -0
  59. package/src/adapters/client-fingerprint.ts +65 -0
  60. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  61. package/src/adapters/command-code.ts +601 -0
  62. package/src/adapters/cursor/arg-codec.ts +38 -0
  63. package/src/adapters/cursor/arg-normalize.ts +104 -0
  64. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  65. package/src/adapters/cursor/cursor-errors.ts +288 -0
  66. package/src/adapters/cursor/discovery.ts +333 -0
  67. package/src/adapters/cursor/effort-map.ts +151 -0
  68. package/src/adapters/cursor/exec-policy.ts +88 -0
  69. package/src/adapters/cursor/framing.ts +250 -0
  70. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  71. package/src/adapters/cursor/h2-pool.ts +123 -0
  72. package/src/adapters/cursor/http1-bidi.ts +361 -0
  73. package/src/adapters/cursor/images.ts +704 -0
  74. package/src/adapters/cursor/kv-store.ts +52 -0
  75. package/src/adapters/cursor/live-models.ts +269 -0
  76. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  77. package/src/adapters/cursor/live-transport.ts +1653 -0
  78. package/src/adapters/cursor/mcp-config.ts +42 -0
  79. package/src/adapters/cursor/mcp-manager.ts +333 -0
  80. package/src/adapters/cursor/message-mapper.ts +49 -0
  81. package/src/adapters/cursor/native-exec-common.ts +76 -0
  82. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  83. package/src/adapters/cursor/native-exec-fs.ts +332 -0
  84. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  85. package/src/adapters/cursor/native-exec-network.ts +43 -0
  86. package/src/adapters/cursor/native-exec-shell.ts +547 -0
  87. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  88. package/src/adapters/cursor/native-exec.ts +663 -0
  89. package/src/adapters/cursor/protobuf-events.ts +1381 -0
  90. package/src/adapters/cursor/protobuf-request.ts +1032 -0
  91. package/src/adapters/cursor/request-builder.ts +461 -0
  92. package/src/adapters/cursor/thread-continuity.ts +67 -0
  93. package/src/adapters/cursor/tool-definitions.ts +735 -0
  94. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  95. package/src/adapters/cursor/transport-retry.ts +132 -0
  96. package/src/adapters/cursor/transport.ts +79 -0
  97. package/src/adapters/cursor/types.ts +79 -0
  98. package/src/adapters/cursor.ts +322 -0
  99. package/src/adapters/google-antigravity-hosts.ts +48 -0
  100. package/src/adapters/google-antigravity-replay.ts +827 -0
  101. package/src/adapters/google-antigravity-tools.ts +105 -0
  102. package/src/adapters/google-antigravity-wire.ts +141 -0
  103. package/src/adapters/google-errors.ts +92 -0
  104. package/src/adapters/google-http.ts +460 -0
  105. package/src/adapters/google-tool-schema.ts +238 -0
  106. package/src/adapters/google-truncation.ts +24 -0
  107. package/src/adapters/google-wire-compiler.ts +232 -0
  108. package/src/adapters/google.ts +1377 -0
  109. package/src/adapters/identity.ts +77 -0
  110. package/src/adapters/image.ts +23 -0
  111. package/src/adapters/kiro-constants.ts +16 -0
  112. package/src/adapters/kiro-errors.ts +208 -0
  113. package/src/adapters/kiro-events.ts +197 -0
  114. package/src/adapters/kiro-images.ts +129 -0
  115. package/src/adapters/kiro-retry.ts +312 -0
  116. package/src/adapters/kiro-thinking.ts +112 -0
  117. package/src/adapters/kiro-tool-fallback.ts +36 -0
  118. package/src/adapters/kiro-tools.ts +224 -0
  119. package/src/adapters/kiro-truncation.ts +33 -0
  120. package/src/adapters/kiro-wire.ts +129 -0
  121. package/src/adapters/kiro.ts +1936 -0
  122. package/src/adapters/mimo-free.ts +280 -0
  123. package/src/adapters/openai-chat-url.ts +11 -0
  124. package/src/adapters/openai-chat.ts +1980 -0
  125. package/src/adapters/openai-responses-url.ts +16 -0
  126. package/src/adapters/openai-responses.ts +1911 -0
  127. package/src/adapters/registry.ts +175 -0
  128. package/src/adapters/responses-tool-schema.ts +67 -0
  129. package/src/adapters/run-turn-queue.ts +114 -0
  130. package/src/adapters/tool-call-id.ts +119 -0
  131. package/src/adapters/tool-catalog-nudge.ts +154 -0
  132. package/src/adapters/upstream-http-error.ts +48 -0
  133. package/src/adapters/xai-web-search.ts +185 -0
  134. package/src/bridge.ts +1986 -0
  135. package/src/chat/inbound.ts +319 -0
  136. package/src/chat/outbound.ts +821 -0
  137. package/src/claude/agents-inject.ts +266 -0
  138. package/src/claude/alias.ts +149 -0
  139. package/src/claude/auth-detect.ts +229 -0
  140. package/src/claude/auth-mode-migration.ts +32 -0
  141. package/src/claude/auth-mode.ts +62 -0
  142. package/src/claude/context-windows.ts +205 -0
  143. package/src/claude/desktop-3p-guard.ts +35 -0
  144. package/src/claude/desktop-3p-paths.ts +84 -0
  145. package/src/claude/desktop-3p.ts +615 -0
  146. package/src/claude/desktop-health.ts +26 -0
  147. package/src/claude/desktop-profile.ts +263 -0
  148. package/src/claude/gateway-cache.ts +107 -0
  149. package/src/claude/inbound-debug.ts +163 -0
  150. package/src/claude/inbound.ts +578 -0
  151. package/src/claude/model-info.ts +174 -0
  152. package/src/claude/outbound.ts +926 -0
  153. package/src/cli/access.ts +108 -0
  154. package/src/cli/account-api.ts +302 -0
  155. package/src/cli/account-auth.ts +250 -0
  156. package/src/cli/account-catalog-refresh.ts +14 -0
  157. package/src/cli/account-extended.ts +737 -0
  158. package/src/cli/account-main.ts +317 -0
  159. package/src/cli/account.ts +299 -0
  160. package/src/cli/agent-driven.ts +70 -0
  161. package/src/cli/agent.ts +290 -0
  162. package/src/cli/catalog-prewarm.ts +27 -0
  163. package/src/cli/claude-agent-startup-sync.ts +73 -0
  164. package/src/cli/claude-desktop.ts +213 -0
  165. package/src/cli/claude.ts +355 -0
  166. package/src/cli/codex-log-guard-doctor.ts +103 -0
  167. package/src/cli/codex-shim-autorestore.ts +47 -0
  168. package/src/cli/codex-shim-readiness.ts +76 -0
  169. package/src/cli/combo.ts +127 -0
  170. package/src/cli/config-command.ts +209 -0
  171. package/src/cli/debug.ts +228 -0
  172. package/src/cli/dispatch.ts +585 -0
  173. package/src/cli/doctor.ts +1202 -0
  174. package/src/cli/ensure-desired-integrations.ts +152 -0
  175. package/src/cli/export-command.ts +213 -0
  176. package/src/cli/help.ts +101 -0
  177. package/src/cli/index.ts +973 -0
  178. package/src/cli/init.ts +211 -0
  179. package/src/cli/integrations.ts +260 -0
  180. package/src/cli/interactive-confirm.ts +133 -0
  181. package/src/cli/lab.ts +607 -0
  182. package/src/cli/launcher-context.ts +77 -0
  183. package/src/cli/minimax.ts +497 -0
  184. package/src/cli/models-runtime.ts +245 -0
  185. package/src/cli/models.ts +422 -0
  186. package/src/cli/observe.ts +206 -0
  187. package/src/cli/opencode.ts +588 -0
  188. package/src/cli/provider-replit.ts +232 -0
  189. package/src/cli/provider-runtime.ts +179 -0
  190. package/src/cli/provider.ts +492 -0
  191. package/src/cli/ready.ts +301 -0
  192. package/src/cli/registry.ts +422 -0
  193. package/src/cli/replit-gateway-key-input.ts +138 -0
  194. package/src/cli/root.ts +86 -0
  195. package/src/cli/route-policy.ts +92 -0
  196. package/src/cli/runtime-api.ts +328 -0
  197. package/src/cli/star-prompt.ts +211 -0
  198. package/src/cli/status-oauth.ts +78 -0
  199. package/src/cli/status.ts +328 -0
  200. package/src/cli/system-command.ts +112 -0
  201. package/src/cli/system-restart-client.ts +146 -0
  202. package/src/cli/tray-proxy.ts +199 -0
  203. package/src/cli/v2.ts +268 -0
  204. package/src/cli.ts +10 -0
  205. package/src/clients/config-export.ts +1704 -0
  206. package/src/codex/account-id.ts +34 -0
  207. package/src/codex/account-label.ts +47 -0
  208. package/src/codex/account-lifecycle.ts +172 -0
  209. package/src/codex/account-namespace-match.ts +63 -0
  210. package/src/codex/account-namespaces.ts +195 -0
  211. package/src/codex/account-pause.ts +20 -0
  212. package/src/codex/account-priority.ts +83 -0
  213. package/src/codex/account-runtime-state.ts +31 -0
  214. package/src/codex/account-store.ts +544 -0
  215. package/src/codex/account-usability.ts +43 -0
  216. package/src/codex/admission.ts +256 -0
  217. package/src/codex/affinity-debug.ts +162 -0
  218. package/src/codex/agent-roles-sync.ts +225 -0
  219. package/src/codex/agent-roles.ts +238 -0
  220. package/src/codex/app-server-processes.ts +1143 -0
  221. package/src/codex/app-server-restart-service.ts +232 -0
  222. package/src/codex/auth-api.ts +2147 -0
  223. package/src/codex/auth-collision.ts +109 -0
  224. package/src/codex/auth-context.ts +665 -0
  225. package/src/codex/autostart-health.ts +156 -0
  226. package/src/codex/catalog/account-models.ts +67 -0
  227. package/src/codex/catalog/aggregation.ts +436 -0
  228. package/src/codex/catalog/bundled.ts +549 -0
  229. package/src/codex/catalog/effort.ts +446 -0
  230. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  231. package/src/codex/catalog/kinds.ts +2 -0
  232. package/src/codex/catalog/metadata.ts +664 -0
  233. package/src/codex/catalog/native-models.ts +72 -0
  234. package/src/codex/catalog/parsing.ts +650 -0
  235. package/src/codex/catalog/provider-fetch.ts +2064 -0
  236. package/src/codex/catalog/sync.ts +1883 -0
  237. package/src/codex/catalog-admission.ts +199 -0
  238. package/src/codex/catalog-refresh-status.ts +105 -0
  239. package/src/codex/catalog-write-serialization.ts +242 -0
  240. package/src/codex/catalog.ts +14 -0
  241. package/src/codex/codex-write-lock.ts +384 -0
  242. package/src/codex/convergence-types.ts +614 -0
  243. package/src/codex/convergence.ts +651 -0
  244. package/src/codex/coordinator-doctor.ts +332 -0
  245. package/src/codex/custom-model-catalog-migration.ts +176 -0
  246. package/src/codex/data/upstream-models.json +830 -0
  247. package/src/codex/desired-state.ts +230 -0
  248. package/src/codex/exec-invocation.ts +22 -0
  249. package/src/codex/features.ts +1566 -0
  250. package/src/codex/generation.ts +202 -0
  251. package/src/codex/history-job.ts +407 -0
  252. package/src/codex/history-lock.ts +242 -0
  253. package/src/codex/history-migration-guardian.ts +108 -0
  254. package/src/codex/history-provider.ts +979 -0
  255. package/src/codex/history-transition.ts +105 -0
  256. package/src/codex/history-worker.ts +220 -0
  257. package/src/codex/home.ts +206 -0
  258. package/src/codex/inject-coordination.ts +290 -0
  259. package/src/codex/inject.ts +1733 -0
  260. package/src/codex/injected-marker.ts +106 -0
  261. package/src/codex/integration-record.ts +266 -0
  262. package/src/codex/internal/catalog-writer.ts +203 -0
  263. package/src/codex/internal/history-writer.ts +80 -0
  264. package/src/codex/journal.ts +225 -0
  265. package/src/codex/log-guard/inspect.ts +506 -0
  266. package/src/codex/log-guard/lock.ts +150 -0
  267. package/src/codex/log-guard/maintenance.ts +403 -0
  268. package/src/codex/log-guard/path-safety.ts +88 -0
  269. package/src/codex/log-guard/policy.ts +44 -0
  270. package/src/codex/log-guard/processes.ts +205 -0
  271. package/src/codex/log-guard/protection.ts +489 -0
  272. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  273. package/src/codex/main-account-cache.ts +56 -0
  274. package/src/codex/main-account.ts +68 -0
  275. package/src/codex/management-convergence.ts +167 -0
  276. package/src/codex/model-cache.ts +273 -0
  277. package/src/codex/model-entitlements.ts +353 -0
  278. package/src/codex/native-main-admission.ts +47 -0
  279. package/src/codex/native-main-auth-temp.ts +187 -0
  280. package/src/codex/native-main-claim.ts +178 -0
  281. package/src/codex/native-main-lock-file.ts +162 -0
  282. package/src/codex/native-main-owner.ts +329 -0
  283. package/src/codex/native-profile-api.ts +247 -0
  284. package/src/codex/native-profile-manager.ts +1531 -0
  285. package/src/codex/native-profile-processes.ts +121 -0
  286. package/src/codex/native-profile-recovery.ts +99 -0
  287. package/src/codex/native-profile-stage-store.ts +387 -0
  288. package/src/codex/native-profile-startup.ts +492 -0
  289. package/src/codex/native-profile-store.ts +855 -0
  290. package/src/codex/native-profile-types.ts +120 -0
  291. package/src/codex/native-residue.ts +682 -0
  292. package/src/codex/paths.ts +144 -0
  293. package/src/codex/plan-from-token.ts +140 -0
  294. package/src/codex/plan.ts +40 -0
  295. package/src/codex/plugins-doctor.ts +242 -0
  296. package/src/codex/pool-rotation.ts +295 -0
  297. package/src/codex/project-config-warnings.ts +425 -0
  298. package/src/codex/prompt-journal.ts +352 -0
  299. package/src/codex/prompt-layers.ts +967 -0
  300. package/src/codex/prompt-lock.ts +143 -0
  301. package/src/codex/quota-rejection.ts +298 -0
  302. package/src/codex/quota.ts +573 -0
  303. package/src/codex/refresh.ts +62 -0
  304. package/src/codex/reset-credit-recovery.ts +1044 -0
  305. package/src/codex/routing.ts +1888 -0
  306. package/src/codex/runtime.ts +659 -0
  307. package/src/codex/shim.ts +2170 -0
  308. package/src/codex/subagent-defaults.ts +550 -0
  309. package/src/codex/subagent-model-fallback.ts +784 -0
  310. package/src/codex/sync.ts +319 -0
  311. package/src/codex/transition-state.ts +612 -0
  312. package/src/codex/upstream-host-health.ts +368 -0
  313. package/src/codex/user-identity.ts +557 -0
  314. package/src/codex/warmup.ts +298 -0
  315. package/src/codex/websocket-registry.ts +100 -0
  316. package/src/codex/write-coordination.ts +114 -0
  317. package/src/combos/failover.ts +160 -0
  318. package/src/combos/index.ts +45 -0
  319. package/src/combos/request.ts +94 -0
  320. package/src/combos/resolve.ts +232 -0
  321. package/src/combos/types.ts +398 -0
  322. package/src/config/provider-name.ts +24 -0
  323. package/src/config.ts +4041 -0
  324. package/src/fork/register.ts +3 -0
  325. package/src/generated/compatibility-version.json +3116 -0
  326. package/src/generated/model-metadata.ts +106 -0
  327. package/src/github/star-state.ts +203 -0
  328. package/src/grok/inject.ts +530 -0
  329. package/src/grok/inspect.ts +45 -0
  330. package/src/grok/status.ts +121 -0
  331. package/src/grok/sync.ts +66 -0
  332. package/src/images/artifacts.ts +516 -0
  333. package/src/images/fulfill-video.ts +163 -0
  334. package/src/images/fulfill.ts +149 -0
  335. package/src/images/index.ts +4 -0
  336. package/src/images/loop.ts +955 -0
  337. package/src/images/plan.ts +143 -0
  338. package/src/images/synthetic-tool.ts +133 -0
  339. package/src/images/types.ts +41 -0
  340. package/src/images/xai-client.ts +141 -0
  341. package/src/images/xai-video-client.ts +163 -0
  342. package/src/index.ts +22 -0
  343. package/src/integrations/config-io.ts +269 -0
  344. package/src/integrations/journal.ts +315 -0
  345. package/src/integrations/merge.ts +135 -0
  346. package/src/integrations/mutation-flight.ts +71 -0
  347. package/src/integrations/native/ownership-preflight.ts +202 -0
  348. package/src/integrations/omp-yaml-source.ts +358 -0
  349. package/src/integrations/owned-refresh.ts +74 -0
  350. package/src/integrations/ownership.ts +111 -0
  351. package/src/integrations/registry.ts +159 -0
  352. package/src/integrations/serialize.ts +314 -0
  353. package/src/integrations/state.ts +361 -0
  354. package/src/integrations/store.ts +103 -0
  355. package/src/integrations/writer-lock.ts +98 -0
  356. package/src/integrations/writer.ts +691 -0
  357. package/src/lab/artifacts/sanitize.ts +586 -0
  358. package/src/lab/artifacts/secure-fs.ts +475 -0
  359. package/src/lab/artifacts/store.ts +310 -0
  360. package/src/lab/automation/budgets.ts +78 -0
  361. package/src/lab/automation/config-persistence.ts +256 -0
  362. package/src/lab/automation/constants.ts +39 -0
  363. package/src/lab/automation/cooldown.ts +103 -0
  364. package/src/lab/automation/dispatch.ts +211 -0
  365. package/src/lab/automation/index.ts +13 -0
  366. package/src/lab/automation/orchestrator.ts +499 -0
  367. package/src/lab/automation/persistence.ts +512 -0
  368. package/src/lab/automation/planner.ts +371 -0
  369. package/src/lab/automation/policy.ts +136 -0
  370. package/src/lab/automation/queue.ts +191 -0
  371. package/src/lab/automation/recovery.ts +24 -0
  372. package/src/lab/automation/route-context.ts +21 -0
  373. package/src/lab/automation/run-key.ts +44 -0
  374. package/src/lab/automation/runs-query.ts +34 -0
  375. package/src/lab/automation/types.ts +160 -0
  376. package/src/lab/conformance/assertion.ts +325 -0
  377. package/src/lab/conformance/digest.ts +22 -0
  378. package/src/lab/conformance/executor.ts +741 -0
  379. package/src/lab/conformance/fixture-provider.ts +27 -0
  380. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  381. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  382. package/src/lab/conformance/harness-budget.ts +47 -0
  383. package/src/lab/conformance/index.ts +5 -0
  384. package/src/lab/conformance/jcs.ts +64 -0
  385. package/src/lab/conformance/json-pointer.ts +39 -0
  386. package/src/lab/conformance/manifest.ts +180 -0
  387. package/src/lab/conformance/mcp-stub.ts +179 -0
  388. package/src/lab/conformance/negative-controls.ts +164 -0
  389. package/src/lab/conformance/observation.ts +355 -0
  390. package/src/lab/conformance/runner.ts +68 -0
  391. package/src/lab/conformance/sse-normalize.ts +59 -0
  392. package/src/lab/conformance/suite-manifest.ts +78 -0
  393. package/src/lab/conformance/types.ts +214 -0
  394. package/src/lab/constants.ts +126 -0
  395. package/src/lab/digest.ts +64 -0
  396. package/src/lab/events/errors.ts +9 -0
  397. package/src/lab/events/limits.ts +117 -0
  398. package/src/lab/events/types.ts +229 -0
  399. package/src/lab/events/validate.ts +781 -0
  400. package/src/lab/fabric/constants.ts +40 -0
  401. package/src/lab/fabric/executor.ts +492 -0
  402. package/src/lab/fabric/index.ts +80 -0
  403. package/src/lab/fabric/manifest.ts +222 -0
  404. package/src/lab/fabric/observe.ts +489 -0
  405. package/src/lab/fabric/patch.ts +79 -0
  406. package/src/lab/fabric/producer-child.ts +139 -0
  407. package/src/lab/fabric/producer-isolate.ts +276 -0
  408. package/src/lab/fabric/producer-protocol.ts +61 -0
  409. package/src/lab/fabric/scratch.ts +439 -0
  410. package/src/lab/fabric/subject.ts +106 -0
  411. package/src/lab/fabric/types.ts +134 -0
  412. package/src/lab/fabric/verifier.ts +98 -0
  413. package/src/lab/index.ts +54 -0
  414. package/src/lab/ledger/artifact-refs.ts +127 -0
  415. package/src/lab/ledger/invalidation.ts +136 -0
  416. package/src/lab/ledger/purge.ts +310 -0
  417. package/src/lab/ledger/store.ts +532 -0
  418. package/src/lab/live/credential-lease.ts +53 -0
  419. package/src/lab/live/destination.ts +155 -0
  420. package/src/lab/live/executor.ts +336 -0
  421. package/src/lab/live/inert-tools.ts +56 -0
  422. package/src/lab/live/manifest.ts +85 -0
  423. package/src/lab/live/mcp-loopback.ts +57 -0
  424. package/src/lab/live/runner.ts +19 -0
  425. package/src/lab/live/sandbox.ts +61 -0
  426. package/src/lab/live/suite-manifest.ts +41 -0
  427. package/src/lab/live/transport.ts +118 -0
  428. package/src/lab/live/types.ts +197 -0
  429. package/src/lab/observe/from-conformance.ts +301 -0
  430. package/src/lab/observe/from-live.ts +117 -0
  431. package/src/lab/paths.ts +153 -0
  432. package/src/lab/projection/rebuild.ts +495 -0
  433. package/src/lab/projection/schema.ts +135 -0
  434. package/src/lab/projection/verdicts.ts +474 -0
  435. package/src/lab/projection/verification.ts +412 -0
  436. package/src/lab/public/bundle.ts +217 -0
  437. package/src/lab/public/community-authority.ts +175 -0
  438. package/src/lab/public/community-files.ts +29 -0
  439. package/src/lab/public/community.ts +479 -0
  440. package/src/lab/public/file-safety.ts +155 -0
  441. package/src/lab/public/ids.ts +26 -0
  442. package/src/lab/public/index.ts +16 -0
  443. package/src/lab/public/mutation-lock.ts +424 -0
  444. package/src/lab/public/operator.ts +353 -0
  445. package/src/lab/public/origin-purge.ts +79 -0
  446. package/src/lab/public/origin.ts +203 -0
  447. package/src/lab/public/privacy.ts +143 -0
  448. package/src/lab/public/private-file.ts +261 -0
  449. package/src/lab/public/project.ts +124 -0
  450. package/src/lab/public/purge-test-fault.ts +21 -0
  451. package/src/lab/public/purge.ts +223 -0
  452. package/src/lab/public/registry.ts +44 -0
  453. package/src/lab/public/revocation.ts +252 -0
  454. package/src/lab/public/signature.ts +243 -0
  455. package/src/lab/public/storage.ts +105 -0
  456. package/src/lab/public/strict-json.ts +206 -0
  457. package/src/lab/public/time.ts +26 -0
  458. package/src/lab/public/types.ts +172 -0
  459. package/src/lab/public/validate.ts +391 -0
  460. package/src/lab/query/catalog.ts +101 -0
  461. package/src/lab/query/connection.ts +107 -0
  462. package/src/lab/query/constants.ts +4 -0
  463. package/src/lab/query/cursor.ts +132 -0
  464. package/src/lab/query/dto-map.ts +277 -0
  465. package/src/lab/query/errors.ts +22 -0
  466. package/src/lab/query/freshness.ts +53 -0
  467. package/src/lab/query/index.ts +45 -0
  468. package/src/lab/query/latest-observation.ts +59 -0
  469. package/src/lab/query/passive-production.ts +159 -0
  470. package/src/lab/query/queries.ts +444 -0
  471. package/src/lab/query/types.ts +266 -0
  472. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  473. package/src/lab/subject/installation-salt.ts +112 -0
  474. package/src/lab/subject/protocol-subject.ts +80 -0
  475. package/src/lab/subject/route-subject.ts +74 -0
  476. package/src/lib/abort.ts +146 -0
  477. package/src/lib/admin-secrets.ts +25 -0
  478. package/src/lib/admission.ts +83 -0
  479. package/src/lib/app-owned-memory-stores.ts +195 -0
  480. package/src/lib/app-owned-memory.ts +265 -0
  481. package/src/lib/bounded-body.ts +346 -0
  482. package/src/lib/bun-binary-validator.d.mts +3 -0
  483. package/src/lib/bun-binary-validator.mjs +18 -0
  484. package/src/lib/bun-runtime.ts +184 -0
  485. package/src/lib/bun-stream-caps.ts +130 -0
  486. package/src/lib/codex-restart-contract.ts +120 -0
  487. package/src/lib/config-ownership.ts +364 -0
  488. package/src/lib/crash-guard.ts +344 -0
  489. package/src/lib/debug-log-buffer.ts +83 -0
  490. package/src/lib/debug-settings.ts +108 -0
  491. package/src/lib/debug.ts +31 -0
  492. package/src/lib/destination-policy.ts +380 -0
  493. package/src/lib/errors.ts +406 -0
  494. package/src/lib/eventstream-decoder.ts +253 -0
  495. package/src/lib/fabric-task-execution-authority.ts +7 -0
  496. package/src/lib/fabric-task-host.ts +29 -0
  497. package/src/lib/gcp-adc.ts +341 -0
  498. package/src/lib/injection-debug-log.ts +58 -0
  499. package/src/lib/lab-activation.ts +223 -0
  500. package/src/lib/lab-live-execution-authority.ts +13 -0
  501. package/src/lib/lab-live-host.ts +30 -0
  502. package/src/lib/lab-live-pinned-sender.ts +56 -0
  503. package/src/lib/lab-live-route-production.ts +130 -0
  504. package/src/lib/lab-passive-linker-registration.ts +26 -0
  505. package/src/lib/local-management-attestation.ts +51 -0
  506. package/src/lib/local-management-capability.ts +100 -0
  507. package/src/lib/local-provider-reload-contract.ts +100 -0
  508. package/src/lib/open-url.ts +25 -0
  509. package/src/lib/optional-shutdown-hooks.ts +57 -0
  510. package/src/lib/pinned-http.ts +270 -0
  511. package/src/lib/privacy.ts +20 -0
  512. package/src/lib/process-control.ts +168 -0
  513. package/src/lib/provider-outbound.ts +210 -0
  514. package/src/lib/provider-url.ts +14 -0
  515. package/src/lib/proxy-env.ts +18 -0
  516. package/src/lib/redact.ts +521 -0
  517. package/src/lib/retry-after.ts +55 -0
  518. package/src/lib/self-launch-argv.ts +15 -0
  519. package/src/lib/server-resource-ownership.ts +71 -0
  520. package/src/lib/service-secrets.ts +25 -0
  521. package/src/lib/shadow-call.ts +61 -0
  522. package/src/lib/sidecar-tracker.ts +52 -0
  523. package/src/lib/sse-decoder.ts +364 -0
  524. package/src/lib/state-store-registrations.ts +119 -0
  525. package/src/lib/state-store-sweeper.ts +184 -0
  526. package/src/lib/system-restart-contract.ts +73 -0
  527. package/src/lib/test-home-guard.ts +90 -0
  528. package/src/lib/token-estimate.ts +86 -0
  529. package/src/lib/tool-argument-integers.ts +202 -0
  530. package/src/lib/translator-budget.ts +400 -0
  531. package/src/lib/upstream-http-version.ts +57 -0
  532. package/src/lib/upstream-reachability.ts +95 -0
  533. package/src/lib/upstream-retry.ts +392 -0
  534. package/src/lib/win-exec.ts +115 -0
  535. package/src/lib/win-paths.ts +68 -0
  536. package/src/lib/windows-atomic-replace.ts +156 -0
  537. package/src/lib/windows-elevation.ts +773 -0
  538. package/src/lib/windows-secret-acl.ts +854 -0
  539. package/src/lib/windows-service-wrappers.ts +72 -0
  540. package/src/lib/windows-text.ts +106 -0
  541. package/src/lib/windows-user-principal.ts +341 -0
  542. package/src/lib/winsw.ts +403 -0
  543. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  544. package/src/oauth/account-import/index.ts +15 -0
  545. package/src/oauth/account-import/parser.ts +83 -0
  546. package/src/oauth/account-import/registry.ts +18 -0
  547. package/src/oauth/account-import/service.ts +75 -0
  548. package/src/oauth/account-import/types.ts +91 -0
  549. package/src/oauth/anthropic-routing.ts +594 -0
  550. package/src/oauth/anthropic.ts +188 -0
  551. package/src/oauth/antigravity-routing.ts +151 -0
  552. package/src/oauth/callback-server.ts +300 -0
  553. package/src/oauth/chatgpt.ts +161 -0
  554. package/src/oauth/command-code.ts +239 -0
  555. package/src/oauth/cursor.ts +252 -0
  556. package/src/oauth/github-copilot.ts +428 -0
  557. package/src/oauth/google-antigravity.ts +262 -0
  558. package/src/oauth/health.ts +407 -0
  559. package/src/oauth/index.ts +1504 -0
  560. package/src/oauth/key-providers.ts +124 -0
  561. package/src/oauth/kimi.ts +227 -0
  562. package/src/oauth/kiro-credentials.ts +726 -0
  563. package/src/oauth/kiro.ts +621 -0
  564. package/src/oauth/local-token-detect.ts +130 -0
  565. package/src/oauth/log.ts +50 -0
  566. package/src/oauth/login-cli.ts +223 -0
  567. package/src/oauth/nous.ts +798 -0
  568. package/src/oauth/pkce.ts +15 -0
  569. package/src/oauth/store.ts +728 -0
  570. package/src/oauth/token-guardian.ts +309 -0
  571. package/src/oauth/types.ts +62 -0
  572. package/src/oauth/xai.ts +241 -0
  573. package/src/providers/alibaba-region-backup.ts +75 -0
  574. package/src/providers/alibaba-region-migration.ts +156 -0
  575. package/src/providers/alibaba-region-startup.ts +36 -0
  576. package/src/providers/antigravity-models.ts +695 -0
  577. package/src/providers/antigravity-quota.ts +216 -0
  578. package/src/providers/api-keys.ts +140 -0
  579. package/src/providers/base-url-choices.ts +74 -0
  580. package/src/providers/codex-capacity.ts +292 -0
  581. package/src/providers/command-code-efforts.ts +144 -0
  582. package/src/providers/context-cap.ts +82 -0
  583. package/src/providers/cursor-pool.ts +72 -0
  584. package/src/providers/derive.ts +586 -0
  585. package/src/providers/fastwire.ts +501 -0
  586. package/src/providers/free-directory.ts +187 -0
  587. package/src/providers/github-copilot-transport.ts +56 -0
  588. package/src/providers/google-vertex-location.ts +14 -0
  589. package/src/providers/key-failover.ts +271 -0
  590. package/src/providers/kiro-models.ts +67 -0
  591. package/src/providers/label.ts +19 -0
  592. package/src/providers/model-discovery-limits.ts +16 -0
  593. package/src/providers/model-discovery.ts +449 -0
  594. package/src/providers/model-rename-migration.ts +255 -0
  595. package/src/providers/model-rename-startup.ts +28 -0
  596. package/src/providers/openai-sidecar.ts +243 -0
  597. package/src/providers/openai-tier-startup.ts +56 -0
  598. package/src/providers/openai-tiers.ts +423 -0
  599. package/src/providers/openai-virtual-models.ts +83 -0
  600. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  601. package/src/providers/openrouter-routing.ts +102 -0
  602. package/src/providers/provider-id-rewrite.ts +185 -0
  603. package/src/providers/quota.ts +2345 -0
  604. package/src/providers/registry.ts +2918 -0
  605. package/src/providers/replit/constants.ts +27 -0
  606. package/src/providers/replit/derive.ts +85 -0
  607. package/src/providers/replit/headers.ts +28 -0
  608. package/src/providers/replit/origin.ts +55 -0
  609. package/src/providers/replit/pair-install-response.ts +72 -0
  610. package/src/providers/replit/probe.ts +199 -0
  611. package/src/providers/replit/setup.ts +350 -0
  612. package/src/providers/request-pacing.ts +310 -0
  613. package/src/providers/service-tier.ts +277 -0
  614. package/src/providers/slug-codec.ts +103 -0
  615. package/src/providers/static-model-discovery.ts +86 -0
  616. package/src/providers/xai-responses-opt-in.ts +15 -0
  617. package/src/providers/xai-transport.ts +148 -0
  618. package/src/reasoning-effort.ts +183 -0
  619. package/src/responses/compaction.ts +142 -0
  620. package/src/responses/custom-tool-compat.ts +266 -0
  621. package/src/responses/hosted-tool-policy.ts +9 -0
  622. package/src/responses/namespace-tool-compat.ts +355 -0
  623. package/src/responses/parser.ts +838 -0
  624. package/src/responses/provider-continuation.ts +98 -0
  625. package/src/responses/provider-opaque-metadata.ts +73 -0
  626. package/src/responses/reasoning-envelope.ts +60 -0
  627. package/src/responses/reasoning-replay-cache.ts +426 -0
  628. package/src/responses/schema.ts +165 -0
  629. package/src/responses/spill-store.ts +459 -0
  630. package/src/responses/state.ts +1433 -0
  631. package/src/responses/thought-signature-replay.ts +347 -0
  632. package/src/responses/tool-groups.ts +19 -0
  633. package/src/responses/tool-search-compat.ts +301 -0
  634. package/src/responses/truncated-stop-reason.ts +60 -0
  635. package/src/router.ts +761 -0
  636. package/src/routing/analytics.ts +378 -0
  637. package/src/routing/capability.ts +244 -0
  638. package/src/routing/compatibility/assemble.ts +73 -0
  639. package/src/routing/compatibility/behavior.ts +278 -0
  640. package/src/routing/compatibility/catalog.ts +99 -0
  641. package/src/routing/compatibility/endpoint.ts +52 -0
  642. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  643. package/src/routing/compatibility/policy.ts +181 -0
  644. package/src/routing/compatibility/provider-slot.ts +56 -0
  645. package/src/routing/compatibility/reader.ts +110 -0
  646. package/src/routing/compatibility/subject.ts +191 -0
  647. package/src/routing/compatibility/types.ts +64 -0
  648. package/src/routing/compatibility/version.ts +104 -0
  649. package/src/routing/cost.ts +77 -0
  650. package/src/routing/evaluator.ts +495 -0
  651. package/src/routing/health.ts +412 -0
  652. package/src/routing/history/cursor.ts +43 -0
  653. package/src/routing/history/indexer.ts +605 -0
  654. package/src/routing/history/schema.ts +72 -0
  655. package/src/routing/profile-namespace.ts +15 -0
  656. package/src/routing/profile.ts +547 -0
  657. package/src/routing/quota.ts +145 -0
  658. package/src/routing/request-evidence.ts +45 -0
  659. package/src/routing/trace.ts +776 -0
  660. package/src/server/adapter-resolve.ts +53 -0
  661. package/src/server/auth-cors.ts +751 -0
  662. package/src/server/background-lifecycle.ts +182 -0
  663. package/src/server/chat-completions.ts +442 -0
  664. package/src/server/chat-native-sse.ts +331 -0
  665. package/src/server/chat-native.ts +426 -0
  666. package/src/server/claude-messages.ts +1030 -0
  667. package/src/server/direct-local-http.ts +347 -0
  668. package/src/server/effort-policy.ts +190 -0
  669. package/src/server/github-copilot-responses-repair.ts +338 -0
  670. package/src/server/gui-static.ts +152 -0
  671. package/src/server/image-retry.ts +42 -0
  672. package/src/server/images.ts +568 -0
  673. package/src/server/index.ts +1813 -0
  674. package/src/server/lifecycle.ts +498 -0
  675. package/src/server/live.ts +717 -0
  676. package/src/server/local-management-read-client.ts +90 -0
  677. package/src/server/local-provider-reload-client.ts +137 -0
  678. package/src/server/management/agent-settings-routes.ts +1433 -0
  679. package/src/server/management/api-access.ts +141 -0
  680. package/src/server/management/api-key-usage.ts +193 -0
  681. package/src/server/management/body.ts +41 -0
  682. package/src/server/management/combo-routes.ts +263 -0
  683. package/src/server/management/config-routes.ts +835 -0
  684. package/src/server/management/context.ts +113 -0
  685. package/src/server/management/integration-routes.ts +498 -0
  686. package/src/server/management/lab-automation-routes.ts +206 -0
  687. package/src/server/management/lab-routes.ts +563 -0
  688. package/src/server/management/logs-usage-routes.ts +586 -0
  689. package/src/server/management/model-routes.ts +560 -0
  690. package/src/server/management/model-rows.ts +163 -0
  691. package/src/server/management/native-integration-routes.ts +769 -0
  692. package/src/server/management/oauth-account-routes.ts +637 -0
  693. package/src/server/management/provider-capability-config.ts +48 -0
  694. package/src/server/management/provider-routes.ts +1033 -0
  695. package/src/server/management/replit-provider-routes.ts +86 -0
  696. package/src/server/management/request-history-routes.ts +191 -0
  697. package/src/server/management/routing-analytics-routes.ts +74 -0
  698. package/src/server/management/routing-profile-routes.ts +385 -0
  699. package/src/server/management/shared.ts +286 -0
  700. package/src/server/management/sidebar-routes.ts +106 -0
  701. package/src/server/management/storage-log-guard-routes.ts +186 -0
  702. package/src/server/management/sync-response.ts +69 -0
  703. package/src/server/management/system-restart.ts +435 -0
  704. package/src/server/management/system-routes.ts +194 -0
  705. package/src/server/management/usage-summary-cache.ts +94 -0
  706. package/src/server/management/vision-sidecar-options.ts +167 -0
  707. package/src/server/management/web-search-sidecar-options.ts +120 -0
  708. package/src/server/management-api.ts +314 -0
  709. package/src/server/management-auth.ts +482 -0
  710. package/src/server/memory-watchdog.ts +156 -0
  711. package/src/server/passive-route-linker.ts +66 -0
  712. package/src/server/port-reclaim.ts +307 -0
  713. package/src/server/ports.ts +156 -0
  714. package/src/server/proxy-liveness.ts +328 -0
  715. package/src/server/readiness.ts +99 -0
  716. package/src/server/relay-eager.ts +353 -0
  717. package/src/server/relay.ts +1209 -0
  718. package/src/server/request-decompress.ts +239 -0
  719. package/src/server/request-log-conversation.ts +168 -0
  720. package/src/server/request-log.ts +1259 -0
  721. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  722. package/src/server/responses/agent-task-recovery.ts +465 -0
  723. package/src/server/responses/collaboration.ts +551 -0
  724. package/src/server/responses/compact.ts +771 -0
  725. package/src/server/responses/core.ts +5389 -0
  726. package/src/server/responses/empty-completion-guard.ts +276 -0
  727. package/src/server/responses/encrypted-payload.ts +331 -0
  728. package/src/server/responses/fetch-helpers.ts +232 -0
  729. package/src/server/responses/input-admission.ts +185 -0
  730. package/src/server/responses/pacing-overload.ts +13 -0
  731. package/src/server/responses/passthrough-error.ts +78 -0
  732. package/src/server/responses/policy-fallback.ts +178 -0
  733. package/src/server/responses/responses-field-backfill.ts +251 -0
  734. package/src/server/responses/terminal-guard.ts +251 -0
  735. package/src/server/responses/upstream-error.ts +53 -0
  736. package/src/server/responses/ws-upstream.ts +308 -0
  737. package/src/server/responses-custom-tool-repair.ts +282 -0
  738. package/src/server/responses-image-gen-repair.ts +132 -0
  739. package/src/server/responses-item-id-repair.ts +272 -0
  740. package/src/server/responses-json-events.ts +90 -0
  741. package/src/server/responses-model-rewrite.ts +29 -0
  742. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  743. package/src/server/responses-snapshot-repair.ts +621 -0
  744. package/src/server/responses-terminal-repair.ts +342 -0
  745. package/src/server/responses-tool-search-repair.ts +267 -0
  746. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  747. package/src/server/responses.ts +25 -0
  748. package/src/server/search.ts +201 -0
  749. package/src/server/sse-frame-buffer.ts +292 -0
  750. package/src/server/sse-payload-rewrite.ts +263 -0
  751. package/src/server/startup-action-control.ts +315 -0
  752. package/src/server/startup-health-cache.ts +131 -0
  753. package/src/server/system-env.ts +484 -0
  754. package/src/server/windows-tcp-drop.ts +184 -0
  755. package/src/server/windows-tray-control.ts +41 -0
  756. package/src/server/ws-bridge.ts +472 -0
  757. package/src/service-manager-probe.ts +892 -0
  758. package/src/service.ts +3575 -0
  759. package/src/sidecar/auth.ts +92 -0
  760. package/src/sidecar/candidates.ts +83 -0
  761. package/src/stall-timeout.ts +20 -0
  762. package/src/storage/cleanup-job.ts +57 -0
  763. package/src/storage/cleanup.ts +3085 -0
  764. package/src/storage/policy-job.ts +457 -0
  765. package/src/storage/policy-scheduler.ts +40 -0
  766. package/src/storage/policy-worker.ts +59 -0
  767. package/src/storage/policy.ts +527 -0
  768. package/src/storage/restore-job.ts +299 -0
  769. package/src/storage/restore-worker.ts +58 -0
  770. package/src/storage/scanner.ts +238 -0
  771. package/src/storage/storage-mutation-coordinator.ts +139 -0
  772. package/src/storage/worker-lifecycle.ts +215 -0
  773. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  774. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  775. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  776. package/src/tray/assets/opencodex-tray.png +0 -0
  777. package/src/tray/windows-tray.ps1 +364 -0
  778. package/src/tray/windows.ts +757 -0
  779. package/src/types/accounts.ts +37 -0
  780. package/src/types/config.ts +876 -0
  781. package/src/types/provider.ts +545 -0
  782. package/src/types/request.ts +384 -0
  783. package/src/types/tools.ts +131 -0
  784. package/src/types/wire.ts +80 -0
  785. package/src/types.ts +106 -0
  786. package/src/update/badge.ts +72 -0
  787. package/src/update/index.ts +415 -0
  788. package/src/update/job.ts +1887 -0
  789. package/src/update/notify.ts +263 -0
  790. package/src/update/npm-cache-preflight.d.mts +47 -0
  791. package/src/update/npm-cache-preflight.mjs +201 -0
  792. package/src/update/npm-invocation.d.mts +23 -0
  793. package/src/update/npm-invocation.mjs +94 -0
  794. package/src/update/transactional-install.d.mts +22 -0
  795. package/src/update/transactional-install.mjs +259 -0
  796. package/src/update/tray-update-plan.d.mts +18 -0
  797. package/src/update/tray-update-plan.mjs +38 -0
  798. package/src/usage/cost.ts +625 -0
  799. package/src/usage/debug.ts +97 -0
  800. package/src/usage/expected-prices.ts +416 -0
  801. package/src/usage/log.ts +1223 -0
  802. package/src/usage/summary.ts +753 -0
  803. package/src/usage/totals.ts +14 -0
  804. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  805. package/src/usage/user-cost-overlays.ts +314 -0
  806. package/src/vision/anthropic-describe.ts +189 -0
  807. package/src/vision/backends.ts +97 -0
  808. package/src/vision/describe.ts +131 -0
  809. package/src/vision/eligibility.ts +250 -0
  810. package/src/vision/index.ts +681 -0
  811. package/src/vision/reasoning.ts +55 -0
  812. package/src/vision/routed-describe.ts +175 -0
  813. package/src/vision/timeout-bounds.ts +9 -0
  814. package/src/web-search/anthropic-executor.ts +195 -0
  815. package/src/web-search/backends.ts +108 -0
  816. package/src/web-search/exa-executor.ts +88 -0
  817. package/src/web-search/executor.ts +113 -0
  818. package/src/web-search/format-result.ts +89 -0
  819. package/src/web-search/gemini-executor.ts +141 -0
  820. package/src/web-search/index.ts +331 -0
  821. package/src/web-search/loop.ts +896 -0
  822. package/src/web-search/parse.ts +315 -0
  823. package/src/web-search/progress-stream.ts +342 -0
  824. package/src/web-search/sources.ts +60 -0
  825. package/src/web-search/synthetic-tool.ts +47 -0
  826. package/src/web-search/xai-executor.ts +219 -0
@@ -0,0 +1,403 @@
1
+ /**
2
+ * WinSW-backed native Windows service (opt-in via `ocx service install --native`).
3
+ *
4
+ * Design (devlog/_plan/260720_windows_service/060):
5
+ * - WinSW 2.12.0 NET461 build, downloaded on first native install and verified against
6
+ * a pinned SHA-256 (fail-closed: mismatch deletes the file and throws). The binary is
7
+ * NOT bundled in npm; offline installs get an explicit manual-placement hint.
8
+ * - Runs as the USER account (v2 `<serviceaccount>` domain/user/allowservicelogon —
9
+ * never LocalSystem: the ACL hardening in windows-secret-acl grants only the user SID,
10
+ * so a SYSTEM service could not read the token file, and SYSTEM-owned writes would
11
+ * change the user-access contract).
12
+ * - No password in XML: `winsw install /p` prompts on the console (stdin inherit).
13
+ * - Absolute paths only — no %USERPROFILE% indirection (that exists for OEM-codepage
14
+ * batch parsing; WinSW XML is Unicode).
15
+ */
16
+ import { createHash } from "node:crypto";
17
+ import { execFileSync } from "node:child_process";
18
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
19
+ import { homedir } from "node:os";
20
+ import { join, resolve, win32 } from "node:path";
21
+ import { expandUserPath, getConfigDir, loadConfig } from "../config";
22
+ import { recordOwnedConfigPath } from "./config-ownership";
23
+ import { BUN_RUNTIME_PATH_ENV, BUN_RUNTIME_SOURCE_ENV, durableBunRuntime } from "./bun-runtime";
24
+ import type { BunRuntimeSource } from "./bun-runtime";
25
+ import { serviceApiTokenFilePath } from "./service-secrets";
26
+
27
+ export const WINSW_VERSION = "2.12.0";
28
+ export const WINSW_URL = `https://github.com/winsw/winsw/releases/download/v${WINSW_VERSION}/WinSW.NET461.exe`;
29
+ /** SHA-256 of the official v2.12.0 WinSW.NET461.exe release asset (655872 bytes). */
30
+ export const WINSW_SHA256 = "b5066b7bbdfba1293e5d15cda3caaea88fbeab35bd5b38c41c913d492aadfc4f";
31
+
32
+ /** SCM service id — distinct from the Task Scheduler task name (opencodex-proxy). */
33
+ export const WINSW_SERVICE_ID = "opencodex-proxy-native";
34
+
35
+ export function winswDir(): string {
36
+ return join(getConfigDir(), "winsw");
37
+ }
38
+
39
+ /** WinSW discovers its config as the same-basename XML next to the exe. */
40
+ export function winswExePath(): string {
41
+ return join(winswDir(), `${WINSW_SERVICE_ID}.exe`);
42
+ }
43
+
44
+ export function winswXmlPath(): string {
45
+ return join(winswDir(), `${WINSW_SERVICE_ID}.xml`);
46
+ }
47
+
48
+ function winswLogDir(): string {
49
+ return getConfigDir();
50
+ }
51
+
52
+ function xmlEscape(value: string): string {
53
+ return value
54
+ .replace(/&/g, "&amp;")
55
+ .replace(/</g, "&lt;")
56
+ .replace(/>/g, "&gt;")
57
+ .replace(/"/g, "&quot;")
58
+ .replace(/'/g, "&apos;");
59
+ }
60
+
61
+ function currentCodexHomeAbsolute(): string {
62
+ const raw = process.env.CODEX_HOME?.trim();
63
+ return raw ? resolve(expandUserPath(raw)) : join(homedir(), ".codex");
64
+ }
65
+
66
+ function windowsServicePathAbsolute(raw: string): string {
67
+ const expanded = expandUserPath(raw);
68
+ return win32.isAbsolute(expanded) ? win32.normalize(expanded) : resolve(expanded);
69
+ }
70
+
71
+ export interface WinswEntry {
72
+ bun: string;
73
+ /** Provenance of `bun`, resolved together with it so the two can never disagree. */
74
+ bunRuntimeSource: BunRuntimeSource;
75
+ cli: string;
76
+ }
77
+
78
+ /**
79
+ * Build the WinSW v2 XML. Never embeds the API token value — the app loads it from
80
+ * OCX_API_TOKEN_FILE at startup (cli handleStart). PATH is baked for parity with the
81
+ * Task Scheduler wrapper / launchd / systemd: the SCM service environment lacks the
82
+ * user's interactive PATH, which provider subprocesses may need.
83
+ */
84
+ export function buildWinswXml(entry: WinswEntry, env: NodeJS.ProcessEnv = process.env, port?: number): string {
85
+ const domain = env.USERDOMAIN?.trim() || ".";
86
+ const user = env.USERNAME?.trim() || "";
87
+ const listenPort = (() => {
88
+ if (typeof port === "number" && Number.isFinite(port) && port > 0 && port <= 65535) return Math.trunc(port);
89
+ const baked = env.OCX_BAKE_PORT?.trim();
90
+ if (baked && /^\d+$/.test(baked)) {
91
+ const n = Number(baked);
92
+ if (n > 0 && n <= 65535) return n;
93
+ }
94
+ return loadConfig().port ?? 10100;
95
+ })();
96
+ // Services never bake `--port 0` (parsePortOption rejects it); treat as default.
97
+ const safeListenPort = listenPort > 0 && listenPort <= 65535 ? listenPort : 10100;
98
+ // SCM services do not inherit the interactive user environment (#764). Bake:
99
+ // - OPENCODEX_HOME so file-backed admin auth (`admin-api-token`) resolves
100
+ // - OPENCODEX_ACL_TIMEOUT_MS when set (not a secret)
101
+ // Never embed OPENCODEX_ADMIN_AUTH_TOKEN or OPENCODEX_API_AUTH_TOKEN values in XML —
102
+ // those stay file-pointer / generated-file only (uninstall retains the XML).
103
+ const aclTimeout = env.OPENCODEX_ACL_TIMEOUT_MS?.trim();
104
+ const envLines = [
105
+ ` <env name="OCX_SERVICE" value="1"/>`,
106
+ ` <env name="${BUN_RUNTIME_SOURCE_ENV}" value="${xmlEscape(entry.bunRuntimeSource)}"/>`,
107
+ ` <env name="${BUN_RUNTIME_PATH_ENV}" value="${xmlEscape(entry.bun)}"/>`,
108
+ ` <env name="OCX_API_TOKEN_FILE" value="${xmlEscape(serviceApiTokenFilePath())}"/>`,
109
+ ` <env name="PATH" value="${xmlEscape(env.PATH ?? "")}"/>`,
110
+ env.CODEX_HOME?.trim() ? ` <env name="CODEX_HOME" value="${xmlEscape(currentCodexHomeAbsolute())}"/>` : null,
111
+ env.CODEX_SQLITE_HOME?.trim() ? ` <env name="CODEX_SQLITE_HOME" value="${xmlEscape(windowsServicePathAbsolute(env.CODEX_SQLITE_HOME.trim()))}"/>` : null,
112
+ ` <env name="OPENCODEX_HOME" value="${xmlEscape(getConfigDir())}"/>`,
113
+ aclTimeout ? ` <env name="OPENCODEX_ACL_TIMEOUT_MS" value="${xmlEscape(aclTimeout)}"/>` : null,
114
+ ].filter((line): line is string => Boolean(line));
115
+ return `<?xml version="1.0" encoding="UTF-8"?>
116
+ <service>
117
+ <id>${WINSW_SERVICE_ID}</id>
118
+ <name>OpenCodex Proxy (native)</name>
119
+ <description>OpenCodex proxy running as a native Windows service (windowless, starts at boot).</description>
120
+ <executable>${xmlEscape(entry.bun)}</executable>
121
+ <arguments>${xmlEscape(`"${entry.cli}" start --port ${safeListenPort}`)}</arguments>
122
+ ${envLines.join("\n")}
123
+ <logpath>${xmlEscape(winswLogDir())}</logpath>
124
+ <log mode="roll-by-size">
125
+ <sizeThreshold>10240</sizeThreshold>
126
+ <keepFiles>4</keepFiles>
127
+ </log>
128
+ <onfailure action="restart" delay="5 sec"/>
129
+ <stoptimeout>20 sec</stoptimeout>
130
+ <serviceaccount>
131
+ <domain>${xmlEscape(domain)}</domain>
132
+ <user>${xmlEscape(user)}</user>
133
+ <allowservicelogon>true</allowservicelogon>
134
+ </serviceaccount>
135
+ </service>
136
+ `;
137
+ }
138
+
139
+ export function sha256Hex(data: Uint8Array | Buffer): string {
140
+ return createHash("sha256").update(data).digest("hex");
141
+ }
142
+
143
+ /**
144
+ * Ensure the pinned WinSW binary exists locally; download + verify on first use.
145
+ * Fail-closed: any hash mismatch deletes the file and throws.
146
+ */
147
+ export async function ensureWinswBinary(fetchImpl: typeof fetch = fetch): Promise<string> {
148
+ const exe = winswExePath();
149
+ if (existsSync(exe)) {
150
+ const digest = sha256Hex(readFileSync(exe));
151
+ if (digest === WINSW_SHA256) return exe;
152
+ unlinkSync(exe);
153
+ console.warn("⚠️ Existing WinSW binary failed hash verification; re-downloading.");
154
+ }
155
+ recordOwnedConfigPath(getConfigDir(), winswDir());
156
+ if (!existsSync(winswDir())) mkdirSync(winswDir(), { recursive: true });
157
+ let body: ArrayBuffer;
158
+ try {
159
+ const res = await fetchImpl(WINSW_URL);
160
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
161
+ body = await res.arrayBuffer();
162
+ } catch (err) {
163
+ throw new Error(
164
+ `Failed to download WinSW ${WINSW_VERSION} (${err instanceof Error ? err.message : String(err)}). ` +
165
+ `Offline? Place the official WinSW.NET461.exe (v${WINSW_VERSION}) at ${exe} and retry.`,
166
+ );
167
+ }
168
+ const bytes = Buffer.from(body);
169
+ const digest = sha256Hex(bytes);
170
+ if (digest !== WINSW_SHA256) {
171
+ throw new Error(
172
+ `WinSW download failed SHA-256 verification (got ${digest}, expected ${WINSW_SHA256}). ` +
173
+ "Refusing to install an unverified service binary.",
174
+ );
175
+ }
176
+ writeFileSync(exe, bytes);
177
+ return exe;
178
+ }
179
+
180
+ function runWinsw(args: string[]): string {
181
+ return execFileSync(winswExePath(), args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true }).trim();
182
+ }
183
+
184
+ /** `install /p` prompts for the service-account password on the console — stdin must be inherited. */
185
+ function runWinswInteractive(args: string[]): void {
186
+ if (!process.stdin.isTTY) {
187
+ throw new Error(
188
+ "WinSW install requires an interactive console to prompt for the service account password. "
189
+ + "Run `ocx service install --native` from an elevated Command Prompt or PowerShell window, not a hidden or piped session.",
190
+ );
191
+ }
192
+ execFileSync(winswExePath(), args, { stdio: "inherit" });
193
+ }
194
+
195
+ function scQc(): string {
196
+ const sc = join(process.env.SystemRoot ?? "C:\\Windows", "System32", "sc.exe");
197
+ return execFileSync(existsSync(sc) ? sc : "sc.exe", ["qc", WINSW_SERVICE_ID], {
198
+ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true,
199
+ });
200
+ }
201
+
202
+ export type WinswStatus = "started" | "stopped" | "nonexistent" | "unknown";
203
+
204
+ /** WinSW v2 `status` prints exactly Started / Stopped / NonExistent. */
205
+ export function parseWinswStatus(output: string): WinswStatus {
206
+ const normalized = output.trim().toLowerCase();
207
+ if (normalized.includes("nonexistent")) return "nonexistent";
208
+ if (normalized.includes("started")) return "started";
209
+ if (normalized.includes("stopped")) return "stopped";
210
+ // Anything else is an unparseable result — NOT proof of absence. Callers must
211
+ // fail closed: only an exact NonExistent may skip stop/uninstall.
212
+ return "unknown";
213
+ }
214
+
215
+ export function statusWinswRaw(): WinswStatus {
216
+ if (existsSync(winswExePath())) {
217
+ try {
218
+ return parseWinswStatus(runWinsw(["status"]));
219
+ } catch {
220
+ // The query itself failed (access denied, damaged/quarantined exe, ...). Treat the
221
+ // service as possibly-installed so lifecycle operations still attempt stop/uninstall
222
+ // instead of skipping a live SCM service that would keep respawning the proxy.
223
+ return "unknown";
224
+ }
225
+ }
226
+ // A missing exe does NOT prove the SCM registration is gone (quarantined binary,
227
+ // partial uninstall): a stale opencodex-proxy-native registration can outlive it.
228
+ // Confirm absence against the SCM itself before reporting "nonexistent".
229
+ if (process.platform !== "win32") return "nonexistent";
230
+ const probe = probeScmRegistration();
231
+ // probe === "error": the SCM could not be queried — fail closed, never claim absence.
232
+ return probe === false ? "nonexistent" : "unknown";
233
+ }
234
+
235
+ /**
236
+ * Probe the SCM for the native service registration.
237
+ * Returns true (registered), false (confirmed absent — exit 1060 only), or "error"
238
+ * (query itself failed: access denied, sc.exe missing, ...). Only a confirmed
239
+ * ERROR_SERVICE_DOES_NOT_EXIST may prove absence to lifecycle callers.
240
+ */
241
+ export function probeScmRegistration(run: () => string = queryScmForService): boolean | "error" {
242
+ try {
243
+ run();
244
+ return true;
245
+ } catch (err) {
246
+ const e = err as { status?: number | null; stderr?: string | Buffer | null; stdout?: string | Buffer | null; message?: string };
247
+ // sc.exe does not reliably channel the 1060 line — it can land on stderr OR stdout
248
+ // depending on the host — so scan every captured stream and the error message.
249
+ const text = [e.stderr, e.stdout, e.message]
250
+ .map(v => (typeof v === "string" ? v : ""))
251
+ .join("\n");
252
+ // ERROR_SERVICE_DOES_NOT_EXIST: the numeric identifier 1060 is locale-invariant
253
+ // (FALHA 1060 pt-BR, localized ko output, English FAILED 1060). The query is a
254
+ // fixed `sc.exe query <service>` so a standalone 1060 in its output is proof of
255
+ // absence. Bun may deliver e.status as 36 (1060 & 0xff) — status 36 ALONE is
256
+ // NOT accepted (collides with any status ≡ 36 mod 256); the textual 1060 is
257
+ // required corroboration and covers those hosts.
258
+ if (e.status === 1060 || /\b1060\b/.test(text)) return false;
259
+ return "error";
260
+ }
261
+ }
262
+
263
+ function scExePath(): string {
264
+ const sc = join(process.env.SystemRoot ?? "C:\\Windows", "System32", "sc.exe");
265
+ return existsSync(sc) ? sc : "sc.exe";
266
+ }
267
+
268
+ function queryScmForService(): string {
269
+ return execFileSync(scExePath(), ["query", WINSW_SERVICE_ID], {
270
+ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true,
271
+ });
272
+ }
273
+
274
+ /**
275
+ * Verify the installed SCM service runs as the intended user, not LocalSystem (WinSW's
276
+ * default when the XML account section is ignored/malformed). Rolls back on mismatch.
277
+ */
278
+ function assertServiceAccountApplied(env: NodeJS.ProcessEnv = process.env): void {
279
+ const qc = scQc();
280
+ const startName = /SERVICE_START_NAME\s*:\s*(.+)/i.exec(qc)?.[1]?.trim() ?? "";
281
+ const user = env.USERNAME?.trim() ?? "";
282
+ if (/localsystem/i.test(startName) || (user && !startName.toLowerCase().includes(user.toLowerCase()))) {
283
+ try { runWinsw(["uninstall"]); } catch { /* rollback is best-effort */ }
284
+ throw new Error(
285
+ `Native service was registered as "${startName || "unknown"}" instead of the current user; ` +
286
+ "rolled back. Re-run `ocx service install --native` and enter the account credentials when prompted.",
287
+ );
288
+ }
289
+ }
290
+
291
+ export interface WinswInstallDeps {
292
+ ensureBinary?: () => Promise<string>;
293
+ writeXml?: (path: string, content: string) => void;
294
+ interactive?: (args: string[]) => void;
295
+ run?: (args: string[]) => string;
296
+ verifyAccount?: () => void;
297
+ status?: () => WinswStatus;
298
+ }
299
+
300
+ /**
301
+ * Install (or repair) the native service. Re-running against an existing service skips
302
+ * `install /p` — assets are rewritten and the service restarted without re-prompting
303
+ * credentials (WinSW `install` fails with "service already exists").
304
+ */
305
+ export async function installWinswService(entry: WinswEntry, deps: WinswInstallDeps = {}): Promise<void> {
306
+ const ensureBinary = deps.ensureBinary ?? ensureWinswBinary;
307
+ const writeXml = deps.writeXml ?? ((path: string, content: string) => writeFileSync(path, content, "utf8"));
308
+ const interactive = deps.interactive ?? runWinswInteractive;
309
+ const run = deps.run ?? runWinsw;
310
+ const verifyAccount = deps.verifyAccount ?? assertServiceAccountApplied;
311
+ const status = deps.status ?? statusWinswRaw;
312
+
313
+ await ensureBinary();
314
+ writeXml(winswXmlPath(), buildWinswXml(entry));
315
+ const existing = status();
316
+ if (existing === "unknown") {
317
+ throw new Error(
318
+ "Could not query the native service state (WinSW status failed or returned an unexpected result). " +
319
+ "Refusing to guess the install state — check 'ocx service status' and retry.",
320
+ );
321
+ }
322
+ if (existing === "nonexistent") {
323
+ // WinSW self-elevates via UAC; a refused prompt aborts install (no silent fallback).
324
+ // v2.12 recognizes prompting only as args[1]: `install /p` (XML is auto-discovered
325
+ // as the same-basename file next to the exe).
326
+ interactive(["install", "/p"]);
327
+ verifyAccount();
328
+ } else {
329
+ // Use `stopwait` (not `stop`) so the SCM service fully stops before `start` — bare
330
+ // `stop` only sends the stop request; `start` against a STOP_PENDING service fails.
331
+ try { run(["stopwait"]); } catch { /* already stopped */ }
332
+ }
333
+ run(["start"]);
334
+ }
335
+
336
+ export function startWinswService(): void { runWinsw(["start"]); }
337
+
338
+ /**
339
+ * Stop the native service and prove it is no longer running. `stopwait` can fail both
340
+ * for the benign already-stopped case and for real access/timeout failures, so a bare
341
+ * catch cannot decide whether it is safe for lifecycle callers to continue. Re-read
342
+ * SCM state and only accept the two states that cannot still own the proxy listener.
343
+ */
344
+ export function stopWinswService(): void {
345
+ try { runWinsw(["stopwait"]); } catch { /* classify by verified state below */ }
346
+ const status = statusWinswRaw();
347
+ if (status === "stopped" || status === "nonexistent") return;
348
+ if (status === "unknown") {
349
+ throw new Error("Native service stop could not be verified.");
350
+ }
351
+ throw new Error("Native service is still running after stop.");
352
+ }
353
+
354
+ export function uninstallWinswService(): void {
355
+ if (!existsSync(winswExePath())) {
356
+ // The binary is gone but the SCM registration can outlive it (quarantine, partial
357
+ // uninstall). WinSW can't run without its exe, so remove the stale registration
358
+ // directly via sc.exe — otherwise the SCM service survives every cleanup path.
359
+ if (process.platform === "win32") {
360
+ const probe = probeScmRegistration();
361
+ if (probe === "error") {
362
+ // Presence unknown — fail closed: keep service state, surface the failure
363
+ // instead of reporting a clean uninstall over a possibly-live registration.
364
+ throw new Error(
365
+ `Cannot verify the native service registration (sc.exe query failed). ` +
366
+ `Uninstall aborted; check 'sc query ${WINSW_SERVICE_ID}' and retry.`,
367
+ );
368
+ }
369
+ if (probe === true) {
370
+ try {
371
+ execFileSync(scExePath(), ["stop", WINSW_SERVICE_ID], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
372
+ } catch { /* not running */ }
373
+ execFileSync(scExePath(), ["delete", WINSW_SERVICE_ID], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
374
+ }
375
+ }
376
+ return;
377
+ }
378
+ try { runWinsw(["stopwait"]); } catch { /* not running */ }
379
+ try { runWinsw(["uninstall"]); } catch (err) {
380
+ // Surface the failure so the caller can decide; silent swallow hides UAC refusals.
381
+ const msg = err instanceof Error ? err.message : String(err);
382
+ if (!msg.toLowerCase().includes("nonexistent")) throw new Error(`WinSW uninstall failed: ${msg}`);
383
+ // "NonExistent" means already absent — that's fine.
384
+ }
385
+ // exe/xml intentionally retained for credential-free reinstall; `--purge` is out of scope.
386
+ }
387
+
388
+ export function winswStatusSummary(): string {
389
+ const status = statusWinswRaw();
390
+ if (status === "nonexistent") {
391
+ // A stale SCM service can outlive a deleted exe; surface the repair path.
392
+ return existsSync(winswXmlPath()) && !existsSync(winswExePath())
393
+ ? "native assets present but WinSW binary missing — run 'ocx service repair'"
394
+ : "";
395
+ }
396
+ return `native (WinSW ${WINSW_VERSION}): ${status}`;
397
+ }
398
+
399
+ /** Default entry mirrors the Task Scheduler baking: durable Bun + cli.ts. */
400
+ export function defaultWinswEntry(cliDir: string): WinswEntry {
401
+ const runtime = durableBunRuntime();
402
+ return { bun: runtime.path, bunRuntimeSource: runtime.source, cli: join(cliDir, "cli", "index.ts") };
403
+ }
@@ -0,0 +1,74 @@
1
+ import { validateAntigravityImportCredential } from "../google-antigravity";
2
+ import { upsertCredentialByIdentity } from "../store";
3
+ import type { OAuthCredentials } from "../types";
4
+ import {
5
+ ACCOUNT_IMPORT_FORMAT,
6
+ ACCOUNT_IMPORT_MAX_EMAIL_LENGTH,
7
+ ACCOUNT_IMPORT_PROVIDER,
8
+ throwIfAccountImportAborted,
9
+ type AccountImportAdapter,
10
+ type CockpitAccountRecord,
11
+ type ValidatedAntigravityCredential,
12
+ } from "./types";
13
+
14
+ export interface AntigravityImportAdapterDeps {
15
+ validate(refreshToken: string, signal?: AbortSignal): Promise<ValidatedAntigravityCredential>;
16
+ upsert(credential: OAuthCredentials): Promise<"inserted" | "updated">;
17
+ }
18
+
19
+ function safeProviderEmail(value: unknown): string | null {
20
+ if (typeof value !== "string") return null;
21
+ const normalized = value.toLowerCase();
22
+ if (
23
+ normalized.length === 0
24
+ || normalized.length > ACCOUNT_IMPORT_MAX_EMAIL_LENGTH
25
+ || normalized !== normalized.trim()
26
+ || /[\x00-\x20\x7f]/.test(normalized)
27
+ ) return null;
28
+ return normalized;
29
+ }
30
+
31
+ export function createAntigravityAccountImportAdapter(
32
+ deps: AntigravityImportAdapterDeps = {
33
+ validate: validateAntigravityImportCredential,
34
+ upsert: credential => upsertCredentialByIdentity(ACCOUNT_IMPORT_PROVIDER, credential),
35
+ },
36
+ ): AccountImportAdapter {
37
+ return {
38
+ provider: ACCOUNT_IMPORT_PROVIDER,
39
+ format: ACCOUNT_IMPORT_FORMAT,
40
+ async importRecord(record: CockpitAccountRecord, signal?: AbortSignal) {
41
+ throwIfAccountImportAborted(signal);
42
+ let credential: ValidatedAntigravityCredential;
43
+ try {
44
+ credential = await deps.validate(record.refreshToken, signal);
45
+ } catch {
46
+ throwIfAccountImportAborted(signal);
47
+ return { status: "failed", code: "credential_rejected" };
48
+ }
49
+
50
+ throwIfAccountImportAborted(signal);
51
+
52
+ const providerEmail = safeProviderEmail(credential.email);
53
+ if (!providerEmail) return { status: "failed", code: "credential_rejected" };
54
+ if (providerEmail !== record.email) return { status: "failed", code: "identity_mismatch" };
55
+ if (typeof credential.projectId !== "string" || credential.projectId.length === 0) {
56
+ return { status: "failed", code: "missing_project" };
57
+ }
58
+
59
+ throwIfAccountImportAborted(signal);
60
+ try {
61
+ const disposition = await deps.upsert({
62
+ ...credential,
63
+ email: providerEmail,
64
+ source: "credential-file",
65
+ });
66
+ return disposition === "updated"
67
+ ? { status: "updated", code: "updated" }
68
+ : { status: "imported", code: "imported" };
69
+ } catch {
70
+ return { status: "failed", code: "persist_failed" };
71
+ }
72
+ },
73
+ };
74
+ }
@@ -0,0 +1,15 @@
1
+ export { importAccounts } from "./service";
2
+ export {
3
+ ACCOUNT_IMPORT_DEADLINE_MS,
4
+ ACCOUNT_IMPORT_FORMAT,
5
+ ACCOUNT_IMPORT_MAX_BYTES,
6
+ ACCOUNT_IMPORT_MAX_REQUEST_BYTES,
7
+ ACCOUNT_IMPORT_PROVIDER,
8
+ } from "./types";
9
+ export type {
10
+ AccountImportCode,
11
+ AccountImportRecordResult,
12
+ AccountImportRequest,
13
+ AccountImportResult,
14
+ AccountImportStatus,
15
+ } from "./types";
@@ -0,0 +1,83 @@
1
+ import {
2
+ ACCOUNT_IMPORT_MAX_BYTES,
3
+ ACCOUNT_IMPORT_MAX_EMAIL_LENGTH,
4
+ ACCOUNT_IMPORT_MAX_RECORDS,
5
+ ACCOUNT_IMPORT_MAX_REFRESH_TOKEN_BYTES,
6
+ type ParsedCockpitRecord,
7
+ } from "./types";
8
+
9
+ const encoder = new TextEncoder();
10
+ const ALLOWED_RECORD_KEYS = new Set(["email", "refresh_token", "tags", "notes"]);
11
+
12
+ export type CockpitDocumentParseResult =
13
+ | { ok: true; records: ParsedCockpitRecord[] }
14
+ | { ok: false; code: "invalid_document" };
15
+
16
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
17
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
18
+ const prototype = Object.getPrototypeOf(value);
19
+ return prototype === Object.prototype || prototype === null;
20
+ }
21
+
22
+ function serializedDocumentSize(document: unknown): number | null {
23
+ try {
24
+ const serialized = JSON.stringify(document);
25
+ return serialized === undefined ? null : encoder.encode(serialized).byteLength;
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+
31
+ function validEmail(value: unknown): value is string {
32
+ if (typeof value !== "string" || value.length === 0 || value.length > ACCOUNT_IMPORT_MAX_EMAIL_LENGTH) return false;
33
+ if (value !== value.trim() || /[\x00-\x20\x7f]/.test(value)) return false;
34
+ const at = value.indexOf("@");
35
+ return at > 0 && at === value.lastIndexOf("@") && at < value.length - 1;
36
+ }
37
+
38
+ function validRefreshToken(value: unknown): value is string {
39
+ return typeof value === "string"
40
+ && value.length > 0
41
+ && encoder.encode(value).byteLength <= ACCOUNT_IMPORT_MAX_REFRESH_TOKEN_BYTES
42
+ && !/[\s\x7f]/.test(value);
43
+ }
44
+
45
+ function validMetadata(record: Record<string, unknown>): boolean {
46
+ if (record.tags !== undefined && (
47
+ !Array.isArray(record.tags)
48
+ || record.tags.some(tag => typeof tag !== "string")
49
+ )) return false;
50
+ return record.notes === undefined || typeof record.notes === "string";
51
+ }
52
+
53
+ function parseRecord(value: unknown, index: number): ParsedCockpitRecord {
54
+ if (!isPlainRecord(value)) return { index, code: "invalid_record" };
55
+ if (Object.keys(value).some(key => !ALLOWED_RECORD_KEYS.has(key))) return { index, code: "invalid_record" };
56
+ if (!validEmail(value.email) || !validRefreshToken(value.refresh_token) || !validMetadata(value)) {
57
+ return { index, code: "invalid_record" };
58
+ }
59
+ return {
60
+ index,
61
+ record: {
62
+ email: value.email.toLowerCase(),
63
+ refreshToken: value.refresh_token,
64
+ },
65
+ };
66
+ }
67
+
68
+ export function parseCockpitAccountDocument(document: unknown): CockpitDocumentParseResult {
69
+ const size = serializedDocumentSize(document);
70
+ if (size === null || size > ACCOUNT_IMPORT_MAX_BYTES) return { ok: false, code: "invalid_document" };
71
+ if (!Array.isArray(document) || document.length === 0 || document.length > ACCOUNT_IMPORT_MAX_RECORDS) {
72
+ return { ok: false, code: "invalid_document" };
73
+ }
74
+ const seen = new Set<string>();
75
+ const records = document.map((value, index): ParsedCockpitRecord => {
76
+ const parsed = parseRecord(value, index);
77
+ if ("code" in parsed) return parsed;
78
+ if (seen.has(parsed.record.email)) return { index, code: "invalid_record" };
79
+ seen.add(parsed.record.email);
80
+ return parsed;
81
+ });
82
+ return { ok: true, records };
83
+ }
@@ -0,0 +1,18 @@
1
+ import { createAntigravityAccountImportAdapter } from "./google-antigravity-adapter";
2
+ import {
3
+ ACCOUNT_IMPORT_FORMAT,
4
+ ACCOUNT_IMPORT_PROVIDER,
5
+ type AccountImportAdapter,
6
+ } from "./types";
7
+
8
+ export type AccountImportRegistryResult =
9
+ | { ok: true; adapter: AccountImportAdapter }
10
+ | { ok: false; code: "unsupported_provider" | "unsupported_format" };
11
+
12
+ const antigravityAdapter = createAntigravityAccountImportAdapter();
13
+
14
+ export function resolveAccountImportAdapter(provider: string, format: string): AccountImportRegistryResult {
15
+ if (provider !== ACCOUNT_IMPORT_PROVIDER) return { ok: false, code: "unsupported_provider" };
16
+ if (format !== ACCOUNT_IMPORT_FORMAT) return { ok: false, code: "unsupported_format" };
17
+ return { ok: true, adapter: antigravityAdapter };
18
+ }
@@ -0,0 +1,75 @@
1
+ import { parseCockpitAccountDocument } from "./parser";
2
+ import { resolveAccountImportAdapter, type AccountImportRegistryResult } from "./registry";
3
+ import {
4
+ AccountImportAbortError,
5
+ throwIfAccountImportAborted,
6
+ } from "./types";
7
+ import type {
8
+ AccountImportRequest,
9
+ AccountImportResult,
10
+ AccountImportRecordResult,
11
+ } from "./types";
12
+
13
+ export type AccountImportServiceResult =
14
+ | { ok: true; result: AccountImportResult }
15
+ | {
16
+ ok: false;
17
+ status: 400 | 408;
18
+ code: "unsupported_provider" | "unsupported_format" | "invalid_document" | "import_cancelled";
19
+ /** True when at least one credential was committed before the terminal failure. */
20
+ changed?: boolean;
21
+ };
22
+
23
+ export interface AccountImportServiceDeps {
24
+ resolveAdapter(provider: string, format: string): AccountImportRegistryResult;
25
+ }
26
+
27
+ export async function importAccounts(
28
+ request: AccountImportRequest,
29
+ deps: AccountImportServiceDeps = { resolveAdapter: resolveAccountImportAdapter },
30
+ ): Promise<AccountImportServiceResult> {
31
+ // Provider/format admission intentionally precedes any traversal or serialization of the
32
+ // credential-bearing document.
33
+ const resolved = deps.resolveAdapter(request.provider, request.format);
34
+ if (!resolved.ok) return { ok: false, status: 400, code: resolved.code };
35
+
36
+ const parsed = parseCockpitAccountDocument(request.document);
37
+ if (!parsed.ok) return { ok: false, status: 400, code: parsed.code };
38
+
39
+ const results: AccountImportRecordResult[] = [];
40
+ try {
41
+ for (const item of parsed.records) {
42
+ throwIfAccountImportAborted(request.signal);
43
+ if ("code" in item) {
44
+ results.push({ index: item.index, status: "failed", code: item.code });
45
+ continue;
46
+ }
47
+ const outcome = await resolved.adapter.importRecord(item.record, request.signal);
48
+ results.push({ index: item.index, ...outcome });
49
+ // Record the committed outcome before observing cancellation. The route uses this
50
+ // internal signal to reconcile live stores and caches even when the public response
51
+ // is the terminal 408 DTO.
52
+ throwIfAccountImportAborted(request.signal);
53
+ }
54
+ } catch (error) {
55
+ if (error instanceof AccountImportAbortError) {
56
+ const changed = results.some(result => result.status === "imported" || result.status === "updated");
57
+ return { ok: false, status: 408, code: "import_cancelled", ...(changed ? { changed: true } : {}) };
58
+ }
59
+ throw error;
60
+ }
61
+
62
+ const count = (status: AccountImportRecordResult["status"]) =>
63
+ results.filter(result => result.status === status).length;
64
+ return {
65
+ ok: true,
66
+ result: {
67
+ totalCount: results.length,
68
+ importedCount: count("imported"),
69
+ updatedCount: count("updated"),
70
+ failedCount: count("failed"),
71
+ unsupportedCount: count("unsupported"),
72
+ results,
73
+ },
74
+ };
75
+ }