clawdex-mobile 5.1.3-internal.8 → 5.1.3-internal.9

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.
@@ -84,10 +84,11 @@ gh codespace ports visibility 8787:public 8788:public
84
84
 
85
85
  ### Codespaces Bootstrap
86
86
 
87
- The repo devcontainer now includes:
87
+ The source repo devcontainer now includes:
88
88
 
89
- - `postCreateCommand`: `npm install --include=dev && npm run codespaces:bootstrap -- --prepare-only`
90
- - `postStartCommand`: `npm run codespaces:bootstrap`
89
+ - `updateContentCommand`: `npm install --include=dev --prefer-offline --no-audit --fund=false && npm run codespaces:bootstrap -- --prepare-only`
90
+ - `postStartCommand`: fire-and-forget `npm run codespaces:bootstrap`, writing setup output to `.bridge-bootstrap.log`
91
+ - `waitFor`: `updateContentCommand`
91
92
 
92
93
  `npm run codespaces:bootstrap` does the following:
93
94
 
@@ -99,9 +100,9 @@ The repo devcontainer now includes:
99
100
 
100
101
  Clawdex-created Codespaces request a 45-minute idle timeout. The bridge emits a lightweight active-turn keepalive while a Codex, OpenCode, or Cursor turn is running, so active work has activity even if a long step is otherwise quiet. When no turn is running, the keepalive stops and GitHub can pause the Codespace normally to save cost.
101
102
 
102
- That means the first Codespace create now front-loads the expensive bridge compile during `postCreateCommand`, so the later `postStartCommand` can usually start the bridge much faster.
103
+ That means prebuild-enabled Codespaces can snapshot the expensive dependency install and bridge compile during `updateContentCommand`. The later `postStartCommand` starts the runtime bridge asynchronously so Codespaces does not block editor/app access while the bridge finishes warming up.
103
104
 
104
- The same bootstrap script is included in the published `clawdex-mobile` npm package. That lets the `clawdex-codespace` template stay minimal: it can install `clawdex-mobile@latest` globally in the devcontainer and invoke the packaged bootstrap against the current workspace instead of copying `scripts/*` and `services/rust-bridge/*` into the template repo.
105
+ The same bootstrap script is included in the published `clawdex-mobile` npm package. That lets the `clawdex-codespace` template stay minimal: it installs `clawdex-mobile@internal` globally in `updateContentCommand` and invokes the packaged bootstrap against the current workspace instead of copying `scripts/*` and `services/rust-bridge/*` into the template repo. Because the published package ships Linux bridge binaries, the template does not need Rust, Cargo, or a local bridge compile.
105
106
 
106
107
  Manual examples:
107
108
 
@@ -115,7 +116,7 @@ CLAWDEX_CODESPACES_ENGINES=codex,opencode,cursor npm run codespaces:bootstrap
115
116
  Minimal template equivalent:
116
117
 
117
118
  ```bash
118
- npm install -g clawdex-mobile@latest @openai/codex
119
+ npm install -g --no-fund --no-audit clawdex-mobile@internal @openai/codex
119
120
  CLAWDEX_WORKSPACE_ROOT="$PWD" node "$(npm root -g)/clawdex-mobile/scripts/codespaces-bootstrap.js" --prepare-only
120
121
  CLAWDEX_WORKSPACE_ROOT="$PWD" node "$(npm root -g)/clawdex-mobile/scripts/codespaces-bootstrap.js"
121
122
  ```
@@ -60,7 +60,7 @@ gh codespace ports visibility 8787:public 8788:public
60
60
 
61
61
  ## GitHub Codespaces bootstrap did not start the bridge
62
62
 
63
- - Check the post-start command output in the Codespace terminal or rerun it manually:
63
+ - Check `.bridge-bootstrap.log` for the post-start bootstrap and `.bridge.log` for the bridge process, or rerun the bootstrap manually:
64
64
 
65
65
  ```bash
66
66
  npm run codespaces:bootstrap -- --prepare-only
@@ -81,8 +81,9 @@ CLAWDEX_WORKSPACE_ROOT="$PWD" node "$(npm root -g)/clawdex-mobile/scripts/codesp
81
81
  - Bridge startup logs and runtime state live in the Codespace repo root:
82
82
 
83
83
  ```bash
84
+ tail -n 200 .bridge-bootstrap.log
84
85
  tail -n 200 .bridge.log
85
- ls -la .bridge.pid .bridge.log .env.secure
86
+ ls -la .bridge.pid .bridge.log .bridge-bootstrap.log .env.secure
86
87
  ```
87
88
 
88
89
  - To only rewrite `.env.secure` without starting the bridge:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawdex-mobile",
3
- "version": "5.1.3-internal.8",
3
+ "version": "5.1.3-internal.9",
4
4
  "description": "Private-network mobile bridge and CLI for Codex and OpenCode",
5
5
  "keywords": [
6
6
  "codex",
@@ -16,6 +16,7 @@ const {
16
16
  } = require("./bridge-binary");
17
17
 
18
18
  const DEFAULT_HEALTH_TIMEOUT_MS = 15000;
19
+ const CODESPACES_HEALTH_TIMEOUT_MS = 60000;
19
20
  const DEV_HEALTH_TIMEOUT_MS = 60000;
20
21
  let qrcodeTerminal = null;
21
22
  let qrcodeTerminalLoaded = false;
@@ -346,6 +347,13 @@ function formatCodespacesVisibilityCommand(env, ports) {
346
347
  return ["gh", "codespace", "ports", "visibility", ...visibilityArgs, ...selectionArgs].join(" ");
347
348
  }
348
349
 
350
+ function sleepSync(ms) {
351
+ if (!Number.isFinite(ms) || ms <= 0) {
352
+ return;
353
+ }
354
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
355
+ }
356
+
349
357
  function updateCodespacesBrowseUrls(env, ports) {
350
358
  if (!commandExists("gh")) {
351
359
  return;
@@ -416,38 +424,57 @@ function ensureCodespacesPortsArePublic(env, ports) {
416
424
  return notes;
417
425
  }
418
426
 
419
- const result = spawnSync(
420
- "gh",
421
- [
422
- "codespace",
423
- "ports",
424
- "visibility",
425
- ...uniquePorts.map((port) => `${port}:public`),
426
- ...codespaceSelectionArgs(env),
427
- ],
428
- {
429
- encoding: "utf8",
430
- env: ghAuthEnv(env),
431
- stdio: ["ignore", "pipe", "pipe"],
427
+ const publishedPorts = [];
428
+ const failedPorts = [];
429
+ const selectionArgs = codespaceSelectionArgs(env);
430
+
431
+ for (const port of uniquePorts) {
432
+ let lastDetail = "";
433
+ for (let attempt = 1; attempt <= 8; attempt += 1) {
434
+ const result = spawnSync(
435
+ "gh",
436
+ ["codespace", "ports", "visibility", `${port}:public`, ...selectionArgs],
437
+ {
438
+ encoding: "utf8",
439
+ env: ghAuthEnv(env),
440
+ stdio: ["ignore", "pipe", "pipe"],
441
+ }
442
+ );
443
+
444
+ if ((result.status ?? 1) === 0) {
445
+ publishedPorts.push(port);
446
+ lastDetail = "";
447
+ break;
448
+ }
449
+
450
+ lastDetail = (result.stderr || result.stdout || "").trim();
451
+ if (attempt < 8) {
452
+ sleepSync(1_500);
453
+ }
432
454
  }
433
- );
434
455
 
435
- if ((result.status ?? 1) !== 0) {
436
- const detail = (result.stderr || result.stdout || "").trim();
437
- const suffix = detail ? ` (${detail.split(/\r?\n/, 1)[0]})` : "";
456
+ if (lastDetail) {
457
+ failedPorts.push({ port, detail: lastDetail });
458
+ }
459
+ }
460
+
461
+ if (publishedPorts.length > 0) {
462
+ updateCodespacesBrowseUrls(env, publishedPorts);
438
463
  notes.push(
439
- `Could not set Codespaces forwarded ports public automatically${suffix}. Run '${formatCodespacesVisibilityCommand(
464
+ `Codespaces forwarded ports are set to public for bridge access: ${publishedPorts.join(", ")}.`
465
+ );
466
+ }
467
+
468
+ for (const failure of failedPorts) {
469
+ const suffix = failure.detail ? ` (${failure.detail.split(/\r?\n/, 1)[0]})` : "";
470
+ notes.push(
471
+ `Could not set Codespaces forwarded port ${failure.port} public automatically${suffix}. Run '${formatCodespacesVisibilityCommand(
440
472
  env,
441
- uniquePorts
473
+ [failure.port]
442
474
  )}' or update the Ports panel manually.`
443
475
  );
444
- return notes;
445
476
  }
446
477
 
447
- updateCodespacesBrowseUrls(env, uniquePorts);
448
- notes.push(
449
- `Codespaces forwarded ports are set to public for bridge access: ${uniquePorts.join(", ")}.`
450
- );
451
478
  return notes;
452
479
  }
453
480
 
@@ -752,6 +779,10 @@ function buildBridgeFromSource(packageDir, env, profile) {
752
779
  }
753
780
 
754
781
  function resolveLaunch(workspaceDir, packageDir, env, { devMode, forceSourceBuild }) {
782
+ const defaultHealthTimeoutMs = isCodespacesMode(env)
783
+ ? CODESPACES_HEALTH_TIMEOUT_MS
784
+ : DEFAULT_HEALTH_TIMEOUT_MS;
785
+
755
786
  if (devMode) {
756
787
  if (!commandExists("cargo")) {
757
788
  console.error("error: missing Rust/Cargo toolchain for dev bridge mode.");
@@ -779,7 +810,7 @@ function resolveLaunch(workspaceDir, packageDir, env, { devMode, forceSourceBuil
779
810
  args: [],
780
811
  cwd: workspaceDir,
781
812
  env,
782
- healthTimeoutMs: DEFAULT_HEALTH_TIMEOUT_MS,
813
+ healthTimeoutMs: defaultHealthTimeoutMs,
783
814
  };
784
815
  }
785
816
 
@@ -792,7 +823,7 @@ function resolveLaunch(workspaceDir, packageDir, env, { devMode, forceSourceBuil
792
823
  args: [],
793
824
  cwd: workspaceDir,
794
825
  env,
795
- healthTimeoutMs: DEFAULT_HEALTH_TIMEOUT_MS,
826
+ healthTimeoutMs: defaultHealthTimeoutMs,
796
827
  };
797
828
  }
798
829
 
@@ -804,7 +835,7 @@ function resolveLaunch(workspaceDir, packageDir, env, { devMode, forceSourceBuil
804
835
  args: [],
805
836
  cwd: workspaceDir,
806
837
  env,
807
- healthTimeoutMs: DEFAULT_HEALTH_TIMEOUT_MS,
838
+ healthTimeoutMs: defaultHealthTimeoutMs,
808
839
  };
809
840
  }
810
841
 
@@ -833,7 +864,7 @@ function resolveLaunch(workspaceDir, packageDir, env, { devMode, forceSourceBuil
833
864
  args: [],
834
865
  cwd: workspaceDir,
835
866
  env,
836
- healthTimeoutMs: DEFAULT_HEALTH_TIMEOUT_MS,
867
+ healthTimeoutMs: defaultHealthTimeoutMs,
837
868
  };
838
869
  }
839
870
 
@@ -149,7 +149,7 @@ dependencies = [
149
149
 
150
150
  [[package]]
151
151
  name = "codex-rust-bridge"
152
- version = "5.1.3-internal.8"
152
+ version = "5.1.3-internal.9"
153
153
  dependencies = [
154
154
  "axum",
155
155
  "base64",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "codex-rust-bridge"
3
- version = "5.1.3-internal.8"
3
+ version = "5.1.3-internal.9"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -8202,7 +8202,7 @@ fn thread_list_stream_request_params(include_sub_agents: bool, limit: usize) ->
8202
8202
  json!({
8203
8203
  "cursor": Value::Null,
8204
8204
  "limit": limit,
8205
- "sortKey": Value::Null,
8205
+ "sortKey": "updated_at",
8206
8206
  "modelProviders": Value::Null,
8207
8207
  "sourceKinds": source_kinds,
8208
8208
  "archived": false,
@@ -8258,7 +8258,7 @@ async fn list_workspace_roots(
8258
8258
  Some(json!({
8259
8259
  "cursor": Value::Null,
8260
8260
  "limit": limit,
8261
- "sortKey": Value::Null,
8261
+ "sortKey": "updated_at",
8262
8262
  "modelProviders": Value::Null,
8263
8263
  "sourceKinds": ["cli", "vscode", "exec", "appServer", "unknown"],
8264
8264
  "archived": false,