@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,309 @@
1
+ /**
2
+ * Token Guardian — background proactive OAuth refresh.
3
+ *
4
+ * Keeps idle tokens from aging out server-side (the reported multi-account Codex-pool bug) by
5
+ * refreshing them BEFORE a request needs them. It is a CALLER of the existing refresh machinery —
6
+ * it adds no new refresh/locking logic:
7
+ * - single-account providers → getValidAccessToken() (in-memory dedup + persist)
8
+ * - multi-account Codex pool → getValidCodexToken() (file lock + generation CAS + grant fingerprint)
9
+ *
10
+ * Safety by construction: the guardian only touches a provider whose EFFECTIVE refreshPolicy is
11
+ * "proactive", and the global switch (config.tokenGuardian.enabled) defaults OFF, so a default
12
+ * install adds zero ToS-detection surface. See devlog 260703_oauth-multi-account-refresh-and-tos.
13
+ */
14
+ import { loadConfig } from "../config";
15
+ import type { OcxConfig, OcxTokenGuardianConfig } from "../types";
16
+ import { listAccounts } from "./store";
17
+ import { getValidAccessTokenForAccount, listOAuthProviders, OAuthLoginRequiredError, resolveRefreshPolicy } from "./index";
18
+ import {
19
+ getValidCodexToken,
20
+ listCodexAccountIds,
21
+ markCodexAccountValidated,
22
+ markCodexAccountValidationFailed,
23
+ readCodexAccountRecord,
24
+ TokenRefreshError,
25
+ CodexCredentialRefreshBusyError,
26
+ CodexCredentialRefreshStaleError,
27
+ } from "../codex/account-store";
28
+ import { codexWarmupFailureReason, warmCodexAccount } from "../codex/warmup";
29
+ import { getMainAccountToken, MAIN_CODEX_ACCOUNT_ID } from "../codex/main-account";
30
+ import { isCanonicalOpenAiForwardProvider, OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";
31
+ import { providerCodexAccountMode } from "../providers/registry";
32
+ import { captureConfigGeneration, type GenerationContext } from "../lib/state-store-sweeper";
33
+ import { tryAcquireNativeMainProfileClaim } from "../codex/native-main-admission";
34
+
35
+ export interface TokenGuardianHandle {
36
+ stop(): void;
37
+ }
38
+
39
+ export interface GuardianSweepResult {
40
+ enabled: boolean;
41
+ refreshed: string[];
42
+ warmed: string[];
43
+ failed: string[];
44
+ skippedBackoff: string[];
45
+ }
46
+
47
+ const DEFAULTS = {
48
+ tickSeconds: 21600, // 6h — matches codex-lb's guardian cadence
49
+ jitterSeconds: 300,
50
+ concurrency: 3,
51
+ leadSeconds: 900,
52
+ failureBackoffBaseSeconds: 300,
53
+ failureBackoffMaxSeconds: 3600,
54
+ codexWarmupMaxAgeSeconds: 691_200, // 8d — matches Codex managed-auth last_refresh cadence.
55
+ codexWarmupModel: "gpt-5.4-mini",
56
+ };
57
+
58
+ interface BackoffEntry {
59
+ attempts: number;
60
+ retryAfterMs: number;
61
+ }
62
+
63
+ // Module-scoped so backoff survives across sweeps within one process (keyed "oauth:<p>" / "codex:<id>").
64
+ const backoff = new Map<string, BackoffEntry>();
65
+ let lastReconciledGeneration = 0;
66
+ let liveBackoffKeys = new Set<string>();
67
+
68
+ /** Test hook: clear backoff state between cases. */
69
+ export function __resetGuardianState(): void {
70
+ backoff.clear();
71
+ }
72
+
73
+ function num(value: number | undefined, fallback: number, min: number): number {
74
+ return typeof value === "number" && Number.isFinite(value) && value >= min ? value : fallback;
75
+ }
76
+
77
+ function resolved(g: OcxTokenGuardianConfig | undefined) {
78
+ return {
79
+ tickSeconds: num(g?.tickSeconds, DEFAULTS.tickSeconds, 60),
80
+ jitterSeconds: num(g?.jitterSeconds, DEFAULTS.jitterSeconds, 0),
81
+ concurrency: Math.max(1, Math.floor(num(g?.concurrency, DEFAULTS.concurrency, 1))),
82
+ leadSeconds: num(g?.leadSeconds, DEFAULTS.leadSeconds, 0),
83
+ backoffBaseSeconds: num(g?.failureBackoffBaseSeconds, DEFAULTS.failureBackoffBaseSeconds, 0),
84
+ backoffMaxSeconds: num(g?.failureBackoffMaxSeconds, DEFAULTS.failureBackoffMaxSeconds, 0),
85
+ codexWarmupEnabled: g?.codexWarmupEnabled === true,
86
+ codexWarmupMaxAgeSeconds: num(g?.codexWarmupMaxAgeSeconds, DEFAULTS.codexWarmupMaxAgeSeconds, 60),
87
+ codexWarmupModel: g?.codexWarmupModel?.trim() || DEFAULTS.codexWarmupModel,
88
+ };
89
+ }
90
+
91
+ function inBackoff(key: string, nowMs: number): boolean {
92
+ const entry = backoff.get(key);
93
+ return entry !== undefined && entry.retryAfterMs > nowMs;
94
+ }
95
+
96
+ function recordFailure(
97
+ key: string,
98
+ nowMs: number,
99
+ baseSeconds: number,
100
+ maxSeconds: number,
101
+ permanent: boolean,
102
+ writerGeneration = captureConfigGeneration(),
103
+ ): void {
104
+ if (writerGeneration < lastReconciledGeneration && !liveBackoffKeys.has(key)) return;
105
+ const prev = backoff.get(key);
106
+ const attempts = (prev?.attempts ?? 0) + 1;
107
+ // Permanent failures (revoked/expired refresh token) wait the full ceiling — nothing but a
108
+ // re-login fixes them, so there is no point retrying sooner.
109
+ const delaySeconds = permanent
110
+ ? maxSeconds
111
+ : Math.min(maxSeconds, baseSeconds * 2 ** (attempts - 1));
112
+ backoff.set(key, { attempts, retryAfterMs: nowMs + delaySeconds * 1000 });
113
+ }
114
+
115
+ async function runWithConcurrency(tasks: Array<() => Promise<void>>, limit: number): Promise<void> {
116
+ let cursor = 0;
117
+ const workers = Array.from({ length: Math.min(limit, tasks.length) }, async () => {
118
+ while (cursor < tasks.length) {
119
+ const task = tasks[cursor++];
120
+ if (task) await task();
121
+ }
122
+ });
123
+ await Promise.all(workers);
124
+ }
125
+
126
+ /**
127
+ * One refresh sweep. Reads live config + stores; refreshes every proactive-policy credential that
128
+ * will expire before the next sweep (tick + lead horizon). Never throws — per-credential failures
129
+ * are captured into backoff and the result. Returns a redacted summary (provider names / account
130
+ * ids only, never tokens).
131
+ */
132
+ export async function guardianSweep(nowMs: number = Date.now()): Promise<GuardianSweepResult> {
133
+ const writerGeneration = captureConfigGeneration();
134
+ const config: OcxConfig = loadConfig();
135
+ const g = config.tokenGuardian;
136
+ const result: GuardianSweepResult = { enabled: !!g?.enabled, refreshed: [], warmed: [], failed: [], skippedBackoff: [] };
137
+ if (!g?.enabled) return result;
138
+
139
+ const opts = resolved(g);
140
+ const horizonMs = (opts.tickSeconds + opts.leadSeconds) * 1000;
141
+ const tasks: Array<() => Promise<void>> = [];
142
+
143
+ // A) OAuth providers — every account in each provider's set (multiauth keep-alive),
144
+ // skipping accounts already marked needsReauth (terminal; only a re-login fixes them).
145
+ for (const provider of listOAuthProviders()) {
146
+ if (resolveRefreshPolicy(provider, config) !== "proactive") continue;
147
+ for (const account of listAccounts(provider)) {
148
+ if (account.needsReauth) continue;
149
+ if (account.credential.expires > nowMs + horizonMs) continue;
150
+ const key = `oauth:${provider}:${account.id}`;
151
+ if (inBackoff(key, nowMs)) { result.skippedBackoff.push(key); continue; }
152
+ tasks.push(async () => {
153
+ try {
154
+ await getValidAccessTokenForAccount(provider, account.id);
155
+ backoff.delete(key);
156
+ result.refreshed.push(key);
157
+ } catch (err) {
158
+ // Terminal grant failures surface as OAuthLoginRequiredError (account marked
159
+ // needsReauth by the resolver) — back off at the ceiling; transient errors backoff exponentially.
160
+ const permanent = err instanceof OAuthLoginRequiredError;
161
+ recordFailure(key, nowMs, opts.backoffBaseSeconds, opts.backoffMaxSeconds, permanent, writerGeneration);
162
+ result.failed.push(key);
163
+ }
164
+ });
165
+ }
166
+ }
167
+
168
+ // B) canonical OpenAI Codex login. Direct warms main only; pool additionally maintains every
169
+ // added account. The direct branch returns before the managed account store is enumerated.
170
+ const openai = config.providers[OPENAI_CODEX_PROVIDER_ID];
171
+ if (
172
+ openai
173
+ && openai.disabled !== true
174
+ && isCanonicalOpenAiForwardProvider(openai)
175
+ && resolveRefreshPolicy(OPENAI_CODEX_PROVIDER_ID, config) === "proactive"
176
+ ) {
177
+ const mode = providerCodexAccountMode(OPENAI_CODEX_PROVIDER_ID, openai) ?? "pool";
178
+ if (opts.codexWarmupEnabled) {
179
+ const key = `codex:${MAIN_CODEX_ACCOUNT_ID}`;
180
+ if (!inBackoff(key, nowMs)) {
181
+ tasks.push(async () => {
182
+ const nativeMainLease = tryAcquireNativeMainProfileClaim();
183
+ if (!nativeMainLease) return;
184
+ try {
185
+ const mainToken = getMainAccountToken();
186
+ if (!mainToken) return;
187
+ await warmCodexAccount({
188
+ accessToken: mainToken.accessToken,
189
+ chatgptAccountId: mainToken.chatgptAccountId,
190
+ model: opts.codexWarmupModel,
191
+ });
192
+ backoff.delete(key);
193
+ result.warmed.push(key);
194
+ } catch (err) {
195
+ recordFailure(key, nowMs, opts.backoffBaseSeconds, opts.backoffMaxSeconds, false, writerGeneration);
196
+ result.failed.push(key);
197
+ } finally {
198
+ nativeMainLease.release();
199
+ }
200
+ });
201
+ } else {
202
+ result.skippedBackoff.push(key);
203
+ }
204
+ }
205
+
206
+ const addedAccountIds = mode === "pool" ? listCodexAccountIds() : [];
207
+ for (const id of addedAccountIds) {
208
+ const record = readCodexAccountRecord(id);
209
+ if (!record || record.deletedAt != null) continue;
210
+ const cred = record.credential;
211
+ if (!cred) continue;
212
+ const needsRefresh = cred.expiresAt <= nowMs + horizonMs;
213
+ const needsWarmup = opts.codexWarmupEnabled
214
+ && (record.lastCodexValidatedAt === undefined || nowMs - record.lastCodexValidatedAt > opts.codexWarmupMaxAgeSeconds * 1000);
215
+ if (!needsRefresh && !needsWarmup) continue;
216
+ const key = `codex:${id}`;
217
+ if (inBackoff(key, nowMs)) { result.skippedBackoff.push(key); continue; }
218
+ tasks.push(async () => {
219
+ try {
220
+ const token = await getValidCodexToken(id);
221
+ if (needsRefresh) result.refreshed.push(key);
222
+ if (needsWarmup) {
223
+ await warmCodexAccount({
224
+ accessToken: token.accessToken,
225
+ chatgptAccountId: token.chatgptAccountId,
226
+ model: opts.codexWarmupModel,
227
+ });
228
+ markCodexAccountValidated(id, Date.now());
229
+ result.warmed.push(key);
230
+ }
231
+ backoff.delete(key);
232
+ } catch (err) {
233
+ if (err instanceof CodexCredentialRefreshBusyError || err instanceof CodexCredentialRefreshStaleError) {
234
+ recordFailure(key, nowMs, opts.backoffBaseSeconds, opts.backoffMaxSeconds, false, writerGeneration);
235
+ result.skippedBackoff.push(key);
236
+ return;
237
+ }
238
+ const permanent = err instanceof TokenRefreshError && (err.reason === "revoked" || err.reason === "expired");
239
+ if (needsWarmup && !(err instanceof TokenRefreshError)) {
240
+ markCodexAccountValidationFailed(id, codexWarmupFailureReason(err));
241
+ }
242
+ recordFailure(key, nowMs, opts.backoffBaseSeconds, opts.backoffMaxSeconds, permanent, writerGeneration);
243
+ result.failed.push(key);
244
+ }
245
+ });
246
+ }
247
+ }
248
+
249
+ await runWithConcurrency(tasks, opts.concurrency);
250
+ return result;
251
+ }
252
+
253
+ export function reconcileGuardianBackoff(context: GenerationContext): number {
254
+ if (context.generation <= lastReconciledGeneration) return 0;
255
+ const valid = new Set<string>();
256
+ for (const id of context.codexAccountIds) valid.add(`codex:${id}`);
257
+ for (const key of context.oauthAccountKeys) {
258
+ const separator = key.indexOf("\0");
259
+ if (separator <= 0) continue;
260
+ valid.add(`oauth:${key.slice(0, separator)}:${key.slice(separator + 1)}`);
261
+ }
262
+ let removed = 0;
263
+ for (const key of backoff.keys()) {
264
+ if (valid.has(key)) continue;
265
+ backoff.delete(key);
266
+ removed += 1;
267
+ }
268
+ liveBackoffKeys = valid;
269
+ lastReconciledGeneration = context.generation;
270
+ return removed;
271
+ }
272
+
273
+ /**
274
+ * Start the background sweep loop. Returns a handle whose stop() clears the pending timer (in-flight
275
+ * refreshes settle on their own). Schedules recursively so each interval gets fresh jitter. The loop
276
+ * runs even when the guardian is disabled (each sweep is a cheap no-op) so toggling `enabled` in
277
+ * config takes effect on the next tick without a restart.
278
+ */
279
+ export function startTokenGuardian(): TokenGuardianHandle {
280
+ let stopped = false;
281
+ let timer: ReturnType<typeof setTimeout> | undefined;
282
+
283
+ const scheduleNext = () => {
284
+ if (stopped) return;
285
+ const opts = resolved(loadConfig().tokenGuardian);
286
+ const delayMs = (opts.tickSeconds + Math.random() * opts.jitterSeconds) * 1000;
287
+ timer = setTimeout(runSweep, delayMs);
288
+ if (typeof timer.unref === "function") timer.unref(); // never keep the process alive for a sweep
289
+ };
290
+
291
+ const runSweep = () => {
292
+ void guardianSweep()
293
+ .then(r => {
294
+ if (r.enabled && (r.refreshed.length || r.warmed.length || r.failed.length)) {
295
+ console.log(`🛡️ token-guardian: refreshed ${r.refreshed.length}, warmed ${r.warmed.length}, failed ${r.failed.length}`);
296
+ }
297
+ })
298
+ .catch(err => console.log(`token-guardian sweep error: ${err instanceof Error ? err.message : String(err)}`))
299
+ .finally(scheduleNext);
300
+ };
301
+
302
+ scheduleNext();
303
+ return {
304
+ stop() {
305
+ stopped = true;
306
+ if (timer) clearTimeout(timer);
307
+ },
308
+ };
309
+ }
@@ -0,0 +1,62 @@
1
+ /** Minimal OAuth types, ported from jawcode packages/ai/src/utils/oauth/types.ts. */
2
+ export type OAuthCredentialSource = "oauth" | "local-cli" | "credential-file" | "environment" | "manual";
3
+
4
+ /** Account-scoped Kiro data required for refresh and request routing. */
5
+ export interface KiroOAuthMetadata {
6
+ profileArn?: string;
7
+ ssoRegion?: string;
8
+ apiRegion?: string;
9
+ clientId?: string;
10
+ clientSecret?: string;
11
+ }
12
+
13
+ export type OAuthCredentials = {
14
+ refresh: string;
15
+ access: string;
16
+ /** Epoch ms after any small provider-specific early-refresh margin; the shared gate adds 1 minute. */
17
+ expires: number;
18
+ email?: string;
19
+ accountId?: string;
20
+ source?: OAuthCredentialSource;
21
+ /** Google Antigravity (Cloud Code Assist) discovered project id; injected into the CCA envelope. */
22
+ projectId?: string;
23
+ /**
24
+ * GitHub Copilot allowlisted API origin from token `endpoints.api` (HTTPS `*.githubcopilot.com` only).
25
+ * Never reuse for Antigravity projectId; validated on write and again at request time.
26
+ */
27
+ apiBaseUrl?: string;
28
+ /** Never returned by management APIs; persisted only inside the protected auth-store boundary. */
29
+ kiro?: KiroOAuthMetadata;
30
+ };
31
+
32
+ /** One logged-in account inside a provider's account set (multiauth). */
33
+ export interface ProviderAccount {
34
+ /** Stable short id, generated once at append time; never re-derived after rotation. */
35
+ id: string;
36
+ /** User-owned display label; never participates in auth identity or routing. */
37
+ alias?: string;
38
+ credential: OAuthCredentials;
39
+ /** Terminal refresh failure (invalid_grant / reused / revoked) — re-login required. */
40
+ needsReauth?: boolean;
41
+ addedAt?: number;
42
+ }
43
+
44
+ /** auth.json value per provider: N accounts + which one requests use. */
45
+ export interface ProviderAccountSet {
46
+ activeAccountId: string;
47
+ accounts: ProviderAccount[];
48
+ }
49
+
50
+ export interface OAuthController {
51
+ onAuth?(info: { url: string; instructions?: string; deviceCode?: string }): void;
52
+ onProgress?(message: string): void;
53
+ onManualCodeInput?(expectedState?: string): Promise<string>;
54
+ signal?: AbortSignal;
55
+ }
56
+
57
+ /**
58
+ * How a login flow may use a locally detected CLI token.
59
+ * "off" goes straight to the real OAuth flow, "fallback" imports a local token when present
60
+ * and falls back to OAuth otherwise, "only" imports without any OAuth fallback.
61
+ */
62
+ export type LocalTokenImportMode = "off" | "fallback" | "only";
@@ -0,0 +1,241 @@
1
+ /** xAI OAuth flow (Grok account login). Ported from jawcode oauth/xai.ts. */
2
+ import { OAuthCallbackFlow, type OAuthCallbackFlowOptions } from "./callback-server";
3
+ import { generatePKCE } from "./pkce";
4
+ import type { LocalTokenImportMode, OAuthController, OAuthCredentials } from "./types";
5
+
6
+ const XAI_OAUTH_ISSUER = "https://auth.x.ai";
7
+ export const XAI_OAUTH_DISCOVERY_URL = `${XAI_OAUTH_ISSUER}/.well-known/openid-configuration`;
8
+ export const XAI_OAUTH_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
9
+ export const XAI_OAUTH_SCOPE = "openid profile email offline_access grok-cli:access api:access";
10
+ const XAI_OAUTH_CALLBACK_PORT = 56121;
11
+ const XAI_OAUTH_CALLBACK_PATH = "/callback";
12
+ const XAI_OAUTH_REFRESH_SKEW_MS = 2 * 60 * 1000;
13
+ const TOKEN_REQUEST_TIMEOUT_MS = 30_000;
14
+
15
+ export const XAI_LOCAL_CLI_DETACH_WARNING =
16
+ "[oauth:xai] Grok CLI credential was stale; refreshed into OpenCodex ownership. Grok CLI may require login again.";
17
+
18
+ interface XaiDiscovery {
19
+ authorizationEndpoint: string;
20
+ tokenEndpoint: string;
21
+ }
22
+
23
+ interface XaiDiscoveryPayload {
24
+ authorization_endpoint?: unknown;
25
+ token_endpoint?: unknown;
26
+ }
27
+
28
+ export interface XaiTokenPayload {
29
+ access_token?: unknown;
30
+ refresh_token?: unknown;
31
+ expires_in?: unknown;
32
+ id_token?: unknown;
33
+ token_type?: unknown;
34
+ }
35
+
36
+ interface XaiJwtPayload {
37
+ sub?: unknown;
38
+ email?: unknown;
39
+ [key: string]: unknown;
40
+ }
41
+
42
+ function requestSignal(signal: AbortSignal | undefined): AbortSignal {
43
+ const timeoutSignal = AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS);
44
+ return signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
45
+ }
46
+
47
+ function validateXaiEndpoint(rawUrl: string): string {
48
+ const parsed = new URL(rawUrl);
49
+ const host = parsed.hostname.toLowerCase();
50
+ if (parsed.protocol !== "https:" || (host !== "x.ai" && !host.endsWith(".x.ai"))) {
51
+ throw new Error(`xAI OAuth discovery returned an unexpected endpoint: ${rawUrl}`);
52
+ }
53
+ return parsed.toString();
54
+ }
55
+
56
+ export async function discoverXaiOAuthEndpoints(signal?: AbortSignal): Promise<XaiDiscovery> {
57
+ const response = await fetch(XAI_OAUTH_DISCOVERY_URL, {
58
+ headers: { Accept: "application/json" },
59
+ signal: requestSignal(signal),
60
+ });
61
+ if (!response.ok) {
62
+ throw new Error(`xAI OAuth discovery failed: ${response.status} ${await response.text()}`);
63
+ }
64
+
65
+ const payload = (await response.json()) as XaiDiscoveryPayload;
66
+ if (typeof payload.authorization_endpoint !== "string" || typeof payload.token_endpoint !== "string") {
67
+ throw new Error("xAI OAuth discovery response missing authorization/token endpoints");
68
+ }
69
+
70
+ return {
71
+ authorizationEndpoint: validateXaiEndpoint(payload.authorization_endpoint),
72
+ tokenEndpoint: validateXaiEndpoint(payload.token_endpoint),
73
+ };
74
+ }
75
+
76
+ function decodeJwtPayload(token: string): XaiJwtPayload | undefined {
77
+ const parts = token.split(".");
78
+ const payload = parts[1];
79
+ if (parts.length !== 3 || !payload) return undefined;
80
+ try {
81
+ return JSON.parse(Buffer.from(payload, "base64url").toString("utf8")) as XaiJwtPayload;
82
+ } catch {
83
+ return undefined;
84
+ }
85
+ }
86
+
87
+ function getTokenIdentity(accessToken: string, idToken: string | undefined): { accountId?: string; email?: string } {
88
+ const payload = (idToken ? decodeJwtPayload(idToken) : undefined) ?? decodeJwtPayload(accessToken);
89
+ const accountId = typeof payload?.sub === "string" && payload.sub.length > 0 ? payload.sub : undefined;
90
+ const email =
91
+ typeof payload?.email === "string" && payload.email.length > 0 ? payload.email.toLowerCase() : undefined;
92
+ return { accountId, email };
93
+ }
94
+
95
+ export class XaiTokenRequestError extends Error { constructor(public readonly status?:number,public readonly oauthError?:string,message="xAI token request failed",options?:{cause?:unknown}){super(message,options);this.name="XaiTokenRequestError";} }
96
+ export interface XaiTokenRetryDeps { sleep?:(ms:number)=>Promise<void>; random?:()=>number }
97
+ function isAbortError(error:unknown):boolean{return error instanceof DOMException&&error.name==="AbortError";}
98
+ function retryDelay(attempt:number,retryAfter:string|null,random:()=>number):number{const base=attempt===1?100:250,j=Math.round(base*(.75+random()*.5)),seconds=retryAfter!==null&&/^\d+$/.test(retryAfter)?Number(retryAfter):0;return Math.min(2000,Math.max(j,seconds*1000));}
99
+ async function readTokenError(response:Response):Promise<XaiTokenRequestError>{let oauthError:string|undefined,detail="";try{const body=await response.json() as {error?:unknown;error_description?:unknown};if(typeof body.error==="string")oauthError=body.error;if(typeof body.error_description==="string")detail=body.error_description;}catch{}const suffix=detail?`: ${detail}`:oauthError?`: ${oauthError}`:"";return new XaiTokenRequestError(response.status,oauthError,`xAI token request failed: ${response.status}${suffix}`);}
100
+ export async function postXaiToken(
101
+ tokenEndpoint: string,
102
+ body: Record<string, string>,
103
+ signal?: AbortSignal, deps:XaiTokenRetryDeps={},
104
+ ): Promise<XaiTokenPayload> {
105
+ const sleep=deps.sleep??(ms=>Bun.sleep(ms)),random=deps.random??Math.random;let last:unknown;
106
+ for(let attempt=1;attempt<=3;attempt++){let response:Response;try{response=await fetch(tokenEndpoint, {
107
+ method: "POST",
108
+ headers: {
109
+ Accept: "application/json",
110
+ "Content-Type": "application/x-www-form-urlencoded",
111
+ },
112
+ body: new URLSearchParams(body).toString(),
113
+ signal: requestSignal(signal),
114
+ });}catch(error){if(isAbortError(error)&&signal?.aborted)throw error;last=error;if(attempt===3)throw new XaiTokenRequestError(undefined,undefined,"xAI token request failed: network error",{cause:error});await sleep(retryDelay(attempt,null,random));continue;}if(response.ok)return await response.json() as XaiTokenPayload;const error=await readTokenError(response);last=error;if(!(response.status===429||response.status>=500)||attempt===3)throw error;await sleep(retryDelay(attempt,response.headers.get("retry-after"),random));}throw last;
115
+ }
116
+
117
+ function credentialsFromTokenPayload(payload: XaiTokenPayload, refreshFallback = ""): OAuthCredentials {
118
+ if (typeof payload.access_token !== "string" || payload.access_token.length === 0) {
119
+ throw new Error("xAI token response did not include an access token");
120
+ }
121
+ const refresh =
122
+ typeof payload.refresh_token === "string" && payload.refresh_token.length > 0
123
+ ? payload.refresh_token
124
+ : refreshFallback;
125
+ if (!refresh) {
126
+ throw new Error("xAI token response did not include a refresh token");
127
+ }
128
+ const expiresIn =
129
+ typeof payload.expires_in === "number" && Number.isFinite(payload.expires_in) ? payload.expires_in : 3600;
130
+ const idToken = typeof payload.id_token === "string" ? payload.id_token : undefined;
131
+ const { accountId, email } = getTokenIdentity(payload.access_token, idToken);
132
+ return {
133
+ refresh,
134
+ access: payload.access_token,
135
+ expires: Date.now() + expiresIn * 1000 - XAI_OAUTH_REFRESH_SKEW_MS,
136
+ accountId,
137
+ email,
138
+ };
139
+ }
140
+
141
+ export class XaiOAuthFlow extends OAuthCallbackFlow {
142
+ #verifier = "";
143
+ #discovery: XaiDiscovery | undefined;
144
+
145
+ constructor(ctrl: OAuthController) {
146
+ super(ctrl, {
147
+ preferredPort: XAI_OAUTH_CALLBACK_PORT,
148
+ callbackPath: XAI_OAUTH_CALLBACK_PATH,
149
+ callbackHostname: "127.0.0.1",
150
+ callbackBindHostname: "127.0.0.1",
151
+ redirectUri: `http://127.0.0.1:${XAI_OAUTH_CALLBACK_PORT}${XAI_OAUTH_CALLBACK_PATH}`,
152
+ } satisfies OAuthCallbackFlowOptions);
153
+ }
154
+
155
+ async generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }> {
156
+ const pkce = await generatePKCE();
157
+ this.#verifier = pkce.verifier;
158
+ this.#discovery = await discoverXaiOAuthEndpoints(this.ctrl.signal);
159
+ const params = new URLSearchParams({
160
+ response_type: "code",
161
+ client_id: XAI_OAUTH_CLIENT_ID,
162
+ redirect_uri: redirectUri,
163
+ scope: XAI_OAUTH_SCOPE,
164
+ code_challenge: pkce.challenge,
165
+ code_challenge_method: "S256",
166
+ state,
167
+ nonce: crypto.randomUUID(),
168
+ });
169
+ return {
170
+ url: `${this.#discovery.authorizationEndpoint}?${params.toString()}`,
171
+ instructions:
172
+ "Complete xAI/Grok login in your browser. If the browser cannot reach this machine, paste the final redirect URL or authorization code when prompted.",
173
+ };
174
+ }
175
+
176
+ async exchangeToken(code: string, _state: string, redirectUri: string): Promise<OAuthCredentials> {
177
+ if (!this.#verifier) {
178
+ throw new Error("xAI OAuth PKCE verifier was not initialized");
179
+ }
180
+ const discovery = this.#discovery ?? (await discoverXaiOAuthEndpoints(this.ctrl.signal));
181
+ const tokenPayload = await postXaiToken(
182
+ discovery.tokenEndpoint,
183
+ {
184
+ grant_type: "authorization_code",
185
+ client_id: XAI_OAUTH_CLIENT_ID,
186
+ code,
187
+ redirect_uri: redirectUri,
188
+ code_verifier: this.#verifier,
189
+ },
190
+ this.ctrl.signal,
191
+ );
192
+ return credentialsFromTokenPayload(tokenPayload);
193
+ }
194
+ }
195
+
196
+ export async function loginXai(
197
+ ctrl: OAuthController,
198
+ opts?: { importLocal?: LocalTokenImportMode },
199
+ ): Promise<OAuthCredentials> {
200
+ const importLocal = opts?.importLocal ?? "off";
201
+ if (importLocal !== "off") {
202
+ const { detectGrokCliToken } = await import("./local-token-detect");
203
+ const local = detectGrokCliToken();
204
+ if (local) {
205
+ ctrl.onProgress?.("Found Grok CLI token, importing automatically");
206
+ if (local.expires >= Date.now() + 60_000) return local;
207
+ try {
208
+ const fresh = await refreshXaiToken(local.refresh, ctrl.signal);
209
+ ctrl.onProgress?.(XAI_LOCAL_CLI_DETACH_WARNING);
210
+ return { ...fresh, source: "oauth" };
211
+ } catch (error) {
212
+ if (importLocal === "only") {
213
+ throw new Error(
214
+ `Grok CLI token is expired and could not be refreshed: ${error instanceof Error ? error.message : String(error)}`,
215
+ );
216
+ }
217
+ }
218
+ } else if (importLocal === "only") {
219
+ throw new Error("No Grok CLI token found at ~/.grok/auth.json. Run 'ocx login xai' for browser OAuth.");
220
+ }
221
+ }
222
+
223
+ return new XaiOAuthFlow(ctrl).login();
224
+ }
225
+
226
+ export async function refreshXaiToken(refreshToken: string, signal?: AbortSignal): Promise<OAuthCredentials> {
227
+ if (!refreshToken) {
228
+ throw new Error("xAI credentials are expired and do not include a refresh token");
229
+ }
230
+ const discovery = await discoverXaiOAuthEndpoints(signal);
231
+ const tokenPayload = await postXaiToken(
232
+ discovery.tokenEndpoint,
233
+ {
234
+ grant_type: "refresh_token",
235
+ client_id: XAI_OAUTH_CLIENT_ID,
236
+ refresh_token: refreshToken,
237
+ },
238
+ signal,
239
+ );
240
+ return credentialsFromTokenPayload(tokenPayload, refreshToken);
241
+ }
@@ -0,0 +1,75 @@
1
+ import { copyFileSync, existsSync, linkSync, readFileSync, rmSync } from "node:fs";
2
+ import { getConfigPath } from "../config";
3
+
4
+ export interface AlibabaBackupIO {
5
+ exists: (path: string) => boolean;
6
+ read: (path: string) => Buffer;
7
+ copy: (source: string, destination: string) => void;
8
+ /** Publish with no-replace semantics: fails with EEXIST if the destination exists. */
9
+ publishNoReplace: (temp: string, destination: string) => void;
10
+ remove: (path: string) => void;
11
+ }
12
+
13
+ const DEFAULT_IO: AlibabaBackupIO = {
14
+ exists: existsSync,
15
+ read: path => readFileSync(path),
16
+ copy: (source, destination) => copyFileSync(source, destination),
17
+ publishNoReplace: linkSync,
18
+ remove: path => rmSync(path, { force: true }),
19
+ };
20
+
21
+ export class AlibabaBackupIntegrityError extends Error {}
22
+
23
+ /**
24
+ * Immutable pre-migration snapshot of `config.json`.
25
+ *
26
+ * Written to a temp file first and published by `link`, which fails with EEXIST
27
+ * rather than replacing. Exclusive *creation* alone is not enough: a crash
28
+ * mid-copy can leave a truncated destination that the next run would accept as a
29
+ * valid rollback point. Copy-verify-link means a published snapshot is always a
30
+ * complete one.
31
+ *
32
+ * An existing snapshot is NOT required to equal the current config. Demanding
33
+ * that has a false positive that would brick a working install: a run that
34
+ * created the snapshot and then aborted for an unrelated reason leaves a
35
+ * perfectly valid snapshot, the user then edits `config.json` legitimately, and
36
+ * every subsequent start would throw out of `startServer` and refuse to boot. A
37
+ * safety net must never become the thing that stops the product.
38
+ *
39
+ * So an existing snapshot is reused as-is — it is the earliest one, which is
40
+ * exactly what a rollback point should be. Integrity is carried by publication.
41
+ *
42
+ * Deliberately not built on `backupConfigBeforeOpenAiTierMigration`: that
43
+ * function's stale/rollback classification exists for a repeatable migration and
44
+ * would be wrong here.
45
+ */
46
+ export function backupConfigBeforeAlibabaRegionMigration(
47
+ configPath = getConfigPath(),
48
+ io: AlibabaBackupIO = DEFAULT_IO,
49
+ ): "absent" | "created" | "reused" {
50
+ if (!io.exists(configPath)) return "absent";
51
+ const backup = `${configPath}.pre-alibaba-region-v1.bak`;
52
+ // The earliest snapshot is the most valuable one: it predates every migration
53
+ // this config has been through.
54
+ if (io.exists(backup)) return "reused";
55
+
56
+ const source = io.read(configPath);
57
+ const temp = `${backup}.${process.pid}.tmp`;
58
+ try {
59
+ io.copy(configPath, temp);
60
+ // Verify before publishing: a short copy must never become the snapshot.
61
+ if (!io.read(temp).equals(source)) {
62
+ throw new AlibabaBackupIntegrityError(`failed to write a complete backup to ${temp}`);
63
+ }
64
+ io.publishNoReplace(temp, backup);
65
+ return "created";
66
+ } catch (error) {
67
+ // Another process published between our `exists` check and the link. It went
68
+ // through the same copy-verify-link sequence, so it is complete by
69
+ // construction — nothing else writes this filename.
70
+ if ((error as NodeJS.ErrnoException).code === "EEXIST") return "reused";
71
+ throw error;
72
+ } finally {
73
+ io.remove(temp);
74
+ }
75
+ }