@iislee/opencodex 2.11.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 (476) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/assets/architecture.png +0 -0
  4. package/assets/banner.png +0 -0
  5. package/assets/claude-code-models.gif +0 -0
  6. package/assets/codex-app-picker.png +0 -0
  7. package/bin/ocx.mjs +451 -0
  8. package/bin/package-main.mjs +9 -0
  9. package/gui/dist/assets/index-DTpMHS4F.js +67 -0
  10. package/gui/dist/assets/index-ZNVDE3C7.css +1 -0
  11. package/gui/dist/favicon.png +0 -0
  12. package/gui/dist/icons.svg +24 -0
  13. package/gui/dist/index.html +25 -0
  14. package/gui/dist/logo.png +0 -0
  15. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  16. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  17. package/gui/dist/provider-icons/antigravity.svg +1 -0
  18. package/gui/dist/provider-icons/claude-color.svg +1 -0
  19. package/gui/dist/provider-icons/claude.svg +1 -0
  20. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  21. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  22. package/gui/dist/provider-icons/copilot.svg +1 -0
  23. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  24. package/gui/dist/provider-icons/cursor.svg +2 -0
  25. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  26. package/gui/dist/provider-icons/discord.svg +1 -0
  27. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  28. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  29. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  30. package/gui/dist/provider-icons/gemini.svg +1 -0
  31. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  32. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  33. package/gui/dist/provider-icons/grok-color.svg +1 -0
  34. package/gui/dist/provider-icons/grok.svg +1 -0
  35. package/gui/dist/provider-icons/groq-color.svg +1 -0
  36. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  37. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  38. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  39. package/gui/dist/provider-icons/kiro.svg +14 -0
  40. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  41. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  42. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  43. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  44. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  45. package/gui/dist/provider-icons/openai.svg +1 -0
  46. package/gui/dist/provider-icons/opencode.svg +1 -0
  47. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  48. package/gui/dist/provider-icons/pi.svg +21 -0
  49. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  50. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  51. package/gui/dist/provider-icons/telegram.svg +1 -0
  52. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  53. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  54. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  55. package/package.json +102 -0
  56. package/src/AGENTS.md +28 -0
  57. package/src/adapters/anthropic-image-guard.ts +251 -0
  58. package/src/adapters/anthropic-image-normalize.ts +518 -0
  59. package/src/adapters/anthropic.ts +1003 -0
  60. package/src/adapters/azure.ts +36 -0
  61. package/src/adapters/base.ts +72 -0
  62. package/src/adapters/client-fingerprint.ts +59 -0
  63. package/src/adapters/cursor/arg-codec.ts +38 -0
  64. package/src/adapters/cursor/arg-normalize.ts +104 -0
  65. package/src/adapters/cursor/cursor-errors.ts +165 -0
  66. package/src/adapters/cursor/discovery.ts +276 -0
  67. package/src/adapters/cursor/effort-map.ts +127 -0
  68. package/src/adapters/cursor/exec-policy.ts +88 -0
  69. package/src/adapters/cursor/framing.ts +211 -0
  70. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  71. package/src/adapters/cursor/kv-store.ts +52 -0
  72. package/src/adapters/cursor/live-models.ts +153 -0
  73. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  74. package/src/adapters/cursor/live-transport.ts +1214 -0
  75. package/src/adapters/cursor/mcp-config.ts +42 -0
  76. package/src/adapters/cursor/mcp-manager.ts +333 -0
  77. package/src/adapters/cursor/message-mapper.ts +49 -0
  78. package/src/adapters/cursor/native-exec-common.ts +55 -0
  79. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  80. package/src/adapters/cursor/native-exec-fs.ts +329 -0
  81. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  82. package/src/adapters/cursor/native-exec-network.ts +43 -0
  83. package/src/adapters/cursor/native-exec-shell.ts +548 -0
  84. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  85. package/src/adapters/cursor/native-exec.ts +576 -0
  86. package/src/adapters/cursor/protobuf-events.ts +563 -0
  87. package/src/adapters/cursor/protobuf-request.ts +714 -0
  88. package/src/adapters/cursor/request-builder.ts +255 -0
  89. package/src/adapters/cursor/thread-continuity.ts +67 -0
  90. package/src/adapters/cursor/tool-definitions.ts +505 -0
  91. package/src/adapters/cursor/transport-retry.ts +132 -0
  92. package/src/adapters/cursor/transport.ts +57 -0
  93. package/src/adapters/cursor/types.ts +52 -0
  94. package/src/adapters/cursor.ts +196 -0
  95. package/src/adapters/google-antigravity-replay.ts +303 -0
  96. package/src/adapters/google-antigravity-wire.ts +108 -0
  97. package/src/adapters/google-errors.ts +85 -0
  98. package/src/adapters/google-http.ts +100 -0
  99. package/src/adapters/google-tool-schema.ts +173 -0
  100. package/src/adapters/google-truncation.ts +13 -0
  101. package/src/adapters/google-wire-compiler.ts +232 -0
  102. package/src/adapters/google.ts +758 -0
  103. package/src/adapters/identity.ts +44 -0
  104. package/src/adapters/image.ts +23 -0
  105. package/src/adapters/kiro-constants.ts +16 -0
  106. package/src/adapters/kiro-errors.ts +197 -0
  107. package/src/adapters/kiro-events.ts +179 -0
  108. package/src/adapters/kiro-images.ts +129 -0
  109. package/src/adapters/kiro-retry.ts +312 -0
  110. package/src/adapters/kiro-thinking.ts +96 -0
  111. package/src/adapters/kiro-tool-fallback.ts +36 -0
  112. package/src/adapters/kiro-tools.ts +215 -0
  113. package/src/adapters/kiro-truncation.ts +33 -0
  114. package/src/adapters/kiro-wire.ts +129 -0
  115. package/src/adapters/kiro.ts +1898 -0
  116. package/src/adapters/mimo-free.ts +263 -0
  117. package/src/adapters/openai-chat.ts +1005 -0
  118. package/src/adapters/openai-responses.ts +1137 -0
  119. package/src/adapters/run-turn-queue.ts +114 -0
  120. package/src/adapters/tool-catalog-nudge.ts +71 -0
  121. package/src/adapters/upstream-http-error.ts +48 -0
  122. package/src/bridge.ts +1619 -0
  123. package/src/chat/inbound.ts +295 -0
  124. package/src/chat/outbound.ts +765 -0
  125. package/src/claude/agents-inject.ts +243 -0
  126. package/src/claude/alias.ts +149 -0
  127. package/src/claude/auth-detect.ts +229 -0
  128. package/src/claude/auth-mode-migration.ts +32 -0
  129. package/src/claude/auth-mode.ts +62 -0
  130. package/src/claude/context-windows.ts +189 -0
  131. package/src/claude/desktop-3p-guard.ts +35 -0
  132. package/src/claude/desktop-3p-paths.ts +84 -0
  133. package/src/claude/desktop-3p.ts +381 -0
  134. package/src/claude/desktop-health.ts +26 -0
  135. package/src/claude/desktop-profile.ts +263 -0
  136. package/src/claude/gateway-cache.ts +70 -0
  137. package/src/claude/inbound-debug.ts +163 -0
  138. package/src/claude/inbound.ts +509 -0
  139. package/src/claude/model-info.ts +151 -0
  140. package/src/claude/outbound.ts +872 -0
  141. package/src/cli/access.ts +108 -0
  142. package/src/cli/account-api.ts +268 -0
  143. package/src/cli/account-auth.ts +223 -0
  144. package/src/cli/account-extended.ts +350 -0
  145. package/src/cli/account.ts +275 -0
  146. package/src/cli/agent-driven.ts +70 -0
  147. package/src/cli/agent.ts +184 -0
  148. package/src/cli/catalog-prewarm.ts +27 -0
  149. package/src/cli/claude-desktop.ts +188 -0
  150. package/src/cli/claude.ts +286 -0
  151. package/src/cli/codex-shim-autorestore.ts +45 -0
  152. package/src/cli/combo.ts +119 -0
  153. package/src/cli/config-command.ts +145 -0
  154. package/src/cli/debug.ts +228 -0
  155. package/src/cli/doctor.ts +930 -0
  156. package/src/cli/export-command.ts +187 -0
  157. package/src/cli/help.ts +354 -0
  158. package/src/cli/index.ts +1113 -0
  159. package/src/cli/init.ts +224 -0
  160. package/src/cli/integrations.ts +142 -0
  161. package/src/cli/interactive-confirm.ts +133 -0
  162. package/src/cli/internal-dispatch.ts +20 -0
  163. package/src/cli/models-runtime.ts +212 -0
  164. package/src/cli/models.ts +336 -0
  165. package/src/cli/observe.ts +117 -0
  166. package/src/cli/opencode.ts +586 -0
  167. package/src/cli/pi.ts +188 -0
  168. package/src/cli/provider-runtime.ts +162 -0
  169. package/src/cli/provider.ts +463 -0
  170. package/src/cli/runtime-api.ts +325 -0
  171. package/src/cli/star-prompt.ts +155 -0
  172. package/src/cli/status-oauth.ts +78 -0
  173. package/src/cli/status.ts +321 -0
  174. package/src/cli/sync-cloud.ts +283 -0
  175. package/src/cli/system-command.ts +112 -0
  176. package/src/cli/tray-proxy.ts +52 -0
  177. package/src/cli/v2.ts +173 -0
  178. package/src/cli.ts +10 -0
  179. package/src/clients/config-export.ts +377 -0
  180. package/src/clients/effective-status.ts +385 -0
  181. package/src/clients/probes/agy.ts +55 -0
  182. package/src/clients/probes/cc-switch.ts +110 -0
  183. package/src/clients/probes/claude.ts +90 -0
  184. package/src/clients/probes/codex.ts +125 -0
  185. package/src/clients/probes/grok.ts +29 -0
  186. package/src/clients/probes/opencode.ts +109 -0
  187. package/src/clients/probes/paseo.ts +55 -0
  188. package/src/clients/probes/pi.ts +55 -0
  189. package/src/cloud/onedrive-auth.ts +666 -0
  190. package/src/cloud/onedrive-graph.ts +108 -0
  191. package/src/cloud/settings.ts +75 -0
  192. package/src/cloud/sync.ts +212 -0
  193. package/src/cloud/types.ts +56 -0
  194. package/src/cloud/vault.ts +89 -0
  195. package/src/codex/account-id.ts +34 -0
  196. package/src/codex/account-label.ts +34 -0
  197. package/src/codex/account-lifecycle.ts +55 -0
  198. package/src/codex/account-namespace-match.ts +63 -0
  199. package/src/codex/account-namespaces.ts +149 -0
  200. package/src/codex/account-pause.ts +20 -0
  201. package/src/codex/account-runtime-state.ts +31 -0
  202. package/src/codex/account-store.ts +517 -0
  203. package/src/codex/account-usability.ts +20 -0
  204. package/src/codex/app-server-processes.ts +756 -0
  205. package/src/codex/auth-api.ts +1540 -0
  206. package/src/codex/auth-collision.ts +107 -0
  207. package/src/codex/auth-context.ts +352 -0
  208. package/src/codex/autostart-health.ts +149 -0
  209. package/src/codex/catalog/aggregation.ts +378 -0
  210. package/src/codex/catalog/bundled.ts +251 -0
  211. package/src/codex/catalog/effort.ts +355 -0
  212. package/src/codex/catalog/metadata.ts +180 -0
  213. package/src/codex/catalog/parsing.ts +456 -0
  214. package/src/codex/catalog/provider-fetch.ts +902 -0
  215. package/src/codex/catalog/sync.ts +620 -0
  216. package/src/codex/catalog.ts +12 -0
  217. package/src/codex/data/upstream-models.json +830 -0
  218. package/src/codex/exec-invocation.ts +22 -0
  219. package/src/codex/features.ts +969 -0
  220. package/src/codex/history-migration-guardian.ts +102 -0
  221. package/src/codex/history-provider.ts +776 -0
  222. package/src/codex/home.ts +206 -0
  223. package/src/codex/inject.ts +799 -0
  224. package/src/codex/injected-marker.ts +72 -0
  225. package/src/codex/journal.ts +163 -0
  226. package/src/codex/main-account-cache.ts +32 -0
  227. package/src/codex/main-account.ts +40 -0
  228. package/src/codex/model-cache.ts +227 -0
  229. package/src/codex/paths.ts +65 -0
  230. package/src/codex/plugins-doctor.ts +242 -0
  231. package/src/codex/pool-rotation.ts +225 -0
  232. package/src/codex/project-config-warnings.ts +411 -0
  233. package/src/codex/quota.ts +411 -0
  234. package/src/codex/refresh.ts +53 -0
  235. package/src/codex/routing.ts +1477 -0
  236. package/src/codex/runtime.ts +538 -0
  237. package/src/codex/shim.ts +1189 -0
  238. package/src/codex/subagent-defaults.ts +550 -0
  239. package/src/codex/subagent-model-fallback.ts +469 -0
  240. package/src/codex/sync.ts +130 -0
  241. package/src/codex/warmup.ts +192 -0
  242. package/src/codex/websocket-registry.ts +100 -0
  243. package/src/combos/failover.ts +140 -0
  244. package/src/combos/index.ts +41 -0
  245. package/src/combos/request.ts +62 -0
  246. package/src/combos/resolve.ts +232 -0
  247. package/src/combos/types.ts +326 -0
  248. package/src/config.ts +2356 -0
  249. package/src/generated/jawcode-model-metadata.ts +104 -0
  250. package/src/github/star-state.ts +203 -0
  251. package/src/grok/inject.ts +545 -0
  252. package/src/grok/status.ts +121 -0
  253. package/src/grok/sync.ts +103 -0
  254. package/src/grok/usage-hook/report.mjs +348 -0
  255. package/src/grok/usage-hook.ts +278 -0
  256. package/src/images/artifacts.ts +516 -0
  257. package/src/images/fulfill-video.ts +163 -0
  258. package/src/images/fulfill.ts +149 -0
  259. package/src/images/index.ts +4 -0
  260. package/src/images/loop.ts +829 -0
  261. package/src/images/plan.ts +133 -0
  262. package/src/images/synthetic-tool.ts +133 -0
  263. package/src/images/types.ts +41 -0
  264. package/src/images/xai-client.ts +141 -0
  265. package/src/images/xai-video-client.ts +163 -0
  266. package/src/index.ts +22 -0
  267. package/src/lib/abort.ts +146 -0
  268. package/src/lib/admin-secrets.ts +25 -0
  269. package/src/lib/admission.ts +83 -0
  270. package/src/lib/app-owned-memory-stores.ts +173 -0
  271. package/src/lib/app-owned-memory.ts +265 -0
  272. package/src/lib/bounded-body.ts +202 -0
  273. package/src/lib/bun-binary-validator.d.mts +3 -0
  274. package/src/lib/bun-binary-validator.mjs +18 -0
  275. package/src/lib/bun-runtime.ts +71 -0
  276. package/src/lib/bun-stream-caps.ts +126 -0
  277. package/src/lib/config-ownership.ts +360 -0
  278. package/src/lib/crash-guard.ts +344 -0
  279. package/src/lib/debug-log-buffer.ts +83 -0
  280. package/src/lib/debug-settings.ts +108 -0
  281. package/src/lib/debug.ts +31 -0
  282. package/src/lib/destination-policy.ts +316 -0
  283. package/src/lib/errors.ts +364 -0
  284. package/src/lib/eventstream-decoder.ts +253 -0
  285. package/src/lib/gcp-adc.ts +341 -0
  286. package/src/lib/injection-debug-log.ts +58 -0
  287. package/src/lib/open-url.ts +25 -0
  288. package/src/lib/pinned-http.ts +151 -0
  289. package/src/lib/privacy.ts +20 -0
  290. package/src/lib/process-control.ts +165 -0
  291. package/src/lib/provider-outbound.ts +170 -0
  292. package/src/lib/provider-url.ts +14 -0
  293. package/src/lib/proxy-env.ts +18 -0
  294. package/src/lib/redact.ts +105 -0
  295. package/src/lib/retry-after.ts +55 -0
  296. package/src/lib/service-secrets.ts +25 -0
  297. package/src/lib/shadow-call.ts +30 -0
  298. package/src/lib/sidecar-tracker.ts +52 -0
  299. package/src/lib/sse-decoder.ts +323 -0
  300. package/src/lib/state-store-registrations.ts +109 -0
  301. package/src/lib/state-store-sweeper.ts +184 -0
  302. package/src/lib/test-home-guard.ts +90 -0
  303. package/src/lib/token-estimate.ts +69 -0
  304. package/src/lib/translator-budget.ts +356 -0
  305. package/src/lib/upstream-retry.ts +239 -0
  306. package/src/lib/win-exec.ts +115 -0
  307. package/src/lib/win-paths.ts +68 -0
  308. package/src/lib/windows-elevation.ts +705 -0
  309. package/src/lib/windows-secret-acl.ts +514 -0
  310. package/src/lib/winsw.ts +375 -0
  311. package/src/oauth/anthropic-routing.ts +594 -0
  312. package/src/oauth/anthropic.ts +177 -0
  313. package/src/oauth/callback-server.ts +294 -0
  314. package/src/oauth/chatgpt.ts +150 -0
  315. package/src/oauth/cursor.ts +211 -0
  316. package/src/oauth/github-copilot.ts +428 -0
  317. package/src/oauth/google-antigravity.ts +230 -0
  318. package/src/oauth/health.ts +399 -0
  319. package/src/oauth/index.ts +1174 -0
  320. package/src/oauth/key-providers.ts +108 -0
  321. package/src/oauth/kimi.ts +213 -0
  322. package/src/oauth/kiro-credentials.ts +726 -0
  323. package/src/oauth/kiro.ts +577 -0
  324. package/src/oauth/local-token-detect.ts +121 -0
  325. package/src/oauth/log.ts +48 -0
  326. package/src/oauth/login-cli.ts +163 -0
  327. package/src/oauth/pkce.ts +15 -0
  328. package/src/oauth/store.ts +630 -0
  329. package/src/oauth/token-guardian.ts +303 -0
  330. package/src/oauth/types.ts +62 -0
  331. package/src/oauth/xai.ts +241 -0
  332. package/src/pi/extensions.ts +72 -0
  333. package/src/pi/home.ts +42 -0
  334. package/src/pi/index.ts +40 -0
  335. package/src/pi/models.ts +278 -0
  336. package/src/pi/packages.ts +219 -0
  337. package/src/pi/settings.ts +365 -0
  338. package/src/pi/status.ts +68 -0
  339. package/src/pi/sync.ts +75 -0
  340. package/src/providers/alibaba-region-backup.ts +75 -0
  341. package/src/providers/alibaba-region-migration.ts +156 -0
  342. package/src/providers/alibaba-region-startup.ts +36 -0
  343. package/src/providers/antigravity-models.ts +205 -0
  344. package/src/providers/api-keys.ts +140 -0
  345. package/src/providers/base-url-choices.ts +64 -0
  346. package/src/providers/context-cap.ts +65 -0
  347. package/src/providers/derive.ts +339 -0
  348. package/src/providers/free-directory.ts +184 -0
  349. package/src/providers/github-copilot-transport.ts +56 -0
  350. package/src/providers/key-failover.ts +203 -0
  351. package/src/providers/kiro-models.ts +67 -0
  352. package/src/providers/label.ts +19 -0
  353. package/src/providers/model-discovery.ts +356 -0
  354. package/src/providers/openai-sidecar.ts +175 -0
  355. package/src/providers/openai-tier-startup.ts +27 -0
  356. package/src/providers/openai-tiers.ts +301 -0
  357. package/src/providers/openai-virtual-models.ts +82 -0
  358. package/src/providers/openrouter-routing.ts +102 -0
  359. package/src/providers/provider-id-rewrite.ts +150 -0
  360. package/src/providers/quota.ts +1260 -0
  361. package/src/providers/registry.ts +1600 -0
  362. package/src/providers/slug-codec.ts +67 -0
  363. package/src/providers/xai-transport.ts +141 -0
  364. package/src/reasoning-effort.ts +135 -0
  365. package/src/responses/compaction.ts +117 -0
  366. package/src/responses/parser.ts +656 -0
  367. package/src/responses/reasoning-envelope.ts +52 -0
  368. package/src/responses/schema.ts +159 -0
  369. package/src/responses/spill-store.ts +394 -0
  370. package/src/responses/state.ts +895 -0
  371. package/src/responses/tool-groups.ts +19 -0
  372. package/src/router.ts +425 -0
  373. package/src/server/adapter-resolve.ts +80 -0
  374. package/src/server/auth-cors.ts +530 -0
  375. package/src/server/chat-completions.ts +368 -0
  376. package/src/server/claude-messages.ts +914 -0
  377. package/src/server/effort-policy.ts +172 -0
  378. package/src/server/gui-static.ts +123 -0
  379. package/src/server/image-retry.ts +42 -0
  380. package/src/server/images.ts +476 -0
  381. package/src/server/index.ts +1126 -0
  382. package/src/server/lifecycle.ts +227 -0
  383. package/src/server/live.ts +598 -0
  384. package/src/server/management/agent-settings-routes.ts +1169 -0
  385. package/src/server/management/api-access.ts +141 -0
  386. package/src/server/management/api-key-usage.ts +167 -0
  387. package/src/server/management/body.ts +35 -0
  388. package/src/server/management/clients-routes.ts +63 -0
  389. package/src/server/management/cloud-sync-routes.ts +266 -0
  390. package/src/server/management/combo-routes.ts +220 -0
  391. package/src/server/management/config-routes.ts +422 -0
  392. package/src/server/management/context.ts +31 -0
  393. package/src/server/management/logs-usage-routes.ts +707 -0
  394. package/src/server/management/model-routes.ts +525 -0
  395. package/src/server/management/oauth-account-routes.ts +563 -0
  396. package/src/server/management/provider-routes.ts +556 -0
  397. package/src/server/management/shared.ts +277 -0
  398. package/src/server/management/sidebar-routes.ts +90 -0
  399. package/src/server/management/system-restart.ts +179 -0
  400. package/src/server/management/system-routes.ts +117 -0
  401. package/src/server/management/usage-summary-cache.ts +86 -0
  402. package/src/server/management-api.ts +215 -0
  403. package/src/server/management-auth.ts +267 -0
  404. package/src/server/memory-watchdog.ts +156 -0
  405. package/src/server/port-reclaim.ts +307 -0
  406. package/src/server/ports.ts +116 -0
  407. package/src/server/proxy-liveness.ts +201 -0
  408. package/src/server/relay-eager.ts +313 -0
  409. package/src/server/relay.ts +1049 -0
  410. package/src/server/request-decompress.ts +132 -0
  411. package/src/server/request-log-conversation.ts +168 -0
  412. package/src/server/request-log.ts +1046 -0
  413. package/src/server/responses/collaboration.ts +354 -0
  414. package/src/server/responses/compact.ts +384 -0
  415. package/src/server/responses/core.ts +2758 -0
  416. package/src/server/responses/encrypted-payload.ts +308 -0
  417. package/src/server/responses/fetch-helpers.ts +157 -0
  418. package/src/server/responses/passthrough-error.ts +78 -0
  419. package/src/server/responses/terminal-guard.ts +230 -0
  420. package/src/server/responses/upstream-error.ts +48 -0
  421. package/src/server/responses-image-gen-repair.ts +132 -0
  422. package/src/server/responses-item-id-repair.ts +224 -0
  423. package/src/server/responses.ts +9 -0
  424. package/src/server/search.ts +136 -0
  425. package/src/server/sse-payload-rewrite.ts +175 -0
  426. package/src/server/startup-action-control.ts +308 -0
  427. package/src/server/startup-health-cache.ts +113 -0
  428. package/src/server/system-env.ts +413 -0
  429. package/src/server/windows-tcp-drop.ts +184 -0
  430. package/src/server/windows-tray-control.ts +41 -0
  431. package/src/server/ws-bridge.ts +471 -0
  432. package/src/service.ts +2554 -0
  433. package/src/stall-timeout.ts +20 -0
  434. package/src/storage/cleanup-job.ts +57 -0
  435. package/src/storage/cleanup.ts +3085 -0
  436. package/src/storage/policy-job.ts +457 -0
  437. package/src/storage/policy-scheduler.ts +40 -0
  438. package/src/storage/policy-worker.ts +59 -0
  439. package/src/storage/policy.ts +527 -0
  440. package/src/storage/restore-job.ts +299 -0
  441. package/src/storage/restore-worker.ts +58 -0
  442. package/src/storage/scanner.ts +238 -0
  443. package/src/storage/storage-mutation-coordinator.ts +139 -0
  444. package/src/storage/worker-lifecycle.ts +215 -0
  445. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  446. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  447. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  448. package/src/tray/assets/opencodex-tray.png +0 -0
  449. package/src/tray/windows-tray.ps1 +290 -0
  450. package/src/tray/windows.ts +730 -0
  451. package/src/types.ts +1237 -0
  452. package/src/update/badge.ts +72 -0
  453. package/src/update/index.ts +407 -0
  454. package/src/update/job.ts +1520 -0
  455. package/src/update/notify.ts +257 -0
  456. package/src/update/npm-invocation.d.mts +23 -0
  457. package/src/update/npm-invocation.mjs +94 -0
  458. package/src/update/tray-update-plan.d.mts +18 -0
  459. package/src/update/tray-update-plan.mjs +38 -0
  460. package/src/usage/cost.ts +0 -0
  461. package/src/usage/debug.ts +97 -0
  462. package/src/usage/expected-prices.ts +164 -0
  463. package/src/usage/log.ts +658 -0
  464. package/src/usage/summary.ts +585 -0
  465. package/src/usage/totals.ts +14 -0
  466. package/src/vision/anthropic-describe.ts +185 -0
  467. package/src/vision/describe.ts +125 -0
  468. package/src/vision/index.ts +467 -0
  469. package/src/web-search/anthropic-executor.ts +189 -0
  470. package/src/web-search/executor.ts +105 -0
  471. package/src/web-search/format-result.ts +89 -0
  472. package/src/web-search/index.ts +196 -0
  473. package/src/web-search/loop.ts +664 -0
  474. package/src/web-search/parse.ts +220 -0
  475. package/src/web-search/progress-stream.ts +342 -0
  476. package/src/web-search/synthetic-tool.ts +47 -0
@@ -0,0 +1,36 @@
1
+ import type { IncomingMeta, ProviderAdapter } from "./base";
2
+ import type { OcxParsedRequest, OcxProviderConfig } from "../types";
3
+ import { createResponsesPassthroughAdapter } from "./openai-responses";
4
+
5
+ export function createAzureAdapter(provider: OcxProviderConfig): ProviderAdapter & { passthrough: true } {
6
+ const inner = createResponsesPassthroughAdapter({
7
+ ...provider,
8
+ baseUrl: provider.baseUrl,
9
+ });
10
+
11
+ return {
12
+ ...inner,
13
+ name: "azure-openai",
14
+
15
+ async buildRequest(parsed: OcxParsedRequest, incoming: IncomingMeta) {
16
+ if (provider.authMode === "forward") {
17
+ throw new Error("azure-openai does not support forward auth mode");
18
+ }
19
+ if (typeof provider.apiKey !== "string" || provider.apiKey.trim() === "") {
20
+ throw new Error("azure-openai requires a non-empty apiKey");
21
+ }
22
+
23
+ const request = await inner.buildRequest(parsed, incoming);
24
+ const unresolvedPlaceholder = request.url.match(/\{[^}]*\}/)?.[0] ?? request.url.match(/[{}]/)?.[0];
25
+ if (unresolvedPlaceholder) {
26
+ throw new Error(`azure-openai baseUrl contains unresolved ${unresolvedPlaceholder} — set your real resource URL`);
27
+ }
28
+
29
+ const headers = { ...request.headers };
30
+ headers["api-key"] = provider.apiKey;
31
+ delete headers["Authorization"];
32
+ // The inner adapter always targets Azure's v1 API here, which needs no api-version query.
33
+ return { ...request, headers };
34
+ },
35
+ };
36
+ }
@@ -0,0 +1,72 @@
1
+ import type { AdapterEvent, OcxParsedRequest } from "../types";
2
+ import type { TranslatorBudget } from "../lib/translator-budget";
3
+
4
+ /** Metadata about the caller's incoming request, for auth-forwarding adapters. */
5
+ export interface IncomingMeta {
6
+ headers: Headers;
7
+ translatorBudget: TranslatorBudget;
8
+ abortSignal?: AbortSignal;
9
+ /**
10
+ * Image-normalization ladder bias for upstream-413 tightened retries: every image
11
+ * starts one tier lower (devlog/260714_image_normalization_pipeline/030). Only the
12
+ * anthropic adapter consumes it; others ignore it.
13
+ */
14
+ imageTierBias?: number;
15
+ }
16
+
17
+ export interface ProviderAdapter {
18
+ name: string;
19
+
20
+ /**
21
+ * Convert an already-read provider HTTP error into client-safe text. This hook must be pure and
22
+ * return fully redacted output: callers may pass untrusted provider headers and payload text.
23
+ */
24
+ formatErrorBody?(status: number, headers: Headers, payloadText: string): string;
25
+
26
+ /**
27
+ * Build the upstream request. May be async: adapters that resolve a short-lived credential
28
+ * (e.g. Vertex AI ADC token) return a Promise. Sync adapters return the object directly; callers
29
+ * must `await` the result (awaiting a non-Promise is a no-op).
30
+ */
31
+ buildRequest(parsed: OcxParsedRequest, incoming: IncomingMeta): AdapterRequest | Promise<AdapterRequest>;
32
+
33
+ fetchResponse?(request: AdapterRequest, ctx?: AdapterFetchContext): Promise<Response>;
34
+
35
+ parseStream(response: Response, budget: TranslatorBudget): AsyncGenerator<AdapterEvent>;
36
+ parseResponse?(response: Response, budget: TranslatorBudget): Promise<AdapterEvent[]>;
37
+ runTurn?(
38
+ parsed: OcxParsedRequest,
39
+ incoming: IncomingMeta,
40
+ emit: (event: AdapterEvent) => void,
41
+ ): Promise<void>;
42
+ }
43
+
44
+ export interface AdapterRequest {
45
+ url: string;
46
+ method: string;
47
+ headers: Record<string, string>;
48
+ body: string;
49
+ /** Releases observation of a serialized request body after its final fetch attempt settles. */
50
+ releaseBodyObservation?: () => void;
51
+ /** Exact reasoning parameter emitted by the adapter, for request-log diagnostics only. */
52
+ reasoningLog?: {
53
+ effectiveEffort: string;
54
+ wireField: "reasoning_effort" | "thinking_budget" | "thinking.type";
55
+ wireValue: string | number;
56
+ };
57
+ usageLog?: {
58
+ inputTokens?: number;
59
+ estimated?: boolean;
60
+ };
61
+ }
62
+
63
+ export interface AdapterFetchContext {
64
+ /** Remains attached to the returned response body after the response headers arrive. */
65
+ abortSignal?: AbortSignal;
66
+ /** Deadline for receiving response headers on each attempt, not for consuming the response body. */
67
+ timeoutMs?: number;
68
+ /** Return final non-2xx responses untouched so the caller can own the error-body read. */
69
+ returnRawErrors?: boolean;
70
+ /** Whether the upstream response will be consumed as a stream; adapters may select low-latency transport settings. */
71
+ stream?: boolean;
72
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * First-party client fingerprints.
3
+ *
4
+ * Routed OAuth providers reject — or quietly flag — requests whose header signature doesn't match
5
+ * the real first-party client that minted the token. Sending a valid OAuth token with an empty
6
+ * header set (or a giveaway literal UA like "antigravity") is a non-first-party signature. These
7
+ * constants mirror the headers the real Claude Code CLI and Antigravity CLI send, so the proxy's
8
+ * request fingerprint matches the credential.
9
+ *
10
+ * Pinned versions live HERE (single source) so they're trivial to bump. Values that need a live
11
+ * manifest fetch (Antigravity auto-updater) or a cryptographic billing signature (Claude cch) are
12
+ * intentionally NOT modeled — those are brittle and a wrong guess does more harm than the gap.
13
+ */
14
+ import { createHash } from "node:crypto";
15
+
16
+ // ── Claude Code CLI (matches Claude Code 2.1.63 / @anthropic-ai/sdk 0.74.0) ──
17
+ export const CLAUDE_CODE_HEADERS: Record<string, string> = {
18
+ "X-App": "cli",
19
+ "X-Stainless-Retry-Count": "0",
20
+ "X-Stainless-Runtime": "node",
21
+ "X-Stainless-Lang": "js",
22
+ "X-Stainless-Timeout": "600",
23
+ "X-Stainless-Arch": process.arch,
24
+ "X-Stainless-OS": process.platform,
25
+ "X-Stainless-Package-Version": "0.74.0",
26
+ "X-Stainless-Runtime-Version": process.version.slice(1),
27
+ };
28
+
29
+ /**
30
+ * Stable per-credential session id, matching Claude Code's `X-Claude-Code-Session-Id`. Real Claude
31
+ * Code keeps one session id per CLI session; we derive a deterministic UUIDv4-shaped id from the
32
+ * OAuth token so it stays stable across a conversation's turns without persisting state. The token
33
+ * itself never leaves this function (only its hash drives the id).
34
+ */
35
+ export function claudeCodeSessionId(token: string | undefined): string {
36
+ const seed = token && token.length > 0 ? token : "opencodex-anon";
37
+ const h = createHash("sha256").update(`claude-code-session:${seed}`, "utf8").digest("hex");
38
+ // Shape the hash into a v4-looking UUID (version nibble 4, variant nibble 8-b).
39
+ const variant = ((parseInt(h[16], 16) & 0x3) | 0x8).toString(16);
40
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-4${h.slice(13, 16)}-${variant}${h.slice(17, 20)}-${h.slice(20, 32)}`;
41
+ }
42
+
43
+ // ── Antigravity CLI ──
44
+ /** Pinned fallback Antigravity CLI version (real client fetches a manifest; we pin to avoid the network dependency). */
45
+ export const ANTIGRAVITY_CLI_VERSION = "1.0.13";
46
+ const ANTIGRAVITY_CLI_CLIENT_NAME = "aidev_client";
47
+ const ANTIGRAVITY_CLI_PLATFORM = "darwin/arm64";
48
+ /** Secondary Google API client UA the Antigravity client library reports. */
49
+ export const ANTIGRAVITY_GOOG_API_CLIENT_UA = "google-api-nodejs-client/10.3.0";
50
+
51
+ /**
52
+ * The real Antigravity CLI User-Agent, e.g.
53
+ * `antigravity/cli/1.0.13 (aidev_client; os_type=darwin; arch=arm64)`.
54
+ * A `GOOGLE_ANTIGRAVITY_USER_AGENT` override (set by the caller) takes precedence upstream.
55
+ */
56
+ export function antigravityUserAgent(version = ANTIGRAVITY_CLI_VERSION): string {
57
+ const [osType, arch] = ANTIGRAVITY_CLI_PLATFORM.split("/");
58
+ return `antigravity/cli/${version} (${ANTIGRAVITY_CLI_CLIENT_NAME}; os_type=${osType}; arch=${arch})`;
59
+ }
@@ -0,0 +1,38 @@
1
+ import { fromBinary, toBinary, toJson } from "@bufbuild/protobuf";
2
+ import { ValueSchema } from "@bufbuild/protobuf/wkt";
3
+ import { textDecoder } from "./native-exec-common";
4
+
5
+ function parseJsonText(text: string): unknown {
6
+ try {
7
+ return JSON.parse(text);
8
+ } catch {
9
+ return text;
10
+ }
11
+ }
12
+
13
+ function sameBytes(a: Uint8Array, b: Uint8Array): boolean {
14
+ if (a.length !== b.length) return false;
15
+ for (let i = 0; i < a.length; i++) {
16
+ if (a[i] !== b[i]) return false;
17
+ }
18
+ return true;
19
+ }
20
+
21
+ export function decodeCursorArgValue(value: Uint8Array): unknown {
22
+ try {
23
+ const parsed = fromBinary(ValueSchema, value);
24
+ if (!sameBytes(toBinary(ValueSchema, parsed), value)) throw new Error("not canonical protobuf Value bytes");
25
+ const jsonValue = toJson(ValueSchema, parsed);
26
+ return typeof jsonValue === "string" ? parseJsonText(jsonValue) : jsonValue;
27
+ } catch {
28
+ return parseJsonText(textDecoder.decode(value));
29
+ }
30
+ }
31
+
32
+ export function decodeCursorArgsMap(args: { [key: string]: Uint8Array } | undefined): Record<string, unknown> {
33
+ const out: Record<string, unknown> = {};
34
+ for (const [key, value] of Object.entries(args ?? {})) {
35
+ out[key] = decodeCursorArgValue(value);
36
+ }
37
+ return out;
38
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Schema-aware argument key normalization for Cursor tool calls.
3
+ *
4
+ * Cursor-trained models sometimes emit argument keys that differ from the tool's declared schema
5
+ * (e.g. `filepath` instead of `path`, `cmd` instead of `command`). This module maps common aliases
6
+ * to the canonical key name ONLY when the tool schema declares that canonical key. Keys already
7
+ * matching the schema are never touched.
8
+ *
9
+ * Derived from opencode-cursor reference (src/provider/tool-schema-compat.ts).
10
+ */
11
+
12
+ const KEY_ALIASES = new Map<string, string>([
13
+ ["filepath", "path"],
14
+ ["filename", "path"],
15
+ ["file", "path"],
16
+ ["targetpath", "path"],
17
+ ["directorypath", "path"],
18
+ ["dir", "path"],
19
+ ["folder", "path"],
20
+ ["directory", "path"],
21
+ ["targetdirectory", "path"],
22
+ ["targetfile", "path"],
23
+ ["globpattern", "pattern"],
24
+ ["filepattern", "pattern"],
25
+ ["searchpattern", "pattern"],
26
+ ["includepattern", "include"],
27
+ ["workingdirectory", "cwd"],
28
+ ["workdir", "cwd"],
29
+ ["currentdirectory", "cwd"],
30
+ ["cmd", "command"],
31
+ ["script", "command"],
32
+ ["shellcommand", "command"],
33
+ ["terminalcommand", "command"],
34
+ ["contents", "content"],
35
+ ["text", "content"],
36
+ ["body", "content"],
37
+ ["data", "content"],
38
+ ["payload", "content"],
39
+ ["streamcontent", "content"],
40
+ ["oldstring", "old_string"],
41
+ ["newstring", "new_string"],
42
+ ["oldtext", "old_string"],
43
+ ["newtext", "new_string"],
44
+ ["oldcontent", "old_string"],
45
+ ["newcontent", "new_string"],
46
+ ["recursive", "force"],
47
+ ]);
48
+
49
+ /**
50
+ * Extract the set of declared property names from a JSON Schema parameters object.
51
+ * Handles the common `{ type: "object", properties: { ... } }` shape.
52
+ */
53
+ function schemaPropertyNames(schema: unknown): Set<string> | undefined {
54
+ if (!schema || typeof schema !== "object") return undefined;
55
+ const obj = schema as Record<string, unknown>;
56
+ const props = obj.properties;
57
+ if (!props || typeof props !== "object") return undefined;
58
+ return new Set(Object.keys(props as Record<string, unknown>));
59
+ }
60
+
61
+ /**
62
+ * Normalize argument keys against the tool's declared schema. Keys not in the schema that have a
63
+ * known alias pointing to a schema-declared key are renamed. Explicitly supplied canonical keys
64
+ * always win over aliases, regardless of object property insertion order — conflicting aliases
65
+ * are discarded rather than left beside the canonical key.
66
+ *
67
+ * Returns the original object reference if no changes were needed (cheap identity check for callers).
68
+ */
69
+ export function normalizeArgKeys(args: Record<string, unknown>, toolSchema: unknown): Record<string, unknown> {
70
+ const declared = schemaPropertyNames(toolSchema);
71
+ if (!declared || declared.size === 0) return args;
72
+
73
+ const suppliedCanonical = new Set<string>();
74
+ for (const key of Object.keys(args)) {
75
+ if (declared.has(key)) suppliedCanonical.add(key);
76
+ }
77
+
78
+ let changed = false;
79
+ const result: Record<string, unknown> = {};
80
+ for (const [key, value] of Object.entries(args)) {
81
+ if (declared.has(key)) {
82
+ result[key] = value;
83
+ continue;
84
+ }
85
+ const canonical = KEY_ALIASES.get(key.toLowerCase());
86
+ if (canonical && declared.has(canonical)) {
87
+ // Canonical was explicitly supplied (any order) — drop the alias entirely.
88
+ if (suppliedCanonical.has(canonical)) {
89
+ changed = true;
90
+ continue;
91
+ }
92
+ // First alias fills the canonical slot; later aliases for the same key are discarded.
93
+ if (!(canonical in result)) {
94
+ result[canonical] = value;
95
+ changed = true;
96
+ } else {
97
+ changed = true;
98
+ }
99
+ continue;
100
+ }
101
+ result[key] = value;
102
+ }
103
+ return changed ? result : args;
104
+ }
@@ -0,0 +1,165 @@
1
+ import { redactSecretString } from "../../lib/redact";
2
+
3
+ const ABSOLUTE_PATH_PATTERN = /(?:\/Users\/[^ "';,]+|\/home\/[^ "';,]+|[A-Za-z]:\\Users\\[^ "';,]+)/g;
4
+ // Cursor error messages can contain raw credential key=value pairs beyond what the shared
5
+ // redactSecretString covers. We handle the additional transport-specific patterns locally.
6
+ const CURSOR_CREDENTIAL_PATTERN = /\b(authorization|auth[_-]?token|cursor[_-]?token)=([^&\s"',;]+)/gi;
7
+
8
+ function sanitize(value: string): string {
9
+ return redactSecretString(value)
10
+ .replace(CURSOR_CREDENTIAL_PATTERN, "$1=[REDACTED]")
11
+ .replace(ABSOLUTE_PATH_PATTERN, "[REDACTED_PATH]");
12
+ }
13
+
14
+ function errorMessage(value: unknown): string {
15
+ if (value instanceof Error) return value.message;
16
+ if (typeof value === "string") return value;
17
+ return String(value ?? "");
18
+ }
19
+
20
+ function errorCode(value: unknown): string {
21
+ if (typeof value !== "object" || !value || !("code" in value)) return "";
22
+ const code = (value as { code?: unknown }).code;
23
+ return code === undefined || code === null ? "" : String(code);
24
+ }
25
+
26
+ /**
27
+ * True when Cursor intentionally cancelled the HTTP/2 stream after a client-tool suspend.
28
+ * These are expected between multi-turn Responses bridge cycles, not upstream failures.
29
+ */
30
+ export function isCursorBenignCancelError(value: unknown): boolean {
31
+ const message = errorMessage(value).toLowerCase();
32
+ const code = errorCode(value).toUpperCase();
33
+ if (code === "NGHTTP2_CANCEL") return true;
34
+ if (message.includes("nghttp2_cancel")) return true;
35
+ if (message.includes("cursor stream suspended")) return true;
36
+ return false;
37
+ }
38
+
39
+ /**
40
+ * True when Cursor Connect rejected the turn with invalid_argument.
41
+ * Seen after stepCompleted on brittle external-model continuations.
42
+ */
43
+ export function isCursorInvalidArgumentError(value: unknown): boolean {
44
+ const code = errorCode(value).toLowerCase();
45
+ if (code === "invalid_argument") return true;
46
+ const message = errorMessage(value).toLowerCase();
47
+ return message.includes("invalid_argument");
48
+ }
49
+
50
+ const QUOTA_RATE_CUES = ["too many requests", "quota", "rate limit", "rate-limit", "throttl"];
51
+ const REQUEST_TOO_LARGE_PATTERNS: (string | RegExp)[] = [
52
+ "tool catalog too large",
53
+ "tool registration too large",
54
+ "too many tools",
55
+ "message too large",
56
+ "payload too large",
57
+ "request too large",
58
+ // Size cue required somewhere: a bare "request exceeds ... limit" (concurrency/quota
59
+ // shape) must NOT match, but "request body/size exceeds ... limit" and
60
+ // "request exceeds maximum allowed size" are deterministic overflow (WP3 r1/r2).
61
+ /request exceeds .*size/,
62
+ /request (?:body|size) exceeds .*(?:size|limit)/,
63
+ "maximum allowed size",
64
+ ];
65
+
66
+ /**
67
+ * True when a resource_exhausted detail names a request-size overflow rather than quota.
68
+ * Quota/rate cues are rejected FIRST: "resource_exhausted while loading tool catalog: quota
69
+ * exhausted" is rate limiting, not a too-large request, even though it mentions the catalog.
70
+ */
71
+ export function isCursorRequestTooLargeDetail(lowerMessage: string): boolean {
72
+ if (QUOTA_RATE_CUES.some(cue => lowerMessage.includes(cue))) return false;
73
+ return REQUEST_TOO_LARGE_PATTERNS.some(pattern =>
74
+ typeof pattern === "string" ? lowerMessage.includes(pattern) : pattern.test(lowerMessage),
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Classify a Cursor transport/Connect/gRPC error message into an actionable category.
80
+ * The returned prefix string is recognized by `src/lib/errors.ts` `classifyError` keywords,
81
+ * so bridge-level error mapping produces the right Codex error type (rate_limit, auth, etc.).
82
+ */
83
+ export function classifyCursorError(message: string): string {
84
+ const lower = message.toLowerCase();
85
+
86
+ if (isCursorBenignCancelError(message)) return "Cursor stream suspended";
87
+
88
+ if (
89
+ lower.includes("resource_exhausted") ||
90
+ lower.includes("resource exhausted")
91
+ ) {
92
+ // gRPC RESOURCE_EXHAUSTED is quota/rate exhaustion unless the detail names a
93
+ // request-size overflow (tool catalog/registration). Only the latter is a
94
+ // client-fixable 400; everything else surfaces as a 429 so Codex backs off
95
+ // instead of hammering retries (live evidence: 6x 400 retry storm, devlog
96
+ // 260723_cursor_context_continuity/000_plan.md).
97
+ return isCursorRequestTooLargeDetail(lower)
98
+ ? "Cursor resource limit exceeded"
99
+ : "Cursor rate limit exceeded";
100
+ }
101
+
102
+ if (
103
+ lower.includes("rate limit") ||
104
+ lower.includes("rate-limit") ||
105
+ lower.includes("too many requests") ||
106
+ lower.includes("throttling")
107
+ ) return "Cursor rate limit exceeded";
108
+
109
+ if (
110
+ lower.includes("unauthenticated") ||
111
+ lower.includes("unauthorized") ||
112
+ lower.includes("permission_denied") ||
113
+ lower.includes("permission denied") ||
114
+ lower.includes("forbidden") ||
115
+ lower.includes("invalid token") ||
116
+ lower.includes("expired token") ||
117
+ lower.includes("authentication") ||
118
+ lower.includes("access denied")
119
+ ) return "Cursor authentication failed";
120
+
121
+ if (
122
+ lower.includes("unavailable") ||
123
+ lower.includes("overloaded") ||
124
+ lower.includes("temporarily") ||
125
+ lower.includes("server is busy")
126
+ ) return "Cursor server overloaded";
127
+
128
+ if (
129
+ lower.includes("invalid") ||
130
+ lower.includes("not found") ||
131
+ lower.includes("unsupported") ||
132
+ lower.includes("malformed") ||
133
+ lower.includes("unimplemented")
134
+ ) return "Cursor invalid request";
135
+
136
+ if (
137
+ lower.includes("timed out") ||
138
+ lower.includes("timeout") ||
139
+ lower.includes("etimedout") ||
140
+ lower.includes("deadline")
141
+ ) return "Cursor request timed out";
142
+
143
+ if (
144
+ lower.includes("econnreset") ||
145
+ lower.includes("econnrefused") ||
146
+ lower.includes("goaway") ||
147
+ lower.includes("nghttp2") ||
148
+ lower.includes("socket hang up") ||
149
+ lower.includes("connection reset")
150
+ ) return "Cursor connection failed";
151
+
152
+ return "Cursor upstream error";
153
+ }
154
+
155
+ /**
156
+ * Produce a user-facing, secret-safe Cursor error message with an actionable category prefix.
157
+ * Mirrors `safeKiroErrorMessage` / `safeKiroHttpErrorMessage` in kiro-errors.ts.
158
+ */
159
+ export function safeCursorErrorMessage(rawMessage: string): string {
160
+ const prefix = classifyCursorError(rawMessage);
161
+ const detail = sanitize(rawMessage)
162
+ .replace(/resource[_ ]exhausted/gi, "resource limit exceeded")
163
+ .slice(0, 500);
164
+ return detail ? `${prefix}: ${detail}` : prefix;
165
+ }