@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
package/bin/ocx.mjs ADDED
@@ -0,0 +1,451 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * opencodex npm bin launcher.
4
+ *
5
+ * The package source is TypeScript that runs on the Bun runtime. To let
6
+ * `npm install -g @iislee/opencodex` work without a separately-installed Bun,
7
+ * we bundle the runtime via the `bun` npm dependency and exec it from this
8
+ * Node shim. (Dev still runs `bun run src/cli/index.ts` directly via the shebang on
9
+ * src/cli/index.ts — only the published npm `bin` routes through here.)
10
+ */
11
+ import { spawn, spawnSync } from "node:child_process";
12
+ import { createRequire } from "node:module";
13
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
14
+ import { homedir } from "node:os";
15
+ import { dirname, join, resolve } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+ import { isRealBunBinary } from "../src/lib/bun-binary-validator.mjs";
18
+ import { npmInvocation } from "../src/update/npm-invocation.mjs";
19
+ import { handoffWindowsTrayForUpdate, planWindowsTrayUpdate } from "../src/update/tray-update-plan.mjs";
20
+
21
+ const PKG = "@iislee/opencodex";
22
+ const require = createRequire(import.meta.url);
23
+ const here = dirname(fileURLToPath(import.meta.url));
24
+ const cliPath = join(here, "..", "src", "cli", "index.ts");
25
+
26
+ function isNodeModulesInstall() {
27
+ return here.split(/[\\/]/).includes("node_modules");
28
+ }
29
+
30
+ function isBunGlobalInstall() {
31
+ return /[\\/]\.bun[\\/]/.test(here);
32
+ }
33
+
34
+ function currentPackageVersion() {
35
+ try {
36
+ return JSON.parse(readFileSync(join(here, "..", "package.json"), "utf8")).version ?? "?";
37
+ } catch {
38
+ return "?";
39
+ }
40
+ }
41
+
42
+ function updateTag(currentVersion) {
43
+ // Allowlist the tag: the value is argv-controlled and (on Windows) flows into a
44
+ // shell-joined spawnSync — never forward arbitrary strings.
45
+ const tagIndex = process.argv.indexOf("--tag");
46
+ const explicit = tagIndex !== -1 ? process.argv[tagIndex + 1] : undefined;
47
+ if (explicit === "preview" || explicit === "latest") return explicit;
48
+ return String(currentVersion).includes("-preview.") ? "preview" : "latest";
49
+ }
50
+
51
+ function expandUserPath(raw) {
52
+ // Mirror src/config.ts expandUserPath — the Bun proxy expands `~`, so this launcher's
53
+ // pid/state gates must resolve the same directory or they silently check the wrong path.
54
+ if (raw === "~") return homedir();
55
+ if (raw.startsWith("~/") || raw.startsWith("~\\")) return join(homedir(), raw.slice(2));
56
+ return raw;
57
+ }
58
+
59
+ function configDir() {
60
+ const raw = process.env.OPENCODEX_HOME?.trim();
61
+ return resolve(raw ? expandUserPath(raw) : join(homedir(), ".opencodex"));
62
+ }
63
+
64
+ function shouldRepairCodexShim() {
65
+ return existsSync(join(configDir(), "codex-shim.json"));
66
+ }
67
+
68
+ function historyRestoreIncomplete() {
69
+ // Mirror src/update/index.ts historyRestoreIncomplete — a codex-history-backup-*.json surviving
70
+ // a stop means the native-history restore was skipped (locked state DB).
71
+ try {
72
+ return readdirSync(configDir()).some(
73
+ name => name.startsWith("codex-history-backup-") && name.endsWith(".json"),
74
+ );
75
+ } catch {
76
+ return false;
77
+ }
78
+ }
79
+
80
+ function repairCodexShimIfNeeded() {
81
+ if (!shouldRepairCodexShim()) return;
82
+ const launcher = fileURLToPath(import.meta.url);
83
+ const res = spawnSync(process.execPath, [launcher, "codex-shim", "install"], {
84
+ stdio: "inherit",
85
+ windowsHide: true,
86
+ });
87
+ if (res.status !== 0) {
88
+ console.warn(`opencodex: Codex shim repair failed (${res.status ?? "unknown exit"}). Try: ocx codex-shim install`);
89
+ }
90
+ }
91
+
92
+ function trayInstallState() {
93
+ const statePath = join(configDir(), "tray-state.json");
94
+ if (!existsSync(statePath)) return { installed: false, running: false };
95
+ let running = false;
96
+ try {
97
+ const heartbeat = JSON.parse(readFileSync(join(configDir(), "tray-heartbeat.json"), "utf8"));
98
+ if (Number.isSafeInteger(heartbeat.pid) && Date.now() - Number(heartbeat.timestamp) < 15_000) {
99
+ process.kill(heartbeat.pid, 0);
100
+ running = true;
101
+ }
102
+ } catch { /* installed but not running */ }
103
+ return { installed: true, running };
104
+ }
105
+
106
+ function runTrayLifecycle(launcher, action) {
107
+ return spawnSync(process.execPath, [launcher, "tray", action], {
108
+ stdio: "inherit",
109
+ windowsHide: true,
110
+ });
111
+ }
112
+
113
+ function runNpmSelfUpdate() {
114
+ const current = currentPackageVersion();
115
+ const tag = updateTag(current);
116
+ const latestInvocation = npmInvocation(["view", `${PKG}@${tag}`, "version"]);
117
+ const installInvocation = npmInvocation(["install", "-g", `${PKG}@${tag}`]);
118
+ if (!latestInvocation || !installInvocation) {
119
+ console.error("opencodex: could not resolve npm from a trusted absolute PATH entry; aborting before stopping the proxy.");
120
+ process.exit(1);
121
+ }
122
+ const latestResult = spawnSync(latestInvocation.file, latestInvocation.args, {
123
+ encoding: "utf8",
124
+ timeout: 12000,
125
+ windowsHide: true,
126
+ ...latestInvocation.options,
127
+ });
128
+ const latest = latestResult.status === 0 ? latestResult.stdout.trim() : "";
129
+
130
+ console.log(`opencodex v${current} (installed via npm, tag ${tag})`);
131
+ if (latest && latest === current) {
132
+ console.log(`Already on the latest ${tag} version (v${latest}).`);
133
+ process.exit(0);
134
+ }
135
+
136
+ // Remember whether a background service manages the proxy BEFORE stopping — `ocx stop`
137
+ // unloads it permanently, so a successful update must reinstall it afterwards.
138
+ const serviceStatePath = join(configDir(), "service-state.json");
139
+ const serviceWasInstalled = existsSync(serviceStatePath);
140
+ const trayBeforeUpdate = planWindowsTrayUpdate(
141
+ process.platform === "win32" ? trayInstallState() : { installed: false, running: false },
142
+ );
143
+ /** Read the backend from service-state.json so the update reinstalls the same one. */
144
+ function serviceReinstallArgs() {
145
+ try {
146
+ const state = JSON.parse(readFileSync(serviceStatePath, "utf8"));
147
+ if (state.backend === "native") return [launcher, "service", "install", "--native"];
148
+ } catch { /* missing or corrupt — fall through to default */ }
149
+ return [launcher, "service", "install"];
150
+ }
151
+
152
+ // Capture listen target before stop clears runtime-port.json (mirrors GUI/CLI update worker).
153
+ // Do not treat a live runtime port of 10100 as "missing" — track whether the read succeeded.
154
+ let bakePort = 10100;
155
+ let sawRuntimePort = false;
156
+ try {
157
+ const rt = JSON.parse(readFileSync(join(configDir(), "runtime-port.json"), "utf8"));
158
+ if (Number.isFinite(rt?.port) && rt.port > 0 && rt.port <= 65535) {
159
+ // Only trust runtime when its pid still looks alive (stale crash leftovers fall back to config).
160
+ const rtPid = Number(rt?.pid);
161
+ let runtimeLive = false;
162
+ if (Number.isSafeInteger(rtPid) && rtPid > 0) {
163
+ try {
164
+ process.kill(rtPid, 0);
165
+ runtimeLive = true;
166
+ } catch (e) {
167
+ if (e && typeof e === "object" && "code" in e && e.code === "EPERM") runtimeLive = true;
168
+ }
169
+ }
170
+ if (runtimeLive) {
171
+ bakePort = Math.trunc(rt.port);
172
+ sawRuntimePort = true;
173
+ }
174
+ }
175
+ } catch { /* fall through to config */ }
176
+ if (!sawRuntimePort) {
177
+ try {
178
+ const cfg = JSON.parse(readFileSync(join(configDir(), "config.json"), "utf8"));
179
+ if (Number.isFinite(cfg?.port) && cfg.port > 0 && cfg.port <= 65535) bakePort = Math.trunc(cfg.port);
180
+ } catch { /* keep default */ }
181
+ }
182
+
183
+ // Never replace package files under a live proxy — stop it first (full `ocx stop`
184
+ // semantics: graceful drain, service stop, native Codex restore). Gate on the service
185
+ // and the runtime-port record too: a service-managed or orphaned proxy can be live
186
+ // while ocx.pid is stale/missing.
187
+ const launcher = fileURLToPath(import.meta.url);
188
+ if (trayBeforeUpdate.stopBeforeReplacement) {
189
+ console.log("⏹ Handing off the Windows tray before updating...");
190
+ try {
191
+ handoffWindowsTrayForUpdate(trayBeforeUpdate, {
192
+ stop: () => {
193
+ const stopped = runTrayLifecycle(launcher, "stop");
194
+ return { exitStatus: stopped.status, running: trayInstallState().running };
195
+ },
196
+ start: () => runTrayLifecycle(launcher, "start"),
197
+ });
198
+ } catch {
199
+ console.error("opencodex: could not stop the Windows tray; aborting before package replacement.");
200
+ process.exit(1);
201
+ }
202
+ }
203
+ const hasRuntimeState =
204
+ existsSync(join(configDir(), "ocx.pid")) || existsSync(join(configDir(), "runtime-port.json"));
205
+ if (serviceWasInstalled || hasRuntimeState) {
206
+ console.log("⏹ Stopping the running proxy before updating...");
207
+ const stopRes = spawnSync(process.execPath, [launcher, "stop"], { stdio: "inherit", windowsHide: true });
208
+ const stillHasRuntimeState =
209
+ existsSync(join(configDir(), "ocx.pid")) || existsSync(join(configDir(), "runtime-port.json"));
210
+ if (stopRes.status !== 0 || stillHasRuntimeState) {
211
+ if (trayBeforeUpdate.restoreOnFailure) runTrayLifecycle(launcher, "start");
212
+ console.error("opencodex: could not stop the running proxy; aborting the update. Run 'ocx stop' and retry.");
213
+ process.exit(1);
214
+ }
215
+ if (historyRestoreIncomplete()) {
216
+ console.warn(
217
+ "opencodex: WARNING — Codex resume history was NOT restored (history DB locked; Codex app/IDE open?).\n" +
218
+ " Routed threads stay hidden in the native Codex app until restored.\n" +
219
+ " After the update: close the Codex app, then run 'ocx stop' once to restore.",
220
+ );
221
+ }
222
+ }
223
+
224
+ console.log(`Updating${latest ? ` to v${latest}` : ""}...\n$ npm install -g ${PKG}@${tag}`);
225
+ const res = spawnSync(installInvocation.file, installInvocation.args, {
226
+ stdio: "inherit",
227
+ timeout: 180000,
228
+ windowsHide: true,
229
+ ...installInvocation.options,
230
+ });
231
+ if (res.status === 0) {
232
+ console.log(`\nUpdated${latest ? ` to v${latest}` : ""}.`);
233
+ repairCodexShimIfNeeded();
234
+ if (trayBeforeUpdate.refreshAfterReplacement) {
235
+ const tray = spawnSync(process.execPath, [launcher, ...trayBeforeUpdate.installArgs], {
236
+ stdio: "inherit",
237
+ windowsHide: true,
238
+ });
239
+ if (tray.status !== 0) {
240
+ console.warn("opencodex: Windows tray refresh failed. Run: ocx tray install");
241
+ if (trayBeforeUpdate.restoreOnFailure) runTrayLifecycle(launcher, "start");
242
+ }
243
+ }
244
+ // The stop above unloaded any managed service; reinstall via the freshly-installed
245
+ // launcher so the new files write the baked paths and the service restarts.
246
+ if (serviceWasInstalled) {
247
+ console.log("Reinstalling the background service with the updated files...");
248
+ const prevBake = process.env.OCX_BAKE_PORT;
249
+ process.env.OCX_BAKE_PORT = String(bakePort);
250
+ try {
251
+ const svcArgs = serviceReinstallArgs();
252
+ const svc = spawnSync(process.execPath, svcArgs, { stdio: "inherit", windowsHide: true });
253
+ let needDirectStart = svc.status !== 0;
254
+ if (!needDirectStart) {
255
+ // Exit 0 can still leave stale/missing assets that never bring the proxy
256
+ // back — match the GUI/CLI fallthrough so /healthz is not left dead.
257
+ try {
258
+ const st = spawnSync(process.execPath, [launcher, "status", "--json"], {
259
+ encoding: "utf8",
260
+ timeout: 20_000,
261
+ windowsHide: true,
262
+ });
263
+ if (st.status === 0 && typeof st.stdout === "string" && st.stdout.trim()) {
264
+ const parsed = JSON.parse(st.stdout);
265
+ const proxyUp = parsed?.proxy?.running === true || parsed?.proxy?.health?.ok === true;
266
+ const viable = parsed?.startup?.serviceViable === true;
267
+ if (!proxyUp && !viable) needDirectStart = true;
268
+ } else {
269
+ // status failed or empty — fail closed to direct start (match CLI).
270
+ needDirectStart = true;
271
+ }
272
+ } catch {
273
+ needDirectStart = true;
274
+ }
275
+ }
276
+ if (needDirectStart) {
277
+ // On Windows, schtasks /create requires elevation. The launcher inherits the
278
+ // user's (non-admin) token, so the service reinstall can fail with access
279
+ // denied — or exit 0 while leaving a non-viable manager. Fall back to a
280
+ // direct detached proxy start so the update never leaves the user without
281
+ // a running proxy.
282
+ console.warn(
283
+ svc.status === 0
284
+ ? "opencodex: service refresh left a non-viable manager — starting the proxy directly instead."
285
+ : "opencodex: service refresh failed — starting the proxy directly instead.",
286
+ );
287
+ console.warn(" Run 'ocx service install' as administrator to refresh the background service.");
288
+ const env = { ...process.env };
289
+ delete env.OCX_SERVICE;
290
+ const child = spawn(process.execPath, [launcher, "start", "--port", String(bakePort)], {
291
+ detached: true,
292
+ stdio: "ignore",
293
+ windowsHide: true,
294
+ env,
295
+ });
296
+ child.unref();
297
+ console.log(`Proxy starting on port ${bakePort}.`);
298
+ }
299
+ } finally {
300
+ if (prevBake === undefined) delete process.env.OCX_BAKE_PORT;
301
+ else process.env.OCX_BAKE_PORT = prevBake;
302
+ }
303
+ } else {
304
+ console.log("Restart the proxy: ocx start");
305
+ }
306
+ process.exit(0);
307
+ }
308
+ if (trayBeforeUpdate.restoreOnFailure) runTrayLifecycle(launcher, "start");
309
+ console.error(`\nUpdate failed (npm exit ${res.status ?? "?"}). Try manually: npm install -g ${PKG}@${tag}`);
310
+ process.exit(1);
311
+ }
312
+
313
+ function bunBinDir() {
314
+ // Resolve the `bun` dependency's directory without hardcoding the platform
315
+ // package — npm's os/cpu/libc resolution already picked the right @oven/bun-*.
316
+ return dirname(require.resolve("bun/package.json"));
317
+ }
318
+
319
+ const BUN_OVERRIDE_ENV = "OPENCODEX_BUN_PATH";
320
+
321
+ function findBunBinary(bunDir) {
322
+ // The npm `bun` package ships the binary as bin/bun.exe on every platform;
323
+ // probe bin/bun too for forward compatibility.
324
+ for (const name of ["bun.exe", "bun"]) {
325
+ const p = join(bunDir, "bin", name);
326
+ if (isRealBunBinary(p)) return p;
327
+ }
328
+ return null;
329
+ }
330
+
331
+ function fail(msg) {
332
+ console.error(
333
+ `opencodex: ${msg}\n` +
334
+ "The bundled Bun runtime could not be prepared. This usually means the\n" +
335
+ "install skipped lifecycle scripts (e.g. npm blocked bun's postinstall\n" +
336
+ "under allowScripts) or optional dependencies. Reinstall with:\n" +
337
+ " npm install -g --allow-scripts=bun @iislee/opencodex\n" +
338
+ "(use sudo if the original install used sudo; without --ignore-scripts\n" +
339
+ "and without --omit=optional / optional=false)"
340
+ );
341
+ process.exit(1);
342
+ }
343
+
344
+ function resolveBun() {
345
+ // Keep direct npm-launcher starts aligned with durable service/shim installs:
346
+ // a valid explicit runtime must win even when the bundled dependency exists.
347
+ const override = process.env[BUN_OVERRIDE_ENV]?.trim();
348
+ if (override) {
349
+ const overridePath = resolve(override);
350
+ if (isRealBunBinary(overridePath)) return overridePath;
351
+ console.error(
352
+ `opencodex: ${BUN_OVERRIDE_ENV} is missing, unreadable, or not a complete Bun binary; falling back to the bundled runtime.`,
353
+ );
354
+ }
355
+
356
+ let bunDir;
357
+ try {
358
+ bunDir = bunBinDir();
359
+ } catch {
360
+ fail("the `bun` dependency is not installed.");
361
+ }
362
+
363
+ let bin = findBunBinary(bunDir);
364
+ if (bin) return bin;
365
+
366
+ // Lazy fallback: --ignore-scripts (or a failed postinstall) leaves the
367
+ // ~450-byte placeholder stub. Run the bun package's own installer once.
368
+ const installJs = join(bunDir, "install.js");
369
+ if (existsSync(installJs)) {
370
+ const r = spawnSync(process.execPath, [installJs], { stdio: "inherit" });
371
+ if (r.status === 0) bin = findBunBinary(bunDir);
372
+ }
373
+ if (!bin) fail("Bun binary missing after install attempt.");
374
+ return bin;
375
+ }
376
+
377
+ // `ocx update --help` prints usage and exits WITHOUT side effects. The npm launcher
378
+ // intercepts `update` before the Bun CLI starts, so the help short-circuit must live
379
+ // here too — otherwise --help runs the real self-update, stops the proxy, and drops
380
+ // in-flight routed streams (issue #168).
381
+ const updateHelpRequested = process.argv[2] === "update" &&
382
+ process.argv.slice(3).some(a => a === "--help" || a === "-h" || a === "help");
383
+ if (updateHelpRequested) {
384
+ console.log("Usage: ocx update [--tag latest|preview]\n\nUpdate opencodex. Preview installs stay on the preview tag unless overridden.");
385
+ process.exit(0);
386
+ }
387
+
388
+ if (process.argv[2] === "update" && isNodeModulesInstall() && !isBunGlobalInstall()) {
389
+ runNpmSelfUpdate();
390
+ }
391
+
392
+ const bun = resolveBun();
393
+
394
+ // Run the Bun child asynchronously and FORWARD termination signals to it, then wait
395
+ // for its graceful shutdown before this launcher exits. The previous blocking
396
+ // spawnSync() could not run JS signal handlers and did not forward signals, so a
397
+ // signal delivered only to this launcher (Codex app, IDE terminal, service wrapper,
398
+ // or `kill -INT <launcherPid>`) killed the launcher and ORPHANED the Bun proxy —
399
+ // port left bound, pid/runtime-port files left behind, Codex config not restored.
400
+ //
401
+ // Provenance seam for issue #701: THIS launcher runs under Node, which does not
402
+ // auto-load a project `.env`/`.env.local`; the Bun child does, before any opencodex
403
+ // code evaluates. So this is the last point that can still tell a real shell export
404
+ // from a working-directory dotenv value, and we record which Anthropic credential
405
+ // slots already existed. `src/cli/claude.ts` then treats anything present in the Bun
406
+ // child but missing from this list as ambient project pollution rather than user auth,
407
+ // which stopped a project dotenv from silently moving a claude.ai subscriber onto API
408
+ // billing. An EMPTY value is meaningful (the launcher ran and saw no slots) and is
409
+ // distinct from the variable being absent (no launcher at all — change nothing), so
410
+ // this must stay a plain assignment and never be collapsed to a falsy check.
411
+ // Disabling Bun's dotenv wholesale with --no-env-file is NOT an option: config
412
+ // interpolation and provider settings legitimately read the project environment.
413
+ const preBunAnthropicSlots = ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"]
414
+ .filter(name => typeof process.env[name] === "string" && process.env[name] !== "");
415
+ const child = spawn(bun, [cliPath, ...process.argv.slice(2)], {
416
+ stdio: "inherit",
417
+ env: { ...process.env, OCX_PRE_BUN_ANTHROPIC_ENV: preBunAnthropicSlots.join(",") },
418
+ });
419
+
420
+ // Windows has no real POSIX signals (no SIGHUP); forwarding is best-effort there.
421
+ const FORWARDED = process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
422
+ const handlers = FORWARDED.map(sig => {
423
+ const handler = () => {
424
+ try {
425
+ child.kill(sig);
426
+ } catch {
427
+ /* child already exited */
428
+ }
429
+ };
430
+ process.on(sig, handler);
431
+ return [sig, handler];
432
+ });
433
+ const clearHandlers = () => {
434
+ for (const [sig, handler] of handlers) process.removeListener(sig, handler);
435
+ };
436
+
437
+ child.on("error", err => {
438
+ clearHandlers();
439
+ console.error(`opencodex: failed to launch Bun runtime: ${err.message}`);
440
+ process.exit(1);
441
+ });
442
+
443
+ child.on("exit", (code, signal) => {
444
+ clearHandlers();
445
+ // Mirror the child's terminating signal/exit code so this launcher's status matches.
446
+ if (signal) {
447
+ process.kill(process.pid, signal);
448
+ return;
449
+ }
450
+ process.exit(code ?? 1);
451
+ });
@@ -0,0 +1,9 @@
1
+ export const packageName = "@iislee/opencodex";
2
+ export const cliCommand = "ocx";
3
+
4
+ export async function loadBunApi() {
5
+ if (typeof Bun === "undefined") {
6
+ throw new Error("The opencodex programmatic API requires the Bun runtime. Use `ocx` for the CLI entrypoint.");
7
+ }
8
+ return import("../src/index.ts");
9
+ }