@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,161 @@
1
+ import { OAuthCallbackFlow } from "./callback-server";
2
+ import type { OAuthController, OAuthCredentials } from "./types";
3
+ import { generatePKCE } from "./pkce";
4
+
5
+ const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
6
+ const AUTH_URL = "https://auth.openai.com/oauth/authorize";
7
+ const TOKEN_URL = "https://auth.openai.com/oauth/token";
8
+ const SCOPE = "openid profile email offline_access api.connectors.read api.connectors.invoke";
9
+ const CALLBACK_PORT = 1455;
10
+ const CALLBACK_PATH = "/auth/callback";
11
+ const ORIGINATOR = "opencodex";
12
+
13
+ export function decodeJwtPayload(token: string): Record<string, unknown> | undefined {
14
+ const parts = token.split(".");
15
+ if (parts.length !== 3 || !parts[1]) return undefined;
16
+ try {
17
+ return JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8")) as Record<string, unknown>;
18
+ } catch {
19
+ return undefined;
20
+ }
21
+ }
22
+
23
+ export function extractAccountId(idToken?: string, accessToken?: string): string | undefined {
24
+ for (const token of [idToken, accessToken]) {
25
+ if (!token) continue;
26
+ const payload = decodeJwtPayload(token);
27
+ if (!payload) continue;
28
+ if (typeof payload.chatgpt_account_id === "string") return payload.chatgpt_account_id;
29
+ const ns = payload["https://api.openai.com/auth"];
30
+ if (ns && typeof ns === "object" && typeof (ns as Record<string, unknown>).chatgpt_account_id === "string") {
31
+ return (ns as Record<string, unknown>).chatgpt_account_id as string;
32
+ }
33
+ const orgs = payload.organizations;
34
+ if (Array.isArray(orgs) && orgs[0] && typeof orgs[0].id === "string") return orgs[0].id as string;
35
+ }
36
+ return undefined;
37
+ }
38
+
39
+ export function extractEmail(idToken?: string, accessToken?: string): string | undefined {
40
+ for (const token of [idToken, accessToken]) {
41
+ if (!token) continue;
42
+ const payload = decodeJwtPayload(token);
43
+ if (!payload) continue;
44
+ if (typeof payload.email === "string") return payload.email.toLowerCase();
45
+ }
46
+ return undefined;
47
+ }
48
+
49
+ function credsFromToken(data: Record<string, unknown>): OAuthCredentials {
50
+ const idToken = typeof data.id_token === "string" ? data.id_token : undefined;
51
+ const accessToken = data.access_token as string;
52
+ // ?? only guards null/undefined; NaN or a string expires_in would otherwise
53
+ // produce a NaN expiry that never compares as expired, and a negative duration
54
+ // would stamp an already-past expiry — both block refresh semantics.
55
+ const expiresIn =
56
+ typeof data.expires_in === "number" && Number.isFinite(data.expires_in) && data.expires_in >= 0
57
+ ? data.expires_in
58
+ : 3600;
59
+ // The computed timestamp itself must stay finite: Number.MAX_VALUE passes
60
+ // Number.isFinite but overflows to Infinity once multiplied by 1000.
61
+ const computedExpires = Date.now() + expiresIn * 1000;
62
+ const expires = Number.isFinite(computedExpires) ? computedExpires : Date.now() + 3600 * 1000;
63
+ return {
64
+ access: accessToken,
65
+ refresh: (data.refresh_token as string) ?? "",
66
+ expires,
67
+ accountId: extractAccountId(idToken, accessToken),
68
+ email: extractEmail(idToken, accessToken),
69
+ };
70
+ }
71
+
72
+ export class ChatGPTOAuthFlow extends OAuthCallbackFlow {
73
+ #verifier = "";
74
+ forceLogin = false;
75
+
76
+ constructor(ctrl: OAuthController) {
77
+ super(ctrl, {
78
+ preferredPort: CALLBACK_PORT,
79
+ callbackPath: CALLBACK_PATH,
80
+ callbackHostname: "localhost",
81
+ callbackBindHostname: "127.0.0.1",
82
+ redirectUri: `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`,
83
+ });
84
+ }
85
+
86
+ async generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }> {
87
+ const pkce = await generatePKCE();
88
+ this.#verifier = pkce.verifier;
89
+ const params = new URLSearchParams({
90
+ response_type: "code",
91
+ client_id: CLIENT_ID,
92
+ redirect_uri: redirectUri,
93
+ scope: SCOPE,
94
+ code_challenge: pkce.challenge,
95
+ code_challenge_method: "S256",
96
+ state,
97
+ codex_cli_simplified_flow: "true",
98
+ originator: ORIGINATOR,
99
+ });
100
+ params.set("id_token_add_organizations", "true");
101
+ if (this.forceLogin) params.set("prompt", "login");
102
+ return {
103
+ url: `${AUTH_URL}?${params}`,
104
+ instructions: "Complete ChatGPT login in your browser.",
105
+ };
106
+ }
107
+
108
+ async exchangeToken(code: string, _state: string, redirectUri: string): Promise<OAuthCredentials> {
109
+ if (!this.#verifier) throw new Error("ChatGPT PKCE verifier not initialized");
110
+ const resp = await fetch(TOKEN_URL, {
111
+ method: "POST",
112
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
113
+ body: new URLSearchParams({
114
+ grant_type: "authorization_code",
115
+ client_id: CLIENT_ID,
116
+ code,
117
+ redirect_uri: redirectUri,
118
+ code_verifier: this.#verifier,
119
+ }).toString(),
120
+ });
121
+ if (!resp.ok) {
122
+ const errDesc = await safeErrorDescription(resp);
123
+ throw new Error(`ChatGPT token exchange failed: ${resp.status} ${errDesc}`);
124
+ }
125
+ return credsFromToken((await resp.json()) as Record<string, unknown>);
126
+ }
127
+ }
128
+
129
+ function safeErrorDescription(resp: Response): Promise<string> {
130
+ return resp.text().catch(() => "").then(text => {
131
+ try {
132
+ const parsed = JSON.parse(text) as { error?: string; error_description?: string };
133
+ return [parsed.error, parsed.error_description].filter(Boolean).join(": ") || `HTTP ${resp.status}`;
134
+ } catch { return `HTTP ${resp.status}`; }
135
+ });
136
+ }
137
+
138
+ export async function loginChatGPT(ctrl: OAuthController, opts?: { forceLogin?: boolean }): Promise<OAuthCredentials> {
139
+ const flow = new ChatGPTOAuthFlow(ctrl);
140
+ if (opts?.forceLogin) flow.forceLogin = true;
141
+ return flow.login();
142
+ }
143
+
144
+ // Note: uses form-urlencoded per OAuth 2.0 spec (RFC 6749 §6).
145
+ // Codex-rs uses JSON for refresh — intentional divergence; both accepted by auth.openai.com.
146
+ export async function refreshChatGPTToken(refreshToken: string): Promise<OAuthCredentials> {
147
+ const resp = await fetch(TOKEN_URL, {
148
+ method: "POST",
149
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
150
+ body: new URLSearchParams({
151
+ grant_type: "refresh_token",
152
+ client_id: CLIENT_ID,
153
+ refresh_token: refreshToken,
154
+ }).toString(),
155
+ });
156
+ if (!resp.ok) {
157
+ const errDesc = await safeErrorDescription(resp);
158
+ throw new Error(`ChatGPT refresh failed: ${resp.status} ${errDesc}`);
159
+ }
160
+ return credsFromToken((await resp.json()) as Record<string, unknown>);
161
+ }
@@ -0,0 +1,239 @@
1
+ import type { OAuthController, OAuthCredentials } from "./types";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { isAddrInUse } from "../server/ports";
5
+ import { parseCallbackInput } from "./callback-server";
6
+
7
+ const COMMAND_CODE_STUDIO_URL = "https://commandcode.ai";
8
+ const COMMAND_CODE_CALLBACK_PORT = 5959;
9
+ const LOGIN_TIMEOUT_MS = 120_000;
10
+ const CALLBACK_PATH = "/callback";
11
+
12
+ interface CommandCodeCallback {
13
+ apiKey: string;
14
+ state: string;
15
+ userId: string;
16
+ userName: string;
17
+ keyName: string;
18
+ }
19
+
20
+ interface CommandCodeLocalAuth {
21
+ apiKey?: unknown;
22
+ userId?: unknown;
23
+ }
24
+
25
+ export interface CommandCodeLoginOptions {
26
+ /** Add-account and reauthentication flows must select a fresh browser identity. */
27
+ importLocal?: "fallback" | "off";
28
+ }
29
+
30
+ export function shouldImportLocalCommandCodeAuth(options: CommandCodeLoginOptions = {}): boolean {
31
+ return options.importLocal !== "off";
32
+ }
33
+
34
+ async function importLocalCommandCodeAuth(signal?: AbortSignal): Promise<OAuthCredentials | undefined> {
35
+ if (signal?.aborted) {
36
+ throw signal.reason ?? new DOMException("Command Code login aborted", "AbortError");
37
+ }
38
+ let parsed: CommandCodeLocalAuth;
39
+ try {
40
+ parsed = JSON.parse(await Bun.file(join(homedir(), ".commandcode", "auth.json")).text()) as CommandCodeLocalAuth;
41
+ } catch {
42
+ return undefined;
43
+ }
44
+ if (typeof parsed.apiKey !== "string" || parsed.apiKey.length === 0) return undefined;
45
+ let accountId: string | undefined;
46
+ try {
47
+ const response = await fetch("https://api.commandcode.ai/alpha/whoami", {
48
+ headers: { Authorization: `Bearer ${parsed.apiKey}`, Accept: "application/json" },
49
+ signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(10_000)]) : AbortSignal.timeout(10_000),
50
+ });
51
+ if (!response.ok) return undefined;
52
+ // Carry the validated whoami identity so an imported credential keeps multi-account
53
+ // semantics even when the local auth.json omits userId.
54
+ const body = (await response.json()) as { user?: { id?: unknown } };
55
+ if (typeof body.user?.id === "string" && body.user.id.length > 0) accountId = body.user.id;
56
+ } catch (error) {
57
+ if (signal?.aborted) throw signal.reason ?? new DOMException("Command Code login aborted", "AbortError");
58
+ return undefined;
59
+ }
60
+ if (!accountId && typeof parsed.userId === "string" && parsed.userId.length > 0) accountId = parsed.userId;
61
+ return {
62
+ access: parsed.apiKey,
63
+ refresh: parsed.apiKey,
64
+ expires: Number.MAX_SAFE_INTEGER,
65
+ ...(accountId ? { accountId } : {}),
66
+ source: "local-cli",
67
+ };
68
+ }
69
+
70
+ function randomState(): string {
71
+ const bytes = new Uint8Array(32);
72
+ crypto.getRandomValues(bytes);
73
+ return Buffer.from(bytes).toString("base64url");
74
+ }
75
+
76
+ export function parseCommandCodeCallback(value: unknown, expectedState: string): CommandCodeCallback {
77
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
78
+ throw new Error("Command Code callback must be an object");
79
+ }
80
+ const body = value as Record<string, unknown>;
81
+ if (body.state !== expectedState) throw new Error("Command Code OAuth state mismatch");
82
+ for (const field of ["apiKey", "userId", "userName", "keyName"] as const) {
83
+ if (typeof body[field] !== "string" || body[field].length === 0) {
84
+ throw new Error(`Command Code callback missing ${field}`);
85
+ }
86
+ }
87
+ return body as unknown as CommandCodeCallback;
88
+ }
89
+
90
+ function createCallbackServer(state: string): {
91
+ servers: Array<ReturnType<typeof Bun.serve>>;
92
+ callback: Promise<CommandCodeCallback>;
93
+ } {
94
+ let resolve!: (value: CommandCodeCallback) => void;
95
+ const callback = new Promise<CommandCodeCallback>((res) => { resolve = res; });
96
+ const fetch = async (request: Request): Promise<Response> => {
97
+ const url = new URL(request.url);
98
+ const origin = request.headers.get("origin");
99
+ const headers = new Headers({
100
+ "Content-Type": "application/json",
101
+ "Access-Control-Allow-Origin": origin === COMMAND_CODE_STUDIO_URL ? origin : COMMAND_CODE_STUDIO_URL,
102
+ "Access-Control-Allow-Methods": "POST, OPTIONS",
103
+ "Access-Control-Allow-Headers": "Content-Type",
104
+ });
105
+ if (request.method === "OPTIONS") return new Response(null, { status: 204, headers });
106
+ if (url.pathname !== CALLBACK_PATH) return Response.json({ success: false, error: "Not found" }, { status: 404, headers });
107
+ if (request.method !== "POST") return Response.json({ success: false, error: "Method not allowed" }, { status: 405, headers });
108
+ try {
109
+ const body = await request.json();
110
+ const parsed = parseCommandCodeCallback(body, state);
111
+ queueMicrotask(() => resolve(parsed));
112
+ return Response.json({ success: true }, { headers });
113
+ } catch (error) {
114
+ const message = error instanceof Error ? error.message : String(error);
115
+ return Response.json({ success: false, error: message }, { status: 400, headers });
116
+ }
117
+ };
118
+ const create = (port: number): Array<ReturnType<typeof Bun.serve>> => {
119
+ // The advertised callback host is `127.0.0.1`; on Windows `localhost` commonly resolves to `::1`
120
+ // first, so also bind the IPv6 loopback best-effort (mirrors the shared OAuthCallbackFlow).
121
+ const servers = [Bun.serve({ hostname: "127.0.0.1", port, fetch })];
122
+ try {
123
+ servers.push(Bun.serve({ hostname: "::1", port: servers[0].port, fetch }));
124
+ } catch (error) {
125
+ if (isAddrInUse(error)) {
126
+ for (const server of servers) server.stop(true);
127
+ throw error;
128
+ }
129
+ // IPv6 unsupported (EAFNOSUPPORT etc.) degrades to the IPv4-only listener.
130
+ }
131
+ return servers;
132
+ };
133
+ try {
134
+ return { servers: create(COMMAND_CODE_CALLBACK_PORT), callback };
135
+ } catch {
136
+ return { servers: create(0), callback };
137
+ }
138
+ }
139
+
140
+ /** Validate a raw pasted Command Code API key and return the validated identity. */
141
+ async function validatePastedApiKey(apiKey: string): Promise<{ userId: string; userName: string } | undefined> {
142
+ try {
143
+ const response = await fetch("https://api.commandcode.ai/alpha/whoami", {
144
+ headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
145
+ signal: AbortSignal.timeout(10_000),
146
+ });
147
+ if (!response.ok) return undefined;
148
+ const body = (await response.json()) as { user?: { id?: unknown; userName?: unknown } };
149
+ const userId = body.user?.id;
150
+ const userName = body.user?.userName;
151
+ if (typeof userId !== "string" || typeof userName !== "string") return undefined;
152
+ if (!userId.trim() || !userName.trim()) return undefined;
153
+ return { userId, userName };
154
+ } catch {
155
+ return undefined;
156
+ }
157
+ }
158
+
159
+ /** Manual-paste fallback: a raw API key, or a pasted callback JSON/URL that carries `apiKey`. */
160
+ function parsePastedCommandCodeInput(input: string, expectedState: string): CommandCodeCallback | undefined {
161
+ const trimmed = input.trim();
162
+ if (!trimmed) return undefined;
163
+ if (trimmed.startsWith("{")) {
164
+ try {
165
+ return parseCommandCodeCallback(JSON.parse(trimmed) as unknown, expectedState);
166
+ } catch {
167
+ return undefined;
168
+ }
169
+ }
170
+ const parsed = parseCallbackInput(trimmed);
171
+ const apiKey = parsed.code?.trim();
172
+ if (!apiKey) return undefined;
173
+ // A URL/query-shaped paste is an authorization response and must carry a matching state,
174
+ // mirroring the shared OAuth callback flow; a stale or attacker-supplied URL from another
175
+ // session must not be accepted. Raw in-session keys are exempt (no state to compare).
176
+ if (parsed.kind !== "raw" && parsed.state !== expectedState) return undefined;
177
+ return { apiKey, state: expectedState, userId: "", userName: "", keyName: "manual" };
178
+ }
179
+
180
+ export async function loginCommandCode(ctrl: OAuthController, options: CommandCodeLoginOptions = {}): Promise<OAuthCredentials> {
181
+ if (ctrl.signal?.aborted) {
182
+ throw ctrl.signal.reason ?? new DOMException("Command Code login aborted", "AbortError");
183
+ }
184
+ if (shouldImportLocalCommandCodeAuth(options)) {
185
+ const local = await importLocalCommandCodeAuth(ctrl.signal);
186
+ if (local) {
187
+ ctrl.onProgress?.("Imported existing Command Code CLI authentication.");
188
+ return local;
189
+ }
190
+ }
191
+ const state = randomState();
192
+ let servers: Array<ReturnType<typeof Bun.serve>> = [];
193
+ let timeoutId: ReturnType<typeof setTimeout> | undefined;
194
+ try {
195
+ const created = createCallbackServer(state);
196
+ servers = created.servers;
197
+ const callbackUrl = `http://127.0.0.1:${servers[0].port}${CALLBACK_PATH}`;
198
+ const authUrl = `${COMMAND_CODE_STUDIO_URL}/studio/auth/cli?callback=${encodeURIComponent(callbackUrl)}&state=${encodeURIComponent(state)}`;
199
+ ctrl.onAuth?.({ url: authUrl, instructions: "Sign in with Command Code in the browser." });
200
+ ctrl.onProgress?.("Waiting for Command Code authentication...");
201
+ const timeout = new Promise<never>((_, reject) => {
202
+ timeoutId = setTimeout(() => reject(new Error("Command Code OAuth callback timed out")), LOGIN_TIMEOUT_MS);
203
+ ctrl.signal?.addEventListener("abort", () => { if (timeoutId) clearTimeout(timeoutId); reject(ctrl.signal?.reason); }, { once: true });
204
+ });
205
+ const manual = ctrl.onManualCodeInput
206
+ ? (async (): Promise<CommandCodeCallback> => {
207
+ while (true) {
208
+ // The loop keeps waiting until a valid paste arrives; invalid pastes re-prompt.
209
+ // Yield between iterations so an abort signal can interrupt a fast re-prompt loop.
210
+ if (ctrl.signal?.aborted) throw ctrl.signal.reason ?? new DOMException("Command Code login aborted", "AbortError");
211
+ const input = await ctrl.onManualCodeInput?.(state);
212
+ if (input === undefined) continue;
213
+ const pasted = parsePastedCommandCodeInput(input, state);
214
+ if (!pasted) continue;
215
+ const identity = await validatePastedApiKey(pasted.apiKey);
216
+ if (identity) return { ...pasted, ...identity };
217
+ await new Promise(resolve => setTimeout(resolve, 0));
218
+ }
219
+ })()
220
+ : undefined;
221
+ const result = await Promise.race([created.callback, timeout, ...(manual ? [manual] : [])]);
222
+ if (result === undefined) throw new Error("Command Code OAuth callback cancelled");
223
+ return {
224
+ access: result.apiKey,
225
+ refresh: result.apiKey,
226
+ expires: Number.MAX_SAFE_INTEGER,
227
+ accountId: result.userId,
228
+ source: "oauth",
229
+ };
230
+ } finally {
231
+ if (timeoutId) clearTimeout(timeoutId);
232
+ for (const server of servers) server.stop(true);
233
+ }
234
+ }
235
+
236
+ export async function refreshCommandCodeToken(apiKey: string): Promise<OAuthCredentials> {
237
+ if (!apiKey) throw new Error("Command Code API key missing; run ocx login command-code");
238
+ return { access: apiKey, refresh: apiKey, expires: Number.MAX_SAFE_INTEGER, source: "oauth" };
239
+ }
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Cursor OAuth — PKCE poll flow. Standalone: talks directly to cursor.com / api2.cursor.sh,
3
+ * with no dependency on a local Cursor IDE/CLI install or on jawcode. Ported from jawcode
4
+ * packages/ai/src/utils/oauth/cursor.ts and adapted to opencodex's OAuthController (see kimi.ts).
5
+ *
6
+ * Security: the login URL carries only the PKCE challenge (SHA-256 of the verifier); the verifier
7
+ * is sent only to /auth/poll. Tokens and the verifier are never logged — thrown errors and progress
8
+ * messages are status/string only.
9
+ */
10
+ import { generatePKCE } from "./pkce";
11
+ import type { OAuthController, OAuthCredentials } from "./types";
12
+
13
+ const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
14
+ const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
15
+ const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
16
+
17
+ const POLL_MAX_ATTEMPTS = 150;
18
+ const POLL_BASE_DELAY_MS = 1000;
19
+ const POLL_MAX_DELAY_MS = 10_000;
20
+ const POLL_BACKOFF = 1.2;
21
+ const EXPIRY_SKEW_MS = 5 * 60 * 1000;
22
+ const FALLBACK_TTL_MS = 60 * 60 * 1000;
23
+
24
+ const REFRESH_TIMEOUT_MS = 15_000;
25
+ const REFRESH_ATTEMPTS = 3;
26
+ const REFRESH_RETRY_BASE_MS = 300;
27
+
28
+ export interface CursorAuthParams {
29
+ verifier: string;
30
+ challenge: string;
31
+ uuid: string;
32
+ loginUrl: string;
33
+ }
34
+
35
+ interface CursorJwtPayload {
36
+ sub?: unknown;
37
+ email?: unknown;
38
+ exp?: unknown;
39
+ }
40
+
41
+ function decodeCursorJwtPayload(token: string): CursorJwtPayload | undefined {
42
+ const parts = token.split(".");
43
+ const payload = parts[1];
44
+ if (parts.length !== 3 || !payload) return undefined;
45
+ try {
46
+ return JSON.parse(Buffer.from(payload, "base64url").toString("utf-8")) as CursorJwtPayload;
47
+ } catch {
48
+ return undefined;
49
+ }
50
+ }
51
+
52
+ /** Build OAuthCredentials from Cursor tokens, extracting stable identity from JWT `sub` for multiauth. */
53
+ export function credentialsFromCursorTokens(accessToken: string, refreshToken: string): OAuthCredentials {
54
+ const payload = decodeCursorJwtPayload(accessToken) ?? decodeCursorJwtPayload(refreshToken);
55
+ const accountId = cursorJwtIdentity(payload?.sub);
56
+ const email = cursorJwtEmail(payload?.email);
57
+ return {
58
+ access: accessToken,
59
+ refresh: refreshToken,
60
+ expires: getTokenExpiry(accessToken),
61
+ ...(accountId ? { accountId } : {}),
62
+ ...(email ? { email } : {}),
63
+ };
64
+ }
65
+
66
+ /** Coerce JWT `sub` (string or safe integer) into a stable multiauth account id. */
67
+ function cursorJwtIdentity(value: unknown): string | undefined {
68
+ if (typeof value === "string" && value.length > 0) return value;
69
+ if (typeof value === "number" && Number.isSafeInteger(value)) return String(value);
70
+ return undefined;
71
+ }
72
+
73
+ function cursorJwtEmail(value: unknown): string | undefined {
74
+ if (typeof value !== "string" || value.length === 0) return undefined;
75
+ return value.toLowerCase();
76
+ }
77
+
78
+ /** Generate PKCE params + the cursor.com deep-link login URL (challenge only — never the verifier). */
79
+ export async function generateCursorAuthParams(_opts?: { forceLogin?: boolean }): Promise<CursorAuthParams> {
80
+ const { verifier, challenge } = await generatePKCE();
81
+ const uuid = crypto.randomUUID();
82
+ // Cursor's deep-control page has no documented account-picker query; only the stable
83
+ // PKCE params are sent. forceLogin is honored only in loginCursor instructions.
84
+ const params = new URLSearchParams({ challenge, uuid, mode: "login", redirectTarget: "cli" });
85
+ return { verifier, challenge, uuid, loginUrl: `${CURSOR_LOGIN_URL}?${params.toString()}` };
86
+ }
87
+
88
+ /** Abort-aware delay (mirrors kimi.ts) — rejects if the controller signal aborts. */
89
+ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
90
+ return new Promise((resolve, reject) => {
91
+ if (signal?.aborted) return reject(new Error("Cursor login cancelled"));
92
+ const timer = setTimeout(resolve, ms);
93
+ signal?.addEventListener(
94
+ "abort",
95
+ () => {
96
+ clearTimeout(timer);
97
+ reject(new Error("Cursor login cancelled"));
98
+ },
99
+ { once: true },
100
+ );
101
+ });
102
+ }
103
+
104
+ /** Terminal poll statuses (T07, senpi PR #905): the login is denied/expired — retrying cannot succeed. */
105
+ const POLL_TERMINAL_STATUSES = new Set([400, 401, 403, 410]);
106
+
107
+ export class CursorAuthTerminalError extends Error {
108
+ readonly status: number;
109
+
110
+ constructor(status: number) {
111
+ super(`Cursor login rejected by the auth server (HTTP ${status}); start a new login`);
112
+ this.name = "CursorAuthTerminalError";
113
+ this.status = status;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Poll cursor.com for login completion. 404 = still pending (back off), 200 = tokens.
119
+ * `baseDelayMs` is injectable so tests can avoid the real 1s cadence; production uses the default.
120
+ */
121
+ export async function pollCursorAuth(
122
+ uuid: string,
123
+ verifier: string,
124
+ signal?: AbortSignal,
125
+ baseDelayMs: number = POLL_BASE_DELAY_MS,
126
+ ): Promise<{ accessToken: string; refreshToken: string }> {
127
+ let delay = baseDelayMs;
128
+ let consecutiveErrors = 0;
129
+
130
+ for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
131
+ await sleep(delay, signal);
132
+
133
+ try {
134
+ const url = `${CURSOR_POLL_URL}?uuid=${encodeURIComponent(uuid)}&verifier=${encodeURIComponent(verifier)}`;
135
+ const response = await fetch(url, { signal });
136
+
137
+ if (response.status === 404) {
138
+ consecutiveErrors = 0;
139
+ delay = Math.min(delay * POLL_BACKOFF, POLL_MAX_DELAY_MS);
140
+ continue;
141
+ }
142
+
143
+ if (response.ok) {
144
+ const data = (await response.json()) as { accessToken?: string; refreshToken?: string };
145
+ if (!data.accessToken || !data.refreshToken) {
146
+ throw new Error("Cursor auth response missing tokens");
147
+ }
148
+ return { accessToken: data.accessToken, refreshToken: data.refreshToken };
149
+ }
150
+
151
+ // T07: a terminal auth status means the login attempt itself is dead (denied,
152
+ // expired, revoked). Fail on the FIRST such response instead of burning the
153
+ // 3-strike retry budget and masking the reason behind a generic error.
154
+ if (POLL_TERMINAL_STATUSES.has(response.status)) {
155
+ throw new CursorAuthTerminalError(response.status);
156
+ }
157
+
158
+ throw new Error(`Cursor auth poll failed: ${response.status}`);
159
+ } catch (err) {
160
+ if (signal?.aborted) throw err instanceof Error ? err : new Error("Cursor login cancelled");
161
+ if (err instanceof CursorAuthTerminalError) throw err;
162
+ consecutiveErrors++;
163
+ if (consecutiveErrors >= 3) {
164
+ throw new Error("Too many consecutive errors during Cursor auth polling");
165
+ }
166
+ delay = Math.min(delay * POLL_BACKOFF, POLL_MAX_DELAY_MS);
167
+ }
168
+ }
169
+
170
+ throw new Error("Cursor authentication polling timeout");
171
+ }
172
+
173
+ /** Run the standalone Cursor login: surface the URL via `onAuth`, then poll until approved. */
174
+ export async function loginCursor(
175
+ ctrl: OAuthController,
176
+ pollBaseDelayMs: number = POLL_BASE_DELAY_MS,
177
+ opts?: { forceLogin?: boolean },
178
+ ): Promise<OAuthCredentials> {
179
+ const { verifier, uuid, loginUrl } = await generateCursorAuthParams({ forceLogin: opts?.forceLogin === true });
180
+ ctrl.onAuth?.({
181
+ url: loginUrl,
182
+ instructions: opts?.forceLogin
183
+ ? "Log out of Cursor in the browser (or use a private window), sign in as the account you want to add, then approve and return here."
184
+ : "Approve the Cursor login in your browser, then return here.",
185
+ });
186
+ ctrl.onProgress?.("Waiting for Cursor login approval…");
187
+ const { accessToken, refreshToken } = await pollCursorAuth(uuid, verifier, ctrl.signal, pollBaseDelayMs);
188
+ return credentialsFromCursorTokens(accessToken, refreshToken);
189
+ }
190
+
191
+ function isRetryableRefreshStatus(status: number): boolean {
192
+ return status === 429 || status === 500 || status === 502 || status === 503 || status === 504;
193
+ }
194
+
195
+ function refreshRetryDelayMs(attempt: number): number {
196
+ const exp = REFRESH_RETRY_BASE_MS * 2 ** attempt;
197
+ return Math.floor(exp * (0.8 + Math.random() * 0.4));
198
+ }
199
+
200
+ function refreshTimeoutSignal(parent: AbortSignal | undefined): AbortSignal {
201
+ const timeout = AbortSignal.timeout(REFRESH_TIMEOUT_MS);
202
+ return parent ? AbortSignal.any([parent, timeout]) : timeout;
203
+ }
204
+
205
+ /**
206
+ * Exchange a refresh token for fresh credentials. Keeps the old refresh if the server omits one.
207
+ *
208
+ * Hardened with a per-attempt timeout and bounded retry on transient failures (network errors and
209
+ * 429/5xx). Non-retryable statuses (e.g. 401/403 from an expired refresh token) fail fast so the
210
+ * caller can surface a re-auth prompt. Errors never include the token value.
211
+ */
212
+ export async function refreshCursorToken(refresh: string, signal?: AbortSignal): Promise<OAuthCredentials> {
213
+ let lastError: unknown;
214
+ for (let attempt = 0; attempt < REFRESH_ATTEMPTS; attempt++) {
215
+ if (signal?.aborted) throw signal.reason ?? new Error("Cursor token refresh aborted");
216
+ let response: Response;
217
+ try {
218
+ response = await fetch(CURSOR_REFRESH_URL, {
219
+ method: "POST",
220
+ headers: { Authorization: `Bearer ${refresh}`, "Content-Type": "application/json" },
221
+ body: "{}",
222
+ signal: refreshTimeoutSignal(signal),
223
+ });
224
+ } catch (err) {
225
+ // Network/timeout error: retry unless the caller aborted or we are out of attempts.
226
+ if (signal?.aborted) throw err;
227
+ lastError = err;
228
+ if (attempt === REFRESH_ATTEMPTS - 1) break;
229
+ await new Promise(resolve => setTimeout(resolve, refreshRetryDelayMs(attempt)));
230
+ continue;
231
+ }
232
+ if (response.ok) {
233
+ const data = (await response.json()) as { accessToken?: string; refreshToken?: string };
234
+ if (!data.accessToken) throw new Error("Cursor refresh response missing access token");
235
+ return credentialsFromCursorTokens(data.accessToken, data.refreshToken || refresh);
236
+ }
237
+ if (!isRetryableRefreshStatus(response.status) || attempt === REFRESH_ATTEMPTS - 1) {
238
+ throw new Error(`Cursor token refresh failed: ${response.status}`);
239
+ }
240
+ lastError = new Error(`Cursor token refresh failed: ${response.status}`);
241
+ await response.body?.cancel().catch(() => {});
242
+ await new Promise(resolve => setTimeout(resolve, refreshRetryDelayMs(attempt)));
243
+ }
244
+ throw lastError instanceof Error ? lastError : new Error("Cursor token refresh failed");
245
+ }
246
+
247
+ /** Resolve a token's expiry (epoch ms) from its JWT `exp`, minus a 5-minute skew; ~1h fallback. */
248
+ export function getTokenExpiry(token: string): number {
249
+ const decoded = decodeCursorJwtPayload(token);
250
+ if (typeof decoded?.exp === "number") return decoded.exp * 1000 - EXPIRY_SKEW_MS;
251
+ return Date.now() + FALLBACK_TTL_MS;
252
+ }