clawdex-mobile 5.0.8 → 5.1.2

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## 5.1.2 - 2026-04-07
6
+
7
+ ### Added
8
+ - Local preview browser workflow with desktop and overview shells for mobile web inspection.
9
+ - App-wide font preference support in the mobile client.
10
+
11
+ ### Improved
12
+ - Chat transcript tool-call UX now supports grouped tool-call inspection, per-call output expansion, and file-change labels that include changed filenames.
13
+ - Drawer, sheet, and chat header interactions feel smoother and more consistent across open/close, reconnect, and navigation flows.
14
+ - Composer and transcript responsiveness were tightened with lower rerender churn, more stable activity indicators, and cleaner compaction presentation.
15
+ - Browser preview controls, address handling, and preview session stability were refined for everyday use.
16
+ - Manual npm release runs can now build every packaged bridge target without publishing to npm.
17
+
18
+ ### Fixed
19
+ - Bridge restart cleanup and maintenance behavior are more reliable during repeated local development cycles.
20
+ - Queued thread messages now use guaranteed-unique bridge queue item IDs during blocked-turn queuing.
21
+ - Bridge self-update now reports shutdown failures cleanly while still preserving status updates and `.env.secure` backup cleanup.
22
+ - Browser preview and mobile UI regressions caught during review and CI were resolved before release.
23
+
5
24
  ## 1.1.0 - 2026-02-23
6
25
 
7
26
  ### Added
@@ -80,16 +80,20 @@ When both CLIs are selected, the bridge starts both backends and merges chat lis
80
80
 
81
81
  Open the installed mobile app on your phone, then scan the bridge QR. If needed, enter the bridge URL manually (for example `http://100.x.y.z:8787` or `http://192.168.x.y:8787`). The chosen bridge URL is stored on-device and can be changed later in Settings.
82
82
 
83
- ### In-app Bridge Update
83
+ ### In-app Bridge Maintenance
84
84
 
85
- For published `clawdex-mobile` CLI installs, the mobile Settings screen can start a bridge update safely.
85
+ For secure-launcher installs, the mobile Settings screen can trigger bridge maintenance safely.
86
86
 
87
87
  - Open `Settings > Bridge Maintenance`
88
- - Tap `Update bridge`
89
- - The app will disconnect briefly while a detached helper job stops the current bridge, runs `npm install -g clawdex-mobile@latest`, and starts the bridge again
88
+ - Tap `Restart bridge safely` to stop the current bridge and relaunch it through `scripts/start-bridge-secure.js`
89
+ - The app will disconnect briefly while the detached helper waits for bridge health to recover
90
+
91
+ Published `clawdex-mobile` CLI installs also expose `Update bridge`.
92
+
93
+ - `Update bridge` stops the current bridge, runs `npm install -g clawdex-mobile@latest`, and starts the bridge again
90
94
  - If the upgrade step fails, the helper attempts to restart the previous bridge automatically
91
95
 
92
- Source checkouts do not expose this button because they need repo-specific update logic that is not safe to automate generically from mobile.
96
+ Source checkouts expose only the restart action because repo-specific update logic is not safe to automate generically from mobile.
93
97
 
94
98
  ## Local Mobile Development Only
95
99
 
@@ -110,6 +114,39 @@ Optional environment variables:
110
114
  - `EXPO_AUTO_REPAIR=true` — auto-repair React Native runtime on `npm run mobile`
111
115
  - `EXPO_CLEAR_CACHE=true` — force `expo start --clear` via `npm run mobile`
112
116
 
117
+ ## Local Browser Preview
118
+
119
+ The mobile app includes a `Browser` screen that can open loopback-only web apps from the bridge
120
+ machine inside the app itself.
121
+
122
+ Typical examples:
123
+
124
+ - `localhost:3000`
125
+ - `127.0.0.1:5173`
126
+ - `3000`
127
+
128
+ How it works:
129
+
130
+ - The app creates a short-lived preview session through the bridge RPC API
131
+ - The bridge serves a dedicated preview origin on a separate port
132
+ - HTTP requests, subresources, cookies, and WebSocket/HMR traffic are proxied from the phone to
133
+ the bridge host's loopback target
134
+ - Browser runtime calls to other loopback origins on the host are also rewritten through the
135
+ preview origin for `fetch`, XHR, `EventSource`, `WebSocket`, and form submissions
136
+
137
+ Current scope:
138
+
139
+ - Supports `http://` and `https://` loopback targets only
140
+ - Intended for local web dev servers such as Next.js, Vite, CRA, or simple static servers
141
+ - Separate local frontend/backend ports can work together inside the preview as long as the app
142
+ reaches the backend through normal browser APIs or form posts
143
+ - Hard-coded absolute localhost asset URLs outside those browser APIs may still need a same-origin
144
+ dev proxy in the app itself
145
+ - Does not preview native React Native simulator/device UI directly
146
+
147
+ For a concise list of supported cases and known limitations, see
148
+ `docs/browser-preview-limitations.md`.
149
+
113
150
  ## Teardown / Cleanup
114
151
 
115
152
  ```bash
@@ -138,6 +175,7 @@ npm run teardown -- --yes
138
175
  |---|---|
139
176
  | `BRIDGE_HOST` | bind host for rust bridge |
140
177
  | `BRIDGE_PORT` | bridge port (default `8787`) |
178
+ | `BRIDGE_PREVIEW_PORT` | browser preview port for proxied localhost web apps (default `BRIDGE_PORT + 1`) |
141
179
  | `BRIDGE_AUTH_TOKEN` | required auth token |
142
180
  | `BRIDGE_ALLOW_QUERY_TOKEN_AUTH` | query-token auth fallback |
143
181
  | `CODEX_CLI_BIN` | codex executable |
@@ -207,6 +245,7 @@ Expected response contains `"status":"ok"`.
207
245
  6. Open Git from header and verify status/diff/commit/push behavior
208
246
  7. Test attachment menu (`+`) with workspace path + phone file/image
209
247
  8. Run long task and verify stop button interrupts run and transcript logs stop
248
+ 9. Open `Browser`, enter `localhost:3000` or another active loopback dev port, and verify the page loads inside the app
210
249
 
211
250
  ## Chat Controls (Workspace, Model, Mode, Approvals)
212
251
 
@@ -36,8 +36,20 @@ npm run stop:services
36
36
  - For the shipped mobile app, rescan the bridge QR or update the stored token in Settings.
37
37
  - For a local dev build, also ensure `BRIDGE_AUTH_TOKEN` in `.env.secure` matches `EXPO_PUBLIC_HOST_BRIDGE_TOKEN` in `apps/mobile/.env`.
38
38
  - Restart the bridge after token changes.
39
+ - On secure-launcher installs, `Settings > Bridge Maintenance > Restart bridge safely` can do that from the phone.
39
40
  - If an in-app bridge update fails, inspect `.bridge-updater.log` and `.bridge-update-status.json` in the bridge install root.
40
41
 
42
+ ## Local browser preview does not open
43
+
44
+ - The in-app browser only supports loopback targets from the bridge host: `localhost`, `127.0.0.1`, or `::1`.
45
+ - Use entries like `localhost:3000`, `127.0.0.1:5173`, or just a port number.
46
+ - If a separate local API runs on another port, make sure the app reaches it through `fetch`, XHR, `EventSource`, `WebSocket`, or a normal form post so the preview runtime can rewrite it through the bridge.
47
+ - See `docs/browser-preview-limitations.md` for the current support boundaries and known caveats.
48
+ - If Browser reports preview is unavailable, check whether `BRIDGE_PREVIEW_PORT` is already in use on the host.
49
+ - By default the preview server binds to `BRIDGE_PORT + 1`.
50
+ - Restart the bridge after changing `BRIDGE_PREVIEW_PORT`.
51
+ - If the page shell loads but live reload does not, verify the target dev server is still serving its WebSocket/HMR endpoint locally.
52
+
41
53
  ## Tailscale issues
42
54
 
43
55
  - Verify host and phone are on the same Tailscale network
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawdex-mobile",
3
- "version": "5.0.8",
3
+ "version": "5.1.2",
4
4
  "description": "Private-network mobile bridge and CLI for Codex and OpenCode",
5
5
  "keywords": [
6
6
  "codex",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
 
4
- const { spawn } = require("node:child_process");
4
+ const { spawn, spawnSync } = require("node:child_process");
5
5
  const fs = require("node:fs");
6
6
  const os = require("node:os");
7
7
  const path = require("node:path");
@@ -10,6 +10,7 @@ const https = require("node:https");
10
10
 
11
11
  function parseArgs(argv) {
12
12
  const parsed = {
13
+ action: "update",
13
14
  jobId: "",
14
15
  bridgePid: 0,
15
16
  version: "latest",
@@ -26,6 +27,9 @@ function parseArgs(argv) {
26
27
  }
27
28
 
28
29
  switch (flag) {
30
+ case "--action":
31
+ parsed.action = value;
32
+ break;
29
33
  case "--job-id":
30
34
  parsed.jobId = value;
31
35
  break;
@@ -53,6 +57,10 @@ function parseArgs(argv) {
53
57
  throw new Error("missing updater arguments");
54
58
  }
55
59
 
60
+ if (parsed.action !== "update" && parsed.action !== "restart") {
61
+ throw new Error(`unsupported bridge maintenance action: ${parsed.action}`);
62
+ }
63
+
56
64
  return parsed;
57
65
  }
58
66
 
@@ -94,6 +102,18 @@ function writeStatus(statusPath, payload) {
94
102
  fs.writeFileSync(statusPath, `${JSON.stringify(nextPayload, null, 2)}\n`);
95
103
  }
96
104
 
105
+ function readNonEmptyEnv(env, key) {
106
+ const value = env?.[key];
107
+ return typeof value === "string" && value.trim() ? value.trim() : "";
108
+ }
109
+
110
+ function formatHostForUrl(host) {
111
+ if (host.includes(":") && !host.startsWith("[")) {
112
+ return `[${host}]`;
113
+ }
114
+ return host;
115
+ }
116
+
97
117
  function backupSecureEnv(packageRoot, jobId) {
98
118
  const secureEnvPath = path.join(packageRoot, ".env.secure");
99
119
  if (!fs.existsSync(secureEnvPath)) {
@@ -166,23 +186,135 @@ function killBridgeProcess(pid) {
166
186
  }
167
187
  }
168
188
 
169
- async function waitForBridgeExit(pid) {
170
- for (let attempt = 0; attempt < 40; attempt += 1) {
189
+ function isProcessAlive(pid) {
190
+ try {
191
+ process.kill(pid, 0);
192
+ return true;
193
+ } catch {
194
+ return false;
195
+ }
196
+ }
197
+
198
+ function forceKillBridgeProcess(pid) {
199
+ if (process.platform === "win32") {
200
+ const result = spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], {
201
+ stdio: "ignore",
202
+ });
203
+ if (result.error && result.error.code !== "ENOENT") {
204
+ throw result.error;
205
+ }
206
+ return;
207
+ }
208
+
209
+ process.kill(pid, "SIGKILL");
210
+ }
211
+
212
+ function listMatchingPids(pattern) {
213
+ const result = spawnSync("ps", ["-ax", "-o", "pid=", "-o", "command="], {
214
+ encoding: "utf8",
215
+ });
216
+ if (result.error || result.status !== 0) {
217
+ return [];
218
+ }
219
+
220
+ return result.stdout
221
+ .split(/\r?\n/)
222
+ .map((line) => line.trim())
223
+ .filter(Boolean)
224
+ .map((line) => {
225
+ const match = line.match(/^(\d+)\s+(.*)$/);
226
+ if (!match) {
227
+ return null;
228
+ }
229
+ return {
230
+ pid: Number.parseInt(match[1], 10),
231
+ command: match[2],
232
+ };
233
+ })
234
+ .filter((entry) => entry && Number.isFinite(entry.pid) && pattern.test(entry.command))
235
+ .map((entry) => entry.pid);
236
+ }
237
+
238
+ function isOpencodeEnabled(env) {
239
+ const activeEngine = readNonEmptyEnv(env, "BRIDGE_ACTIVE_ENGINE");
240
+ const enabledEngines = readNonEmptyEnv(env, "BRIDGE_ENABLED_ENGINES");
241
+ return [activeEngine, enabledEngines].some((value) =>
242
+ value
243
+ .split(",")
244
+ .map((entry) => entry.trim())
245
+ .filter(Boolean)
246
+ .includes("opencode")
247
+ );
248
+ }
249
+
250
+ function buildOpencodeServePattern(port) {
251
+ const normalizedPort = String(port).trim().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
252
+ return new RegExp(`\\bopencode(?:\\.cmd|\\.exe)?\\b.*\\bserve\\b.*--port\\s+${normalizedPort}\\b`);
253
+ }
254
+
255
+ async function stopLingeringOpencodeServer(packageRoot) {
256
+ const secureEnvPath = path.join(packageRoot, ".env.secure");
257
+ if (!fs.existsSync(secureEnvPath)) {
258
+ return;
259
+ }
260
+
261
+ const secureEnv = readEnvFile(secureEnvPath);
262
+ if (!isOpencodeEnabled(secureEnv)) {
263
+ return;
264
+ }
265
+
266
+ const opencodePort = readNonEmptyEnv(secureEnv, "BRIDGE_OPENCODE_PORT") || "4090";
267
+ const pids = listMatchingPids(buildOpencodeServePattern(opencodePort));
268
+ if (pids.length === 0) {
269
+ return;
270
+ }
271
+
272
+ for (const pid of pids) {
171
273
  try {
172
- process.kill(pid, 0);
173
- } catch {
274
+ process.kill(pid, "SIGTERM");
275
+ } catch {}
276
+ }
277
+
278
+ for (let attempt = 0; attempt < 20; attempt += 1) {
279
+ const stillRunning = pids.filter((pid) => isProcessAlive(pid));
280
+ if (stillRunning.length === 0) {
174
281
  return;
175
282
  }
176
283
  await sleep(250);
177
284
  }
178
285
 
179
- if (process.platform !== "win32") {
286
+ for (const pid of pids) {
287
+ if (!isProcessAlive(pid)) {
288
+ continue;
289
+ }
180
290
  try {
181
- process.kill(pid, "SIGKILL");
182
- } catch {
291
+ forceKillBridgeProcess(pid);
292
+ } catch {}
293
+ }
294
+ }
295
+
296
+ async function waitForBridgeExit(pid) {
297
+ for (let attempt = 0; attempt < 40; attempt += 1) {
298
+ if (!isProcessAlive(pid)) {
299
+ return;
300
+ }
301
+ await sleep(250);
302
+ }
303
+
304
+ try {
305
+ forceKillBridgeProcess(pid);
306
+ } catch {
307
+ return;
308
+ }
309
+
310
+ for (let attempt = 0; attempt < 20; attempt += 1) {
311
+ if (!isProcessAlive(pid)) {
183
312
  return;
184
313
  }
314
+ await sleep(250);
185
315
  }
316
+
317
+ throw new Error("bridge process did not exit in time");
186
318
  }
187
319
 
188
320
  function startBridge(packageRoot, logPath) {
@@ -209,7 +341,7 @@ async function waitForHealth(envFilePath, timeoutMs) {
209
341
  const secureEnv = readEnvFile(envFilePath);
210
342
  const host = secureEnv.BRIDGE_HOST || "127.0.0.1";
211
343
  const port = secureEnv.BRIDGE_PORT || "8787";
212
- const url = new URL(`http://${host}:${port}/health`);
344
+ const url = new URL(`http://${formatHostForUrl(host)}:${port}/health`);
213
345
  const client = url.protocol === "https:" ? https : http;
214
346
  const startedAt = Date.now();
215
347
 
@@ -242,6 +374,7 @@ async function waitForHealth(envFilePath, timeoutMs) {
242
374
  }
243
375
 
244
376
  async function restartBridge(packageRoot, statusPath, payload, message) {
377
+ await stopLingeringOpencodeServer(packageRoot);
245
378
  writeStatus(statusPath, {
246
379
  ...payload,
247
380
  state: "starting",
@@ -256,13 +389,23 @@ async function restartBridge(packageRoot, statusPath, payload, message) {
256
389
  await waitForHealth(path.join(packageRoot, ".env.secure"), 45_000);
257
390
  }
258
391
 
392
+ async function stopCurrentBridge(statusPath, payload, bridgePid) {
393
+ writeStatus(statusPath, {
394
+ ...payload,
395
+ state: "stopping",
396
+ message: "Stopping the current bridge process.",
397
+ });
398
+ killBridgeProcess(bridgePid);
399
+ await waitForBridgeExit(bridgePid);
400
+ }
401
+
259
402
  async function main() {
260
403
  const args = parseArgs(process.argv.slice(2));
261
404
  const packageRoot = path.resolve(__dirname, "..");
262
405
  const secureEnvBackup = backupSecureEnv(packageRoot, args.jobId);
263
406
  const baseStatus = {
264
407
  jobId: args.jobId,
265
- targetVersion: args.version,
408
+ targetVersion: args.action === "restart" ? args.version || "current" : args.version,
266
409
  startedAt: args.startedAt,
267
410
  logPath: args.logPath || null,
268
411
  };
@@ -270,75 +413,113 @@ async function main() {
270
413
  writeStatus(args.statusPath, {
271
414
  ...baseStatus,
272
415
  state: "scheduled",
273
- message: `Bridge update scheduled for ${args.version}.`,
416
+ message:
417
+ args.action === "restart"
418
+ ? "Bridge restart scheduled."
419
+ : `Bridge update scheduled for ${args.version}.`,
274
420
  });
275
- await sleep(800);
276
-
277
- writeStatus(args.statusPath, {
278
- ...baseStatus,
279
- state: "stopping",
280
- message: "Stopping the current bridge process.",
281
- });
282
- killBridgeProcess(args.bridgePid);
283
- await waitForBridgeExit(args.bridgePid);
284
-
285
- let upgraded = false;
286
421
  try {
287
- writeStatus(args.statusPath, {
288
- ...baseStatus,
289
- state: "upgrading",
290
- message: `Installing clawdex-mobile@${args.version}.`,
291
- });
292
- await runCommand(npmCommand(), ["install", "-g", `clawdex-mobile@${args.version}`], {
293
- cwd: packageRoot,
294
- env: process.env,
295
- });
296
- restoreSecureEnv(secureEnvBackup);
297
- upgraded = true;
298
- await restartBridge(
299
- packageRoot,
300
- args.statusPath,
301
- baseStatus,
302
- "Starting the updated bridge process."
303
- );
304
- writeStatus(args.statusPath, {
305
- ...baseStatus,
306
- state: "completed",
307
- message: `Bridge updated to ${args.version} and restarted successfully.`,
308
- completedAt: new Date().toISOString(),
309
- });
310
- } catch (error) {
311
- console.error(error instanceof Error ? error.message : String(error));
422
+ await sleep(800);
423
+ await stopCurrentBridge(args.statusPath, baseStatus, args.bridgePid);
424
+
425
+ if (args.action === "restart") {
426
+ try {
427
+ await restartBridge(
428
+ packageRoot,
429
+ args.statusPath,
430
+ baseStatus,
431
+ "Starting the bridge process."
432
+ );
433
+ writeStatus(args.statusPath, {
434
+ ...baseStatus,
435
+ state: "completed",
436
+ message: "Bridge restarted successfully.",
437
+ completedAt: new Date().toISOString(),
438
+ });
439
+ } catch (error) {
440
+ writeStatus(args.statusPath, {
441
+ ...baseStatus,
442
+ state: "failed",
443
+ message:
444
+ error instanceof Error
445
+ ? error.message
446
+ : "Bridge restart failed and the bridge did not recover automatically.",
447
+ completedAt: new Date().toISOString(),
448
+ });
449
+ process.exitCode = 1;
450
+ }
451
+ return;
452
+ }
453
+
454
+ let upgraded = false;
312
455
  try {
456
+ writeStatus(args.statusPath, {
457
+ ...baseStatus,
458
+ state: "upgrading",
459
+ message: `Installing clawdex-mobile@${args.version}.`,
460
+ });
461
+ await runCommand(npmCommand(), ["install", "-g", `clawdex-mobile@${args.version}`], {
462
+ cwd: packageRoot,
463
+ env: process.env,
464
+ });
313
465
  restoreSecureEnv(secureEnvBackup);
466
+ upgraded = true;
314
467
  await restartBridge(
315
468
  packageRoot,
316
469
  args.statusPath,
317
470
  baseStatus,
318
- upgraded
319
- ? "Updated bridge failed to come up; restarting the previous bridge."
320
- : "Upgrade failed; restarting the previous bridge."
471
+ "Starting the updated bridge process."
321
472
  );
322
473
  writeStatus(args.statusPath, {
323
474
  ...baseStatus,
324
- state: "recovered",
325
- message: upgraded
326
- ? "Bridge update failed after install. The previous bridge was restarted."
327
- : "Bridge upgrade failed. The previous bridge was restarted.",
328
- completedAt: new Date().toISOString(),
329
- });
330
- } catch (restartError) {
331
- writeStatus(args.statusPath, {
332
- ...baseStatus,
333
- state: "failed",
334
- message:
335
- restartError instanceof Error
336
- ? restartError.message
337
- : "Bridge update failed and automatic recovery did not complete.",
475
+ state: "completed",
476
+ message: `Bridge updated to ${args.version} and restarted successfully.`,
338
477
  completedAt: new Date().toISOString(),
339
478
  });
340
- process.exitCode = 1;
479
+ } catch (error) {
480
+ console.error(error instanceof Error ? error.message : String(error));
481
+ try {
482
+ restoreSecureEnv(secureEnvBackup);
483
+ await restartBridge(
484
+ packageRoot,
485
+ args.statusPath,
486
+ baseStatus,
487
+ upgraded
488
+ ? "Updated bridge failed to come up; restarting the previous bridge."
489
+ : "Upgrade failed; restarting the previous bridge."
490
+ );
491
+ writeStatus(args.statusPath, {
492
+ ...baseStatus,
493
+ state: "recovered",
494
+ message: upgraded
495
+ ? "Bridge update failed after install. The previous bridge was restarted."
496
+ : "Bridge upgrade failed. The previous bridge was restarted.",
497
+ completedAt: new Date().toISOString(),
498
+ });
499
+ } catch (restartError) {
500
+ writeStatus(args.statusPath, {
501
+ ...baseStatus,
502
+ state: "failed",
503
+ message:
504
+ restartError instanceof Error
505
+ ? restartError.message
506
+ : "Bridge update failed and automatic recovery did not complete.",
507
+ completedAt: new Date().toISOString(),
508
+ });
509
+ process.exitCode = 1;
510
+ }
341
511
  }
512
+ } catch (error) {
513
+ writeStatus(args.statusPath, {
514
+ ...baseStatus,
515
+ state: "failed",
516
+ message:
517
+ error instanceof Error
518
+ ? error.message
519
+ : "Bridge maintenance failed before restart or recovery could begin.",
520
+ completedAt: new Date().toISOString(),
521
+ });
522
+ process.exitCode = 1;
342
523
  } finally {
343
524
  cleanupSecureEnvBackup(secureEnvBackup);
344
525
  }
@@ -579,6 +579,9 @@ async function start() {
579
579
  const fileEnv = readEnvFile(secureEnvFile);
580
580
  const env = { ...fileEnv, ...process.env };
581
581
  const devMode = process.argv.includes("--dev") || env.BRIDGE_RUN_MODE === "dev";
582
+ if (devMode) {
583
+ env.BRIDGE_RUN_MODE = "dev";
584
+ }
582
585
  const backgroundMode = process.argv.includes("--background");
583
586
  const forceSourceBuild = env.CLAWDEX_BRIDGE_FORCE_SOURCE_BUILD === "true";
584
587
  const launch = resolveLaunch(rootDir, env, { devMode, forceSourceBuild });
@@ -149,7 +149,7 @@ dependencies = [
149
149
 
150
150
  [[package]]
151
151
  name = "codex-rust-bridge"
152
- version = "5.0.8"
152
+ version = "5.1.2"
153
153
  dependencies = [
154
154
  "axum",
155
155
  "base64",
@@ -162,6 +162,7 @@ dependencies = [
162
162
  "serde_json",
163
163
  "shlex",
164
164
  "tokio",
165
+ "tokio-tungstenite",
165
166
  ]
166
167
 
167
168
  [[package]]
@@ -278,6 +279,12 @@ version = "0.3.32"
278
279
  source = "registry+https://github.com/rust-lang/crates.io-index"
279
280
  checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
280
281
 
282
+ [[package]]
283
+ name = "futures-io"
284
+ version = "0.3.32"
285
+ source = "registry+https://github.com/rust-lang/crates.io-index"
286
+ checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
287
+
281
288
  [[package]]
282
289
  name = "futures-macro"
283
290
  version = "0.3.32"
@@ -308,9 +315,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
308
315
  checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
309
316
  dependencies = [
310
317
  "futures-core",
318
+ "futures-io",
311
319
  "futures-macro",
312
320
  "futures-sink",
313
321
  "futures-task",
322
+ "memchr",
314
323
  "pin-project-lite",
315
324
  "slab",
316
325
  ]
@@ -433,7 +442,7 @@ dependencies = [
433
442
  "tokio",
434
443
  "tokio-rustls",
435
444
  "tower-service",
436
- "webpki-roots",
445
+ "webpki-roots 1.0.6",
437
446
  ]
438
447
 
439
448
  [[package]]
@@ -932,14 +941,16 @@ dependencies = [
932
941
  "sync_wrapper",
933
942
  "tokio",
934
943
  "tokio-rustls",
944
+ "tokio-util",
935
945
  "tower",
936
946
  "tower-http",
937
947
  "tower-service",
938
948
  "url",
939
949
  "wasm-bindgen",
940
950
  "wasm-bindgen-futures",
951
+ "wasm-streams",
941
952
  "web-sys",
942
- "webpki-roots",
953
+ "webpki-roots 1.0.6",
943
954
  ]
944
955
 
945
956
  [[package]]
@@ -1277,8 +1288,25 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
1277
1288
  dependencies = [
1278
1289
  "futures-util",
1279
1290
  "log",
1291
+ "rustls",
1292
+ "rustls-pki-types",
1280
1293
  "tokio",
1294
+ "tokio-rustls",
1281
1295
  "tungstenite",
1296
+ "webpki-roots 0.26.11",
1297
+ ]
1298
+
1299
+ [[package]]
1300
+ name = "tokio-util"
1301
+ version = "0.7.18"
1302
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1303
+ checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
1304
+ dependencies = [
1305
+ "bytes",
1306
+ "futures-core",
1307
+ "futures-sink",
1308
+ "pin-project-lite",
1309
+ "tokio",
1282
1310
  ]
1283
1311
 
1284
1312
  [[package]]
@@ -1365,6 +1393,8 @@ dependencies = [
1365
1393
  "httparse",
1366
1394
  "log",
1367
1395
  "rand",
1396
+ "rustls",
1397
+ "rustls-pki-types",
1368
1398
  "sha1",
1369
1399
  "thiserror",
1370
1400
  "utf-8",
@@ -1507,6 +1537,19 @@ dependencies = [
1507
1537
  "unicode-ident",
1508
1538
  ]
1509
1539
 
1540
+ [[package]]
1541
+ name = "wasm-streams"
1542
+ version = "0.4.2"
1543
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1544
+ checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
1545
+ dependencies = [
1546
+ "futures-util",
1547
+ "js-sys",
1548
+ "wasm-bindgen",
1549
+ "wasm-bindgen-futures",
1550
+ "web-sys",
1551
+ ]
1552
+
1510
1553
  [[package]]
1511
1554
  name = "web-sys"
1512
1555
  version = "0.3.91"
@@ -1527,6 +1570,15 @@ dependencies = [
1527
1570
  "wasm-bindgen",
1528
1571
  ]
1529
1572
 
1573
+ [[package]]
1574
+ name = "webpki-roots"
1575
+ version = "0.26.11"
1576
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1577
+ checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
1578
+ dependencies = [
1579
+ "webpki-roots 1.0.6",
1580
+ ]
1581
+
1530
1582
  [[package]]
1531
1583
  name = "webpki-roots"
1532
1584
  version = "1.0.6"