clawdex-mobile 5.1.3-internal.11 → 5.1.3-internal.13

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 (43) hide show
  1. package/README.md +2 -3
  2. package/bin/clawdex.js +2 -2
  3. package/docs/setup-and-operations.md +2 -2
  4. package/package.json +11 -4
  5. package/scripts/setup-wizard.sh +11 -21
  6. package/scripts/start-bridge-secure.js +6 -53
  7. package/services/cursor-app-server/README.md +39 -0
  8. package/services/cursor-app-server/dist/appServer.d.ts +52 -0
  9. package/services/cursor-app-server/dist/appServer.js +780 -0
  10. package/services/cursor-app-server/dist/appServer.js.map +1 -0
  11. package/services/cursor-app-server/dist/cursorWorkspace.d.ts +7 -0
  12. package/services/cursor-app-server/dist/cursorWorkspace.js +126 -0
  13. package/services/cursor-app-server/dist/cursorWorkspace.js.map +1 -0
  14. package/services/cursor-app-server/dist/index.d.ts +4 -0
  15. package/services/cursor-app-server/dist/index.js +4 -0
  16. package/services/cursor-app-server/dist/index.js.map +1 -0
  17. package/services/cursor-app-server/dist/input.d.ts +27 -0
  18. package/services/cursor-app-server/dist/input.js +143 -0
  19. package/services/cursor-app-server/dist/input.js.map +1 -0
  20. package/services/cursor-app-server/dist/jsonRpc.d.ts +15 -0
  21. package/services/cursor-app-server/dist/jsonRpc.js +93 -0
  22. package/services/cursor-app-server/dist/jsonRpc.js.map +1 -0
  23. package/services/cursor-app-server/dist/projection.d.ts +8 -0
  24. package/services/cursor-app-server/dist/projection.js +507 -0
  25. package/services/cursor-app-server/dist/projection.js.map +1 -0
  26. package/services/cursor-app-server/dist/sdkDriver.d.ts +50 -0
  27. package/services/cursor-app-server/dist/sdkDriver.js +166 -0
  28. package/services/cursor-app-server/dist/sdkDriver.js.map +1 -0
  29. package/services/cursor-app-server/dist/stdio.d.ts +2 -0
  30. package/services/cursor-app-server/dist/stdio.js +7 -0
  31. package/services/cursor-app-server/dist/stdio.js.map +1 -0
  32. package/services/cursor-app-server/dist/types.d.ts +218 -0
  33. package/services/cursor-app-server/dist/types.js +2 -0
  34. package/services/cursor-app-server/dist/types.js.map +1 -0
  35. package/services/cursor-app-server/package.json +43 -0
  36. package/services/rust-bridge/Cargo.lock +1 -1
  37. package/services/rust-bridge/Cargo.toml +1 -1
  38. package/vendor/bridge-binaries/darwin-arm64/codex-rust-bridge +0 -0
  39. package/vendor/bridge-binaries/darwin-x64/codex-rust-bridge +0 -0
  40. package/vendor/bridge-binaries/linux-arm64/codex-rust-bridge +0 -0
  41. package/vendor/bridge-binaries/linux-armv7l/codex-rust-bridge +0 -0
  42. package/vendor/bridge-binaries/linux-x64/codex-rust-bridge +0 -0
  43. package/vendor/bridge-binaries/win32-x64/codex-rust-bridge.exe +0 -0
package/README.md CHANGED
@@ -25,7 +25,7 @@ Before you start:
25
25
  - `git`
26
26
  - `codex` in `PATH` for the default Codex flow
27
27
  - `opencode` in `PATH` if you want the OpenCode flow
28
- - `cursor-app-server` in `PATH` if you want the Cursor SDK flow
28
+ - Cursor app-server is bundled with `clawdex-mobile` for the Cursor SDK flow
29
29
 
30
30
  Install the mobile app:
31
31
 
@@ -59,12 +59,11 @@ OpenCode and Cursor can run beside Codex from the same bridge.
59
59
 
60
60
  ```bash
61
61
  npm install -g opencode-ai
62
- npm install -g @clawdex/cursor-app-server
63
62
  npm install -g clawdex-mobile@latest
64
63
  clawdex init --engines codex,opencode,cursor
65
64
  ```
66
65
 
67
- That writes `BRIDGE_ENABLED_ENGINES=codex,opencode,cursor` to `.env.secure`, so the mobile app can control the selected harnesses from one bridge. When Cursor is selected, `clawdex init` asks for the Cursor API key and saves it in `.env.secure`.
66
+ That writes `BRIDGE_ENABLED_ENGINES=codex,opencode,cursor` to `.env.secure`, so the mobile app can control the selected harnesses from one bridge. When Cursor is selected, `clawdex init` uses the bundled `cursor-app-server`, asks for the Cursor API key, and saves it in `.env.secure`.
68
67
 
69
68
  Notes:
70
69
 
package/bin/clawdex.js CHANGED
@@ -10,11 +10,11 @@ function printUsage() {
10
10
  console.log(`Usage: clawdex <command> [options]
11
11
 
12
12
  Commands:
13
- init [--no-start] [--engine codex|opencode]
13
+ init [--no-start] [--engine codex|opencode|cursor] [--engines codex,opencode,cursor]
14
14
  Run interactive bridge onboarding and secure setup.
15
15
  By default, this also starts the secure bridge in the background.
16
16
  Use --no-start to configure only.
17
- Use --engine to set the preferred backend written to .env.secure.
17
+ Use --engine or --engines to choose the backend harnesses written to .env.secure.
18
18
 
19
19
  stop
20
20
  Stop bridge services for this project.
@@ -18,7 +18,7 @@ From a source checkout, the equivalent command is:
18
18
  npm run setup:wizard -- --engines codex,opencode,cursor
19
19
  ```
20
20
 
21
- That writes `BRIDGE_ENABLED_ENGINES=codex,opencode,cursor` into `.env.secure`, so the bridge starts the selected backends and the mobile app can control them from one UI. When Cursor is selected, `clawdex init` asks for the Cursor API key and saves it in `.env.secure`.
21
+ That writes `BRIDGE_ENABLED_ENGINES=codex,opencode,cursor` into `.env.secure`, so the bridge starts the selected backends and the mobile app can control them from one UI. When Cursor is selected, `clawdex init` uses the bundled `cursor-app-server`, asks for the Cursor API key, and saves it in `.env.secure`.
22
22
 
23
23
  If you want only one harness, use `--engine codex`, `--engine opencode`, or `--engine cursor`.
24
24
 
@@ -199,7 +199,7 @@ npm run teardown -- --yes
199
199
  | `BRIDGE_ACTIVE_ENGINE` | internal preferred routing backend used when multiple harnesses are enabled |
200
200
  | `BRIDGE_ENABLED_ENGINES` | selected harnesses to expose (`codex`, `opencode`, `cursor`, or a comma-separated mix) |
201
201
  | `OPENCODE_CLI_BIN` | opencode executable for dual-engine startup |
202
- | `CURSOR_APP_SERVER_BIN` | Cursor app-server executable, usually `cursor-app-server` |
202
+ | `CURSOR_APP_SERVER_BIN` | Cursor app-server executable, usually the `cursor-app-server` binary bundled with `clawdex-mobile` |
203
203
  | `CURSOR_API_KEY` | Cursor API key used by the Cursor SDK harness; collected by `clawdex init` when Cursor is selected |
204
204
  | `CURSOR_MODEL` | optional Cursor model id for non-interactive host defaults; normal mobile chats send the selected model |
205
205
  | `BRIDGE_OPENCODE_HOST` | loopback host for spawned opencode server |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "clawdex-mobile",
3
- "version": "5.1.3-internal.11",
4
- "description": "Private-network mobile bridge and CLI for Codex and OpenCode",
3
+ "version": "5.1.3-internal.13",
4
+ "description": "Private-network mobile bridge and CLI for Codex, OpenCode, and Cursor",
5
5
  "keywords": [
6
6
  "codex",
7
7
  "opencode",
@@ -20,10 +20,13 @@
20
20
  "access": "public"
21
21
  },
22
22
  "dependencies": {
23
- "qrcode-terminal": "^0.12.0"
23
+ "@cursor/sdk": "1.0.11",
24
+ "qrcode-terminal": "^0.12.0",
25
+ "zod": "^3.25.0"
24
26
  },
25
27
  "bin": {
26
- "clawdex": "./bin/clawdex.js"
28
+ "clawdex": "bin/clawdex.js",
29
+ "cursor-app-server": "services/cursor-app-server/dist/stdio.js"
27
30
  },
28
31
  "files": [
29
32
  "CHANGELOG.md",
@@ -38,6 +41,9 @@
38
41
  "scripts/setup-wizard.sh",
39
42
  "scripts/start-bridge-secure.js",
40
43
  "scripts/stop-services.sh",
44
+ "services/cursor-app-server/dist",
45
+ "services/cursor-app-server/README.md",
46
+ "services/cursor-app-server/package.json",
41
47
  "services/rust-bridge/Cargo.lock",
42
48
  "services/rust-bridge/Cargo.toml",
43
49
  "services/rust-bridge/src",
@@ -67,6 +73,7 @@
67
73
  "secure:bridge:dev": "node ./scripts/start-bridge-secure.js --dev",
68
74
  "bridge:ts": "BRIDGE_WORKDIR=$(pwd) npm run -w @codex/mac-bridge dev",
69
75
  "version:sync": "node scripts/sync-versions.js",
76
+ "prepack": "npm run build -w @clawdex/cursor-app-server",
70
77
  "build": "npm run --workspaces build",
71
78
  "typecheck": "npm run --workspaces typecheck",
72
79
  "lint": "npm run --workspaces lint",
@@ -1296,29 +1296,20 @@ ensure_cursor_app_server() {
1296
1296
  local existing_api_key=""
1297
1297
  local existing_model=""
1298
1298
  local provided_api_key="${CURSOR_API_KEY:-}"
1299
+ local resolved_cursor_app_server_bin=""
1299
1300
 
1300
- if [[ -f "$ROOT_DIR/services/cursor-app-server/package.json" ]]; then
1301
- info "Building Cursor app-server package."
1302
- npm run build -w @clawdex/cursor-app-server
1303
- hash -r
1301
+ if [[ -n "${CURSOR_APP_SERVER_BIN:-}" ]]; then
1302
+ resolved_cursor_app_server_bin="$CURSOR_APP_SERVER_BIN"
1303
+ elif command -v cursor-app-server >/dev/null 2>&1; then
1304
+ resolved_cursor_app_server_bin="$(command -v cursor-app-server)"
1304
1305
  fi
1305
1306
 
1306
- while ! command -v cursor-app-server >/dev/null 2>&1; do
1307
- warn "Cursor app-server command not found in PATH."
1308
- if confirm_prompt "Try installing @clawdex/cursor-app-server via npm now?" "N"; then
1309
- if npm install -g @clawdex/cursor-app-server; then
1310
- hash -r
1311
- else
1312
- warn "Automatic install failed."
1313
- fi
1314
- fi
1315
-
1316
- if ! command -v cursor-app-server >/dev/null 2>&1 && ! confirm_prompt "Retry Cursor app-server check?" "Y"; then
1317
- abort_wizard "Install @clawdex/cursor-app-server and rerun: clawdex init --engine cursor"
1318
- fi
1319
- done
1307
+ if [[ -z "$resolved_cursor_app_server_bin" ]]; then
1308
+ abort_wizard "cursor-app-server was not found. Upgrade clawdex-mobile so npm links the bundled command, then rerun: clawdex init --engine cursor"
1309
+ fi
1320
1310
 
1321
- ok "Found cursor-app-server: $(command -v cursor-app-server)"
1311
+ CURSOR_APP_SERVER_BIN="$resolved_cursor_app_server_bin"
1312
+ ok "Found cursor-app-server: $CURSOR_APP_SERVER_BIN"
1322
1313
 
1323
1314
  existing_api_key="$(extract_env_value "$SECURE_ENV_FILE" "CURSOR_API_KEY")"
1324
1315
  existing_model="$(extract_env_value "$SECURE_ENV_FILE" "CURSOR_MODEL")"
@@ -1743,8 +1734,7 @@ ensure_core_tools
1743
1734
  if has_packaged_bridge_binary; then
1744
1735
  ok "Found packaged Rust bridge binary for this host."
1745
1736
  else
1746
- info "No packaged bridge binary found for this host. Falling back to local Rust build."
1747
- ensure_local_rust_build_toolchain
1737
+ abort_wizard "No packaged bridge binary found for this host. Reinstall clawdex-mobile so npm installs the bundled bridge binary, then rerun setup."
1748
1738
  fi
1749
1739
 
1750
1740
  section "Config handling"
@@ -377,48 +377,6 @@ function commandExists(command) {
377
377
  return result.status === 0;
378
378
  }
379
379
 
380
- function walkFiles(directory) {
381
- const entries = fs.readdirSync(directory, { withFileTypes: true });
382
- const files = [];
383
-
384
- for (const entry of entries) {
385
- const entryPath = path.join(directory, entry.name);
386
- if (entry.isDirectory()) {
387
- files.push(...walkFiles(entryPath));
388
- continue;
389
- }
390
- if (entry.isFile()) {
391
- files.push(entryPath);
392
- }
393
- }
394
-
395
- return files;
396
- }
397
-
398
- function isBuiltBinaryFresh(packageDir, binaryPath) {
399
- if (!fs.existsSync(binaryPath)) {
400
- return false;
401
- }
402
-
403
- const binaryMtime = fs.statSync(binaryPath).mtimeMs;
404
- const watchPaths = [
405
- path.join(packageDir, "services", "rust-bridge", "Cargo.toml"),
406
- path.join(packageDir, "services", "rust-bridge", "Cargo.lock"),
407
- ];
408
- const sourceDir = path.join(packageDir, "services", "rust-bridge", "src");
409
-
410
- if (fs.existsSync(sourceDir)) {
411
- watchPaths.push(...walkFiles(sourceDir));
412
- }
413
-
414
- return watchPaths.every((watchPath) => {
415
- if (!fs.existsSync(watchPath)) {
416
- return true;
417
- }
418
- return fs.statSync(watchPath).mtimeMs <= binaryMtime;
419
- });
420
- }
421
-
422
380
  function printMissingCompilerHint() {
423
381
  if (process.platform === "win32") {
424
382
  console.error("Install Visual Studio Build Tools (Desktop development with C++) and Rust, then retry.");
@@ -615,20 +573,15 @@ function resolveLaunch(workspaceDir, packageDir, env, { devMode, forceSourceBuil
615
573
  }
616
574
 
617
575
  const builtBinary = builtBinaryPath(packageDir, os.platform(), buildProfile);
618
- if (isBuiltBinaryFresh(packageDir, builtBinary)) {
619
- ensureExecutable(builtBinary);
620
- return {
621
- command: builtBinary,
622
- args: [],
623
- cwd: workspaceDir,
624
- env,
625
- healthTimeoutMs: defaultHealthTimeoutMs,
626
- };
576
+
577
+ if (!forceSourceBuild) {
578
+ console.error("error: no packaged bridge binary was found for this host.");
579
+ console.error("Reinstall a published clawdex-mobile package with bundled bridge binaries.");
580
+ process.exit(1);
627
581
  }
628
582
 
629
583
  if (!commandExists("cargo")) {
630
- console.error("error: no packaged bridge binary was found for this host, and cargo is not installed.");
631
- console.error("Reinstall a published clawdex-mobile package with bundled bridge binaries, or install Rust and retry.");
584
+ console.error("error: CLAWDEX_BRIDGE_FORCE_SOURCE_BUILD=true was set, but cargo is not installed.");
632
585
  process.exit(1);
633
586
  }
634
587
 
@@ -0,0 +1,39 @@
1
+ # @clawdex/cursor-app-server
2
+
3
+ App-server shaped JSON-RPC adapter for Cursor agents.
4
+
5
+ This package is intentionally strict. It does not fall back to Codex, OpenCode,
6
+ mock agents, empty model lists, or implicit workspace directories. Missing
7
+ Cursor runtime configuration is surfaced as an error.
8
+
9
+ ## Contract
10
+
11
+ Supported JSON-RPC methods:
12
+
13
+ - `thread/list`
14
+ - `thread/loaded/list`
15
+ - `thread/read`
16
+ - `thread/start`
17
+ - `turn/start`
18
+ - `turn/interrupt`
19
+ - `model/list`
20
+
21
+ Emitted notifications:
22
+
23
+ - `thread/started`
24
+ - `thread/status/changed`
25
+ - `turn/started`
26
+ - `item/agentMessage/delta`
27
+ - `item/reasoning/textDelta`
28
+ - `item/started`
29
+ - `turn/completed`
30
+
31
+ ## Run
32
+
33
+ ```bash
34
+ CURSOR_WORKDIR="$PWD" CURSOR_MODEL="cursor-small" CURSOR_API_KEY="..." cursor-app-server
35
+ ```
36
+
37
+ `CURSOR_WORKDIR` is required for local agents. `CURSOR_MODEL` is required unless
38
+ a request provides an explicit model. `CURSOR_API_KEY` is required for Cursor SDK
39
+ operations and model listing.
@@ -0,0 +1,52 @@
1
+ import type { AppServerNotification, CursorAppServerOptions, CursorStreamMessage } from './types.js';
2
+ type NotificationListener = (notification: AppServerNotification) => void;
3
+ export declare class CursorAppServer {
4
+ private readonly runtime;
5
+ private readonly driver;
6
+ private readonly configuredCwd;
7
+ private readonly apiKey;
8
+ private readonly defaultModel;
9
+ private readonly cursorProjectsDir;
10
+ private readonly events;
11
+ private readonly liveThreads;
12
+ private readonly knownThreadCwds;
13
+ private readonly knownThreadStoreCwds;
14
+ constructor(options: CursorAppServerOptions);
15
+ onNotification(listener: NotificationListener): () => void;
16
+ request(method: string, params?: unknown): Promise<Record<string, unknown>>;
17
+ private listThreads;
18
+ private readThread;
19
+ private listLoadedThreads;
20
+ private startThread;
21
+ private startTurn;
22
+ private interruptTurn;
23
+ private listModels;
24
+ private initialize;
25
+ private getOrResumeLiveThread;
26
+ private consumeRun;
27
+ private applyStreamMessage;
28
+ private applyRunResult;
29
+ private findOrCreateTextItem;
30
+ private upsertToolCallItem;
31
+ private findAssistantItem;
32
+ private requireCwd;
33
+ private resolveKnownThreadWorkspace;
34
+ private rememberAgentCwd;
35
+ private listKnownWorkspaceCwds;
36
+ private resolveAgentEffectiveCwd;
37
+ private readPersistedThread;
38
+ private resumePersistedThread;
39
+ private candidateStoreCwds;
40
+ private requireModel;
41
+ private requireTurnModel;
42
+ private configuredModelOrUndefined;
43
+ private latestPersistedRunModel;
44
+ private requireApiKey;
45
+ private buildUserMessage;
46
+ private buildUserThreadContent;
47
+ private toModelSelection;
48
+ private emit;
49
+ }
50
+ export declare function createCursorAppServerFromEnv(env?: NodeJS.ProcessEnv): CursorAppServer;
51
+ export declare function cursorStreamMessageText(message: CursorStreamMessage): string;
52
+ export {};