@bitkyc08/opencodex 2.6.17 → 2.6.18-preview.20260703

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 (84) hide show
  1. package/README.md +9 -0
  2. package/bin/ocx.mjs +70 -5
  3. package/gui/dist/assets/index-BGrHb_az.js +9 -0
  4. package/gui/dist/assets/index-DDcEW0Cm.css +1 -0
  5. package/gui/dist/index.html +2 -2
  6. package/package.json +3 -1
  7. package/src/adapters/anthropic.ts +9 -2
  8. package/src/adapters/base.ts +6 -0
  9. package/src/adapters/cursor/arg-codec.ts +38 -0
  10. package/src/adapters/cursor/arg-normalize.ts +88 -0
  11. package/src/adapters/cursor/cursor-errors.ts +85 -0
  12. package/src/adapters/cursor/discovery.ts +144 -0
  13. package/src/adapters/cursor/effort-map.ts +74 -0
  14. package/src/adapters/cursor/exec-policy.ts +44 -0
  15. package/src/adapters/cursor/framing.ts +136 -0
  16. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  17. package/src/adapters/cursor/kv-store.ts +25 -0
  18. package/src/adapters/cursor/live-models.ts +93 -0
  19. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  20. package/src/adapters/cursor/live-transport.ts +758 -0
  21. package/src/adapters/cursor/mcp-config.ts +42 -0
  22. package/src/adapters/cursor/mcp-manager.ts +236 -0
  23. package/src/adapters/cursor/message-mapper.ts +46 -0
  24. package/src/adapters/cursor/native-exec-common.ts +55 -0
  25. package/src/adapters/cursor/native-exec-desktop.ts +177 -0
  26. package/src/adapters/cursor/native-exec-fs.ts +284 -0
  27. package/src/adapters/cursor/native-exec-mcp.ts +151 -0
  28. package/src/adapters/cursor/native-exec-network.ts +32 -0
  29. package/src/adapters/cursor/native-exec-shell.ts +191 -0
  30. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  31. package/src/adapters/cursor/native-exec.ts +177 -0
  32. package/src/adapters/cursor/protobuf-events.ts +309 -0
  33. package/src/adapters/cursor/protobuf-request.ts +347 -0
  34. package/src/adapters/cursor/request-builder.ts +98 -0
  35. package/src/adapters/cursor/tool-definitions.ts +301 -0
  36. package/src/adapters/cursor/transport-retry.ts +116 -0
  37. package/src/adapters/cursor/transport.ts +47 -0
  38. package/src/adapters/cursor/types.ts +36 -0
  39. package/src/adapters/cursor.ts +99 -0
  40. package/src/adapters/google.ts +7 -1
  41. package/src/adapters/kiro.ts +15 -0
  42. package/src/adapters/openai-chat.ts +7 -2
  43. package/src/adapters/run-turn-queue.ts +58 -0
  44. package/src/adapters/tool-catalog-nudge.ts +71 -0
  45. package/src/bridge.ts +7 -1
  46. package/src/cli-help.ts +9 -2
  47. package/src/cli-status.ts +7 -5
  48. package/src/cli.ts +122 -79
  49. package/src/codex-catalog.ts +213 -71
  50. package/src/codex-history-provider.ts +31 -14
  51. package/src/codex-inject.ts +17 -9
  52. package/src/codex-paths.ts +2 -1
  53. package/src/codex-shim.ts +30 -7
  54. package/src/codex-sync.ts +70 -0
  55. package/src/config.ts +58 -2
  56. package/src/doctor.ts +4 -2
  57. package/src/index.ts +1 -0
  58. package/src/model-cache.ts +22 -2
  59. package/src/oauth/callback-server.ts +44 -16
  60. package/src/oauth/cursor.ts +188 -0
  61. package/src/oauth/index.ts +29 -3
  62. package/src/oauth/key-providers.ts +20 -33
  63. package/src/oauth/login-cli.ts +7 -4
  64. package/src/open-url.ts +5 -1
  65. package/src/ports.ts +13 -0
  66. package/src/process-control.ts +76 -0
  67. package/src/provider-label.ts +10 -5
  68. package/src/providers/derive.ts +30 -3
  69. package/src/providers/registry.ts +39 -1
  70. package/src/proxy-liveness.ts +122 -0
  71. package/src/responses/parser.ts +1 -0
  72. package/src/responses/state.ts +83 -0
  73. package/src/router.ts +38 -23
  74. package/src/server/adapter-resolve.ts +3 -0
  75. package/src/server.ts +130 -18
  76. package/src/service.ts +94 -32
  77. package/src/types.ts +24 -1
  78. package/src/update-job.ts +360 -0
  79. package/src/update.ts +73 -11
  80. package/src/usage-log.ts +3 -3
  81. package/src/usage-summary.ts +3 -2
  82. package/src/win-paths.ts +68 -0
  83. package/gui/dist/assets/index-DIBiVVC0.css +0 -1
  84. package/gui/dist/assets/index-DcnD944i.js +0 -9
package/README.md CHANGED
@@ -181,12 +181,21 @@ next Codex session. opencodex keeps two separate behaviors:
181
181
  | Kimi (Moonshot) | `openai-chat` | oauth / key |
182
182
  | Google Gemini | `google` | key |
183
183
  | Azure OpenAI | `azure-openai` | key |
184
+ | Cursor (experimental) | `cursor` | dashboard/local config; live transport + native exec |
184
185
  | Ollama Cloud + 17-provider catalog | `openai-chat` | key |
185
186
  | Ollama / vLLM / LM Studio (local) | `openai-chat` | key (usually blank) |
186
187
  | Any OpenAI-compatible endpoint | `openai-chat` | key |
187
188
 
188
189
  Plus DeepSeek, Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax, Qwen Portal, and more. See the full list with `ocx init` or in the [provider docs](https://lidge-jun.github.io/opencodex/reference/configuration/).
189
190
 
191
+ Cursor support is a staged experimental bridge: it appears in `ocx init` and the dashboard Add
192
+ Provider picker as a local config with Cursor's static public model catalog. Live
193
+ HTTP/2 transport is enabled when a Cursor access token is configured, and Cursor native
194
+ read/write/delete/ls/grep/shell/fetch requests are handled by opencodex. MCP, screen recording,
195
+ and computer-use are exposed through executor hooks; when no local executor is configured,
196
+ opencodex returns typed no-executor results instead of policy-blocking the request. Cursor OAuth
197
+ and live model discovery remain separate future phases.
198
+
190
199
  ## CLI
191
200
 
192
201
  ```bash
package/bin/ocx.mjs CHANGED
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { spawn, spawnSync } from "node:child_process";
12
12
  import { createRequire } from "node:module";
13
- import { existsSync, readFileSync, statSync } from "node:fs";
13
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
14
14
  import { homedir } from "node:os";
15
15
  import { dirname, join, resolve } from "node:path";
16
16
  import { fileURLToPath } from "node:url";
@@ -41,19 +41,43 @@ function currentPackageVersion() {
41
41
  }
42
42
 
43
43
  function updateTag(currentVersion) {
44
+ // Allowlist the tag: the value is argv-controlled and (on Windows) flows into a
45
+ // shell-joined spawnSync — never forward arbitrary strings.
44
46
  const tagIndex = process.argv.indexOf("--tag");
45
- if (tagIndex !== -1 && process.argv[tagIndex + 1]) return process.argv[tagIndex + 1];
47
+ const explicit = tagIndex !== -1 ? process.argv[tagIndex + 1] : undefined;
48
+ if (explicit === "preview" || explicit === "latest") return explicit;
46
49
  return String(currentVersion).includes("-preview.") ? "preview" : "latest";
47
50
  }
48
51
 
52
+ function expandUserPath(raw) {
53
+ // Mirror src/config.ts expandUserPath — the Bun proxy expands `~`, so this launcher's
54
+ // pid/state gates must resolve the same directory or they silently check the wrong path.
55
+ if (raw === "~") return homedir();
56
+ if (raw.startsWith("~/") || raw.startsWith("~\\")) return join(homedir(), raw.slice(2));
57
+ return raw;
58
+ }
59
+
49
60
  function configDir() {
50
- return resolve(process.env.OPENCODEX_HOME?.trim() || join(homedir(), ".opencodex"));
61
+ const raw = process.env.OPENCODEX_HOME?.trim();
62
+ return resolve(raw ? expandUserPath(raw) : join(homedir(), ".opencodex"));
51
63
  }
52
64
 
53
65
  function shouldRepairCodexShim() {
54
66
  return existsSync(join(configDir(), "codex-shim.json"));
55
67
  }
56
68
 
69
+ function historyRestoreIncomplete() {
70
+ // Mirror src/update.ts historyRestoreIncomplete — a codex-history-backup-*.json surviving
71
+ // a stop means the native-history restore was skipped (locked state DB).
72
+ try {
73
+ return readdirSync(configDir()).some(
74
+ name => name.startsWith("codex-history-backup-") && name.endsWith(".json"),
75
+ );
76
+ } catch {
77
+ return false;
78
+ }
79
+ }
80
+
57
81
  function repairCodexShimIfNeeded() {
58
82
  if (!shouldRepairCodexShim()) return;
59
83
  const launcher = fileURLToPath(import.meta.url);
@@ -70,10 +94,14 @@ function runNpmSelfUpdate() {
70
94
  const current = currentPackageVersion();
71
95
  const tag = updateTag(current);
72
96
  const npm = npmBin();
97
+ // Node ≥18.20/20.12 refuses to spawn .cmd/.bat without a shell (CVE-2024-27980
98
+ // hardening) — spawning "npm.cmd" shell-less throws EINVAL on Windows.
99
+ const winShell = process.platform === "win32";
73
100
  const latestResult = spawnSync(npm, ["view", `${PKG}@${tag}`, "version"], {
74
101
  encoding: "utf8",
75
102
  timeout: 12000,
76
103
  windowsHide: true,
104
+ shell: winShell,
77
105
  });
78
106
  const latest = latestResult.status === 0 ? latestResult.stdout.trim() : "";
79
107
 
@@ -83,17 +111,54 @@ function runNpmSelfUpdate() {
83
111
  process.exit(0);
84
112
  }
85
113
 
114
+ // Remember whether a background service manages the proxy BEFORE stopping — `ocx stop`
115
+ // unloads it permanently, so a successful update must reinstall it afterwards.
116
+ const serviceWasInstalled = existsSync(join(configDir(), "service-state.json"));
117
+
118
+ // Never replace package files under a live proxy — stop it first (full `ocx stop`
119
+ // semantics: graceful drain, service stop, native Codex restore). Gate on the service
120
+ // and the runtime-port record too: a service-managed or orphaned proxy can be live
121
+ // while ocx.pid is stale/missing.
122
+ const launcher = fileURLToPath(import.meta.url);
123
+ const hasRuntimeState =
124
+ existsSync(join(configDir(), "ocx.pid")) || existsSync(join(configDir(), "runtime-port.json"));
125
+ if (serviceWasInstalled || hasRuntimeState) {
126
+ console.log("⏹ Stopping the running proxy before updating...");
127
+ const stopRes = spawnSync(process.execPath, [launcher, "stop"], { stdio: "inherit", windowsHide: true });
128
+ const stillHasRuntimeState =
129
+ existsSync(join(configDir(), "ocx.pid")) || existsSync(join(configDir(), "runtime-port.json"));
130
+ if (stopRes.status !== 0 || stillHasRuntimeState) {
131
+ console.error("opencodex: could not stop the running proxy; aborting the update. Run 'ocx stop' and retry.");
132
+ process.exit(1);
133
+ }
134
+ if (historyRestoreIncomplete()) {
135
+ console.warn(
136
+ "opencodex: WARNING — Codex resume history was NOT restored (history DB locked; Codex app/IDE open?).\n" +
137
+ " Routed threads stay hidden in the native Codex app until restored.\n" +
138
+ " After the update: close the Codex app, then run 'ocx stop' once to restore.",
139
+ );
140
+ }
141
+ }
142
+
86
143
  console.log(`Updating${latest ? ` to v${latest}` : ""}...\n$ ${npm} install -g ${PKG}@${tag}`);
87
144
  const res = spawnSync(npm, ["install", "-g", `${PKG}@${tag}`], {
88
145
  stdio: "inherit",
89
146
  timeout: 180000,
90
147
  windowsHide: true,
148
+ shell: winShell,
91
149
  });
92
150
  if (res.status === 0) {
93
151
  console.log(`\nUpdated${latest ? ` to v${latest}` : ""}.`);
94
152
  repairCodexShimIfNeeded();
95
- console.log("Restart the proxy: ocx stop && ocx start");
96
- console.log("If a background service is installed, refresh its baked path: ocx service install");
153
+ // The stop above unloaded any managed service; reinstall via the freshly-installed
154
+ // launcher so the new files write the baked paths and the service restarts.
155
+ if (serviceWasInstalled) {
156
+ console.log("Reinstalling the background service with the updated files...");
157
+ const svc = spawnSync(process.execPath, [launcher, "service", "install"], { stdio: "inherit", windowsHide: true });
158
+ if (svc.status !== 0) console.warn("opencodex: service refresh failed — run 'ocx service install' manually.");
159
+ } else {
160
+ console.log("Restart the proxy: ocx start");
161
+ }
97
162
  process.exit(0);
98
163
  }
99
164
  console.error(`\nUpdate failed (${npm} exit ${res.status ?? "?"}). Try manually: ${npm} install -g ${PKG}@${tag}`);