@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,276 @@
1
+ import {
2
+ CANONICAL_EFFORT_SUFFIXES,
3
+ cursorModelEffortLadder,
4
+ cursorWireModelIdWithEffort,
5
+ } from "./effort-map";
6
+
7
+ export interface CursorModelInfo {
8
+ id: string;
9
+ contextWindow?: number;
10
+ supportsReasoningEffort?: boolean;
11
+ inputModalities?: string[];
12
+ }
13
+
14
+ export const CURSOR_DEFAULT_CONTEXT_WINDOW = 128_000;
15
+
16
+ const CURSOR_REASONING_EFFORTS = ["low", "medium", "high"] as const;
17
+ const CURSOR_DEFAULT_INPUT_MODALITIES = ["text", "image"] as const;
18
+ const CONTEXT_1M = 1_000_000;
19
+ const CONTEXT_GEMINI = 1_048_576;
20
+ const CONTEXT_272K = 272_000;
21
+ const CONTEXT_262K = 262_144;
22
+ const CONTEXT_256K = 256_000;
23
+ const CONTEXT_200K = 200_000;
24
+
25
+ export function inferCursorContextWindow(modelId: string): number {
26
+ const id = modelId.trim().toLowerCase();
27
+ if (id.includes("1m")) return CONTEXT_1M;
28
+ if (id.startsWith("gemini-")) return CONTEXT_1M;
29
+ if (id === "glm-5.2") return CONTEXT_1M;
30
+ if (id.startsWith("gpt-5.6-")) return CONTEXT_1M;
31
+ if (id.startsWith("gpt-5") || id === "gpt-5-codex") return CONTEXT_272K;
32
+ if (id.startsWith("grok-4.5")) return 500_000;
33
+ if (id.startsWith("grok-")) return CONTEXT_256K;
34
+ if (id.includes("claude")) return CONTEXT_200K;
35
+ return CURSOR_DEFAULT_CONTEXT_WINDOW;
36
+ }
37
+
38
+ function normalizeInputModalities(input: string[] | undefined): string[] {
39
+ const values = (input ?? [...CURSOR_DEFAULT_INPUT_MODALITIES])
40
+ .map(item => item.trim())
41
+ .filter(Boolean);
42
+ return values.length > 0 ? [...new Set(values)] : [...CURSOR_DEFAULT_INPUT_MODALITIES];
43
+ }
44
+
45
+ export function normalizeCursorModels(models: readonly CursorModelInfo[]): CursorModelInfo[] {
46
+ const byId = new Map<string, CursorModelInfo>();
47
+ for (const model of models) {
48
+ const id = model.id.trim();
49
+ if (!id || byId.has(id)) continue;
50
+ byId.set(id, {
51
+ id,
52
+ contextWindow: typeof model.contextWindow === "number" && model.contextWindow > 0
53
+ ? model.contextWindow
54
+ : inferCursorContextWindow(id),
55
+ supportsReasoningEffort: model.supportsReasoningEffort === true,
56
+ inputModalities: normalizeInputModalities(model.inputModalities),
57
+ });
58
+ }
59
+ return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
60
+ }
61
+
62
+ /**
63
+ * Strip the `cursor-` wire prefix that some Cursor GetUsableModels responses prepend to model ids
64
+ * (e.g. `cursor-grok-4.5-high` instead of `grok-4.5-high`). Applied at the comparison boundary
65
+ * so upstream wire ids stay verbatim everywhere else (issue #117).
66
+ */
67
+ function stripCursorWirePrefix(id: string): string {
68
+ return id.startsWith("cursor-") ? id.slice("cursor-".length) : id;
69
+ }
70
+
71
+ /**
72
+ * True when a configured Cursor base model should remain exposed after live GetUsableModels filtering.
73
+ * Live ids are full effort-suffixed variants (`claude-4.6-opus-high`); base ids match exactly, the
74
+ * ordinary `{base}-{effort}` form, or Cursor's current `{base-without-fast}-{effort}-fast` form.
75
+ */
76
+ export function isCursorModelAvailableForAccount(modelId: string, liveIds: readonly string[]): boolean {
77
+ return liveIds.some(raw => {
78
+ const id = stripCursorWirePrefix(raw);
79
+ if (id === modelId) return true;
80
+ for (const effort of CANONICAL_EFFORT_SUFFIXES) {
81
+ if (
82
+ id === `${modelId}-${effort}` ||
83
+ id === cursorWireModelIdWithEffort(modelId, effort)
84
+ ) return true;
85
+ }
86
+ return false;
87
+ });
88
+ }
89
+
90
+ /** Codex-facing id for Cursor's auto-router. Always kept in the catalog even when live discovery omits it. */
91
+ export const CURSOR_AUTO_MODEL_ID = "auto";
92
+
93
+ /** Cursor Router's public optimization modes (cost -> intelligence Pareto frontier). */
94
+ export const CURSOR_ROUTING_LEVELS = ["cost", "balance", "intelligence"] as const;
95
+ export type CursorRoutingLevel = typeof CURSOR_ROUTING_LEVELS[number];
96
+
97
+ /**
98
+ * Codex cannot render Cursor's model-specific parameter control, so expose each optimization mode
99
+ * as a first-class routed model next to the backwards-compatible `cursor/auto` entry.
100
+ */
101
+ export const CURSOR_ROUTER_MODEL_IDS = [
102
+ CURSOR_AUTO_MODEL_ID,
103
+ ...CURSOR_ROUTING_LEVELS.map(level => `${CURSOR_AUTO_MODEL_ID}-${level}`),
104
+ ] as const;
105
+
106
+ /** Wire id Cursor Connect expects for the auto-router (GetUsableModels returns `default`, not `auto`). */
107
+ export const CURSOR_AUTO_WIRE_MODEL_ID = "default";
108
+
109
+ export interface CursorWireModelSelection {
110
+ modelId: string;
111
+ routingLevel?: CursorRoutingLevel;
112
+ }
113
+
114
+ /** Resolve a Codex-facing model id into Cursor's wire model plus optional router parameter. */
115
+ export function cursorWireModelSelection(modelId: string): CursorWireModelSelection {
116
+ const normalized = modelId.startsWith("cursor/") ? modelId.slice("cursor/".length) : modelId;
117
+ if (normalized === CURSOR_AUTO_MODEL_ID) return { modelId: CURSOR_AUTO_WIRE_MODEL_ID };
118
+ const prefix = `${CURSOR_AUTO_MODEL_ID}-`;
119
+ if (normalized.startsWith(prefix)) {
120
+ const level = normalized.slice(prefix.length);
121
+ if ((CURSOR_ROUTING_LEVELS as readonly string[]).includes(level)) {
122
+ return { modelId: CURSOR_AUTO_WIRE_MODEL_ID, routingLevel: level as CursorRoutingLevel };
123
+ }
124
+ }
125
+ return { modelId: normalized };
126
+ }
127
+
128
+ /** Map a Codex-facing Cursor model id to the upstream wire id. */
129
+ export function cursorCodexToWireModelId(modelId: string): string {
130
+ return cursorWireModelSelection(modelId).modelId;
131
+ }
132
+
133
+ /**
134
+ * Cursor-native wire models keep server-side conversation state reliably.
135
+ * External models (gpt/claude/gemini/grok families and similar) are more brittle on resumeAction.
136
+ */
137
+ export function isCursorNativeWireModel(modelId: string): boolean {
138
+ const wire = cursorCodexToWireModelId(modelId).trim().toLowerCase();
139
+ const bare = stripCursorEffortSuffix(wire);
140
+ if (bare === CURSOR_AUTO_WIRE_MODEL_ID || bare === CURSOR_AUTO_MODEL_ID) return true;
141
+ return bare.startsWith("composer-");
142
+ }
143
+
144
+ /** Inverse of {@link isCursorNativeWireModel}. */
145
+ export function isCursorExternalWireModel(modelId: string): boolean {
146
+ return !isCursorNativeWireModel(modelId);
147
+ }
148
+
149
+ function stripCursorEffortSuffix(wireModelId: string): string {
150
+ const suffixes = [...CANONICAL_EFFORT_SUFFIXES].sort((a, b) => b.length - a.length);
151
+ for (const suffix of suffixes) {
152
+ const marker = `-${suffix}`;
153
+ if (wireModelId.endsWith(marker)) return wireModelId.slice(0, -marker.length);
154
+ }
155
+ return wireModelId;
156
+ }
157
+
158
+ export function isCursorRouterModelId(modelId: string): boolean {
159
+ return (CURSOR_ROUTER_MODEL_IDS as readonly string[]).includes(modelId);
160
+ }
161
+
162
+ /** Filter the static Cursor seed to models this account can use. */
163
+ export function filterCursorConfiguredModelsByLiveDiscovery<T extends { id: string }>(
164
+ configured: readonly T[],
165
+ liveIds: readonly string[],
166
+ ): T[] {
167
+ return configured.filter(model =>
168
+ isCursorRouterModelId(model.id) || isCursorModelAvailableForAccount(model.id, liveIds),
169
+ );
170
+ }
171
+
172
+ export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorModels([
173
+ // Context windows and the model lineup mirror Cursor's public models/pricing docs plus the jawcode
174
+ // SOT (../jawcode/packages/ai/src/models.json, `cursor` provider), which mirrors the real
175
+ // GetUsableModels catalog. Live discovery is the preferred path when logged in; these ids seed the
176
+ // routed Codex catalog and provide a static fallback. Cursor base ids carry no effort suffix here —
177
+ // the request builder appends the per-model suffix (see effort-map.ts) and reasoning models
178
+ // advertise effort so Codex exposes the tier picker. `supportsReasoningEffort` tracks whether the
179
+ // model has *selectable effort tiers* (CURSOR_MODEL_EFFORT_TIERS), NOT merely whether it reasons:
180
+ // gemini/grok/kimi-k2.7/gpt-5-mini are reasoning models in the SOT but are sent bare (no tier picker).
181
+ ...CURSOR_ROUTER_MODEL_IDS.map(id => ({ id, contextWindow: CONTEXT_200K, supportsReasoningEffort: false })),
182
+
183
+ { id: "claude-sonnet-5", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
184
+ { id: "claude-4-sonnet", contextWindow: CONTEXT_200K },
185
+ { id: "claude-4-sonnet-1m", contextWindow: CONTEXT_1M },
186
+ { id: "claude-4.5-haiku", contextWindow: CONTEXT_200K },
187
+ { id: "claude-4.5-sonnet", contextWindow: CONTEXT_200K },
188
+ { id: "claude-4.5-opus", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
189
+ { id: "claude-4.6-opus", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
190
+ { id: "claude-4.6-sonnet", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
191
+ { id: "claude-opus-4-7", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
192
+ // opus-4-7-fast: effort-suffix tiers unverified -> no tier picker; sent bare like live-only ids.
193
+ { id: "claude-opus-4-7-fast", contextWindow: CONTEXT_200K },
194
+ { id: "claude-opus-4-8", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
195
+ { id: "claude-opus-5", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
196
+ { id: "claude-fable-5", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
197
+
198
+ { id: "composer-1", contextWindow: CONTEXT_200K },
199
+ { id: "composer-2.5", contextWindow: CONTEXT_200K },
200
+ { id: "composer-2.5-fast", contextWindow: CONTEXT_200K },
201
+
202
+ { id: "gemini-2.5-flash", contextWindow: CONTEXT_GEMINI },
203
+ { id: "gemini-3-flash", contextWindow: CONTEXT_GEMINI },
204
+ { id: "gemini-3-pro", contextWindow: CONTEXT_GEMINI },
205
+ { id: "gemini-3-pro-image-preview", contextWindow: CONTEXT_200K },
206
+ { id: "gemini-3.1-pro", contextWindow: CONTEXT_GEMINI },
207
+ { id: "gemini-3.5-flash", contextWindow: CONTEXT_200K },
208
+
209
+ { id: "gpt-5-codex", contextWindow: CONTEXT_272K },
210
+ { id: "gpt-5-fast", contextWindow: CONTEXT_272K },
211
+ { id: "gpt-5-mini", contextWindow: CONTEXT_272K },
212
+ { id: "gpt-5.1", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
213
+ { id: "gpt-5.1-codex", contextWindow: CONTEXT_272K },
214
+ { id: "gpt-5.1-codex-max", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
215
+ { id: "gpt-5.1-codex-mini", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
216
+ { id: "gpt-5.2", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
217
+ { id: "gpt-5.2-codex", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
218
+ { id: "gpt-5.3-codex", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
219
+ { id: "gpt-5.4", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
220
+ { id: "gpt-5.4-mini", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
221
+ { id: "gpt-5.4-nano", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
222
+ { id: "gpt-5.5", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
223
+ // gpt-5.5-extra: absent from cursor.com docs but SURVIVES the live GetUsableModels filter
224
+ // (account-verified 260709, devlog/model_update/260709_model_refresh/004_live_snapshot.md).
225
+ { id: "gpt-5.5-extra", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
226
+ { id: "gpt-5.6-sol", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
227
+ { id: "gpt-5.6-terra", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
228
+ { id: "gpt-5.6-luna", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
229
+
230
+ // 260709 refresh: stale grok/composer/kimi/gpt ids dropped per current cursor.com docs; the
231
+ // 260709 note: grok-4.5 was deferred; confirmed live 260708 (cursor.com/models, xAI launch).
232
+
233
+ // Conflict resolution (260709): keep the refreshed 1M context + kimi-k2.7-code from de12fc8,
234
+ // take PR #73's supportsReasoningEffort for glm-5.2 (its effort-map tiers landed with the PR).
235
+ { id: "glm-5.2", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
236
+ { id: "kimi-k2.7-code", contextWindow: CONTEXT_262K },
237
+ // kimi-k3: cursor.com/docs/models/kimi-k3; account-verified via GetUsableModels (2026-07-28) —
238
+ // ships only as effort-suffixed kimi-k3-{low,high,max}, so the tier picker is exposed.
239
+ { id: "kimi-k3", contextWindow: CONTEXT_262K, supportsReasoningEffort: true },
240
+
241
+ { id: "grok-4.5", contextWindow: 500_000, supportsReasoningEffort: true },
242
+ { id: "grok-4.5-fast", contextWindow: 500_000, supportsReasoningEffort: true },
243
+ ]);
244
+
245
+ export function cursorModelIds(models: readonly CursorModelInfo[] = CURSOR_STATIC_MODELS): string[] {
246
+ return normalizeCursorModels(models).map(model => model.id);
247
+ }
248
+
249
+ export function cursorModelContextWindows(
250
+ models: readonly CursorModelInfo[] = CURSOR_STATIC_MODELS,
251
+ ): Record<string, number> {
252
+ return Object.fromEntries(
253
+ normalizeCursorModels(models).map(model => [model.id, model.contextWindow ?? inferCursorContextWindow(model.id)]),
254
+ );
255
+ }
256
+
257
+ export function cursorModelInputModalities(
258
+ models: readonly CursorModelInfo[] = CURSOR_STATIC_MODELS,
259
+ ): Record<string, string[]> {
260
+ return Object.fromEntries(
261
+ normalizeCursorModels(models).map(model => [model.id, normalizeInputModalities(model.inputModalities)]),
262
+ );
263
+ }
264
+
265
+ export function cursorModelReasoningEfforts(
266
+ models: readonly CursorModelInfo[] = CURSOR_STATIC_MODELS,
267
+ ): Record<string, string[]> {
268
+ return Object.fromEntries(
269
+ normalizeCursorModels(models).map(model => [
270
+ model.id,
271
+ model.supportsReasoningEffort === true
272
+ ? cursorModelEffortLadder(model.id) ?? []
273
+ : [],
274
+ ]),
275
+ );
276
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Per-model Cursor reasoning-effort mapping.
3
+ *
4
+ * Cursor model ids encode the reasoning effort as a suffix (`claude-4.6-opus-high`), and the available
5
+ * tiers differ per model — `claude-4.6-opus` tops out at `-max`, `claude-opus-4-8` at `-xhigh`,
6
+ * `claude-4.6-sonnet` only has `-medium`, and most `composer`/`gemini` models take no suffix at all.
7
+ * Grok Fast puts its mode marker after the effort (`grok-4.5-high-fast`). A bare id for a model that
8
+ * requires a suffix is rejected `ERROR_BAD_MODEL_NAME` (devlog 350.105).
9
+ *
10
+ * Canonical effort order is always low < medium < high < xhigh < max (max is the top tier, confirmed
11
+ * against Anthropic docs and Cursor's live lineup). Tiers are stored in ascending canonical order.
12
+ *
13
+ * `CURSOR_MODEL_EFFORT_TIERS` is the real catalog (from the Cursor `GetUsableModels` naming, mirrored in
14
+ * jawcode's bundle), each base model -> its available suffixes in ascending order. `cursorEffortSuffix`
15
+ * is literal-first: when the requested effort is one of the model's tiers, the effort you name is the
16
+ * suffix Cursor receives. It only clamps Codex effort ranks for efforts outside that model's tier set.
17
+ */
18
+
19
+ const CURSOR_MODEL_EFFORT_TIERS: Record<string, readonly string[]> = {
20
+ "claude-4.5-opus": ["high"],
21
+ "claude-4.6-opus": ["high", "max"],
22
+ "claude-4.6-sonnet": ["medium"],
23
+ // max is always the top tier (canonical order: low < medium < high < xhigh < max), confirmed
24
+ // against Anthropic's effort ladder docs and Cursor's live model lineup.
25
+ "claude-fable-5": ["low", "medium", "high", "xhigh", "max"],
26
+ "claude-opus-4-7": ["low", "medium", "high", "xhigh", "max"],
27
+ "claude-opus-4-8": ["low", "medium", "high", "xhigh", "max"],
28
+ "claude-opus-5": ["low", "medium", "high", "xhigh", "max"],
29
+ "claude-sonnet-5": ["low", "medium", "high", "xhigh", "max"],
30
+ "glm-5.2": ["high", "max"],
31
+ // GetUsableModels (2026-07-28) lists kimi-k3 only as effort-suffixed kimi-k3-{low,high,max};
32
+ // the bare id returns not_found. Tiers mirror the native Kimi provider's K3 ladder.
33
+ "kimi-k3": ["low", "high", "max"],
34
+ // Cursor renamed the Grok 4.5 slugs to cursor-grok-4.5-{low,medium,high} and
35
+ // cursor-grok-4.5-{low,medium,high}-fast. The bare Fast id returns not_found.
36
+ "grok-4.5": ["low", "medium", "high"],
37
+ "grok-4.5-fast": ["low", "medium", "high"],
38
+ "gpt-5.1": ["low", "high"],
39
+ "gpt-5.1-codex-max": ["low", "medium", "high", "xhigh"],
40
+ "gpt-5.1-codex-mini": ["low", "high"],
41
+ "gpt-5.2": ["low", "high", "xhigh"],
42
+ "gpt-5.2-codex": ["low", "high", "xhigh"],
43
+ "gpt-5.3-codex": ["low", "high", "xhigh"],
44
+ "gpt-5.4": ["low", "medium", "high", "xhigh"],
45
+ "gpt-5.4-mini": ["low", "medium", "high", "xhigh"],
46
+ "gpt-5.4-nano": ["low", "medium", "high", "xhigh"],
47
+ "gpt-5.5": ["low", "medium", "high"],
48
+ "gpt-5.5-extra": ["high"],
49
+ "gpt-5.6-sol": ["low", "medium", "high", "xhigh", "max"],
50
+ "gpt-5.6-terra": ["low", "medium", "high", "xhigh", "max"],
51
+ "gpt-5.6-luna": ["low", "medium", "high", "xhigh", "max"],
52
+ };
53
+
54
+ /** All effort suffixes accepted when matching live Cursor model ids to configured base ids. */
55
+ export const CANONICAL_EFFORT_SUFFIXES: ReadonlySet<string> = new Set([
56
+ "none",
57
+ ...Object.values(CURSOR_MODEL_EFFORT_TIERS).flat(),
58
+ ]);
59
+
60
+ const CANONICAL_CODEX_EFFORT_ORDER = ["low", "medium", "high", "xhigh", "max"] as const;
61
+
62
+ function normalizeRequestedEffort(reasoning: string | undefined): string | undefined {
63
+ const normalized = reasoning?.toLowerCase();
64
+ return normalized === "ultra" ? "max" : normalized;
65
+ }
66
+
67
+ /** Collapse a Codex reasoning-effort label to a low/medium/high rank for clamping onto a model's tiers. */
68
+ function codexEffortRank(reasoning: string | undefined): "low" | "medium" | "high" {
69
+ switch (normalizeRequestedEffort(reasoning) ?? "") {
70
+ case "none":
71
+ case "minimal":
72
+ case "low":
73
+ return "low";
74
+ case "medium":
75
+ return "medium";
76
+ case "high":
77
+ case "max":
78
+ case "xhigh":
79
+ return "high";
80
+ default:
81
+ // No explicit effort: a bare reasoning-model id is invalid, so pick the model's top tier.
82
+ return "high";
83
+ }
84
+ }
85
+
86
+ /**
87
+ * The Cursor effort suffix to use for `baseModelId` given a Codex reasoning effort, or `undefined` when
88
+ * the model takes no suffix (bare). Literal model tiers pass through; unknown efforts clamp by rank.
89
+ */
90
+ export function cursorEffortSuffix(baseModelId: string, reasoning: string | undefined): string | undefined {
91
+ const tiers = CURSOR_MODEL_EFFORT_TIERS[baseModelId];
92
+ if (!tiers || tiers.length === 0) return undefined;
93
+ const requested = normalizeRequestedEffort(reasoning);
94
+ if (requested && tiers.includes(requested)) return requested;
95
+ switch (codexEffortRank(reasoning)) {
96
+ case "low":
97
+ return tiers[0];
98
+ case "high":
99
+ return tiers[tiers.length - 1];
100
+ case "medium":
101
+ return tiers[Math.floor((tiers.length - 1) / 2)];
102
+ }
103
+ }
104
+
105
+ /** The Codex-facing picker ladder for a Cursor model, sorted in canonical Codex effort order. */
106
+ export function cursorModelEffortLadder(baseModelId: string): string[] | undefined {
107
+ const tiers = CURSOR_MODEL_EFFORT_TIERS[baseModelId];
108
+ if (!tiers || tiers.length === 0) return undefined;
109
+ const tierSet = new Set(tiers);
110
+ return CANONICAL_CODEX_EFFORT_ORDER.filter(effort => tierSet.has(effort));
111
+ }
112
+
113
+ /** Base models known to carry a reasoning-effort suffix (everything else is sent bare). */
114
+ export function cursorModelHasEffortTiers(baseModelId: string): boolean {
115
+ return (CURSOR_MODEL_EFFORT_TIERS[baseModelId]?.length ?? 0) > 0;
116
+ }
117
+
118
+ /**
119
+ * Compose a Cursor wire id from a Codex-facing base id and effort tier.
120
+ * Fast variants put the mode after the effort; other models use the ordinary `{base}-{effort}` form.
121
+ */
122
+ export function cursorWireModelIdWithEffort(baseModelId: string, effortSuffix: string): string {
123
+ if (baseModelId.endsWith("-fast")) {
124
+ return `${baseModelId.slice(0, -"-fast".length)}-${effortSuffix}-fast`;
125
+ }
126
+ return `${baseModelId}-${effortSuffix}`;
127
+ }
@@ -0,0 +1,88 @@
1
+ import type { OcxProviderConfig } from "../../types";
2
+ import type { CursorClientMessage } from "./types";
3
+
4
+ export type CursorNativeExecMode = "off" | "codex-sandbox" | "on";
5
+
6
+ /** Codex permissions template marker, e.g. "`sandbox_mode` is `danger-full-access`". */
7
+ export const CURSOR_SANDBOX_FULL_ACCESS_RE = /sandbox_mode[^\n]{0,80}danger-full-access/i;
8
+
9
+ /**
10
+ * Config-owner-selected policy; explicit mode wins, legacy boolean maps to "on".
11
+ * The UNSET default is "off". `nativeLocalExec: "on"` is the only non-legacy setting that
12
+ * authorizes Cursor server-driven local read/write/delete/ls/grep/shell/fetch execution.
13
+ * `nativeLocalExec: "codex-sandbox"` is kept as a recognized legacy/deprecated spelling but is
14
+ * fail-closed: opencodex has no trustworthy per-request attestation that caller-supplied
15
+ * Responses instructions/system/developer prose reflects a real Codex sandbox state.
16
+ */
17
+ export function resolveCursorNativeExecMode(provider: OcxProviderConfig): CursorNativeExecMode {
18
+ const mode = provider.nativeLocalExec;
19
+ if (mode === "off" || mode === "codex-sandbox" || mode === "on") return mode;
20
+ return provider.unsafeAllowNativeLocalExec === true ? "on" : "off";
21
+ }
22
+
23
+ /**
24
+ * True when the request itself declares the Codex full-access sandbox. Carriers are the
25
+ * system/instructions entries and developer-role messages ONLY. This is diagnostic/context
26
+ * metadata; request text is caller-controlled and never authorizes native local exec.
27
+ */
28
+ export function cursorRequestDeclaresFullAccess(
29
+ request: { system: string[]; messages: Array<{ role: string; content: string }> },
30
+ ): boolean {
31
+ for (const entry of request.system) {
32
+ if (CURSOR_SANDBOX_FULL_ACCESS_RE.test(entry)) return true;
33
+ }
34
+ for (const message of request.messages) {
35
+ if (message.role === "developer" && CURSOR_SANDBOX_FULL_ACCESS_RE.test(message.content)) return true;
36
+ }
37
+ return false;
38
+ }
39
+
40
+ /** Effective per-request allowance: only server-local config opt-in enables native exec. */
41
+ export function effectiveCursorNativeExecAllow(provider: OcxProviderConfig, requestDeclaresFullAccess: boolean): boolean {
42
+ const mode = resolveCursorNativeExecMode(provider);
43
+ void requestDeclaresFullAccess;
44
+ return mode === "on";
45
+ }
46
+
47
+ export const CURSOR_EXEC_CASES_DENIED = [
48
+ "readArgs",
49
+ "lsArgs",
50
+ "grepArgs",
51
+ "writeArgs",
52
+ "deleteArgs",
53
+ "shellArgs",
54
+ "shellStreamArgs",
55
+ "diagnosticsArgs",
56
+ "mcpArgs",
57
+ "fetchArgs",
58
+ "recordScreenArgs",
59
+ "computerUseArgs",
60
+ "unknownExecCase",
61
+ ] as const;
62
+
63
+ export type CursorDeniedExecCase = (typeof CURSOR_EXEC_CASES_DENIED)[number];
64
+
65
+ export function cursorExecDeniedMessage(execCase: string): string {
66
+ return [
67
+ `Cursor legacy mock transport cannot execute ${execCase}.`,
68
+ "Production Cursor requests use the live protobuf native exec bridge.",
69
+ "The legacy mock path returns a non-executing placeholder for tests only.",
70
+ ].join(" ");
71
+ }
72
+
73
+ export function cursorExecResult(requestId: string, execCase: string): CursorClientMessage {
74
+ if (execCase === "requestContextArgs") {
75
+ return {
76
+ type: "exec_result",
77
+ requestId,
78
+ ok: true,
79
+ message: "Cursor request context is empty in legacy mock transport mode.",
80
+ };
81
+ }
82
+ return {
83
+ type: "exec_result",
84
+ requestId,
85
+ ok: false,
86
+ message: cursorExecDeniedMessage(execCase),
87
+ };
88
+ }