mindwire 0.1.38 → 0.1.40

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 (39) hide show
  1. package/README.md +16 -0
  2. package/dist/{chunk-CKTVMUS4.js → chunk-BJL5K6M7.js} +50 -16
  3. package/dist/chunk-BJL5K6M7.js.map +1 -0
  4. package/dist/chunk-ZP7F7LP7.js +306 -0
  5. package/dist/chunk-ZP7F7LP7.js.map +1 -0
  6. package/dist/cli.js +499 -250
  7. package/dist/cli.js.map +1 -1
  8. package/dist/computer/dashboard.d.ts +1 -0
  9. package/dist/computer/desktop.d.ts +17 -0
  10. package/dist/computer/directory-http.d.ts +1 -1
  11. package/dist/computer/discovery.d.ts +22 -0
  12. package/dist/computer/inspection.d.ts +30 -0
  13. package/dist/computer/lifecycle.d.ts +4 -2
  14. package/dist/computer/runtime-version.d.ts +6 -0
  15. package/dist/computer/service-update.d.ts +26 -0
  16. package/dist/computer/setup-prompt.d.ts +2 -0
  17. package/dist/computer/startup.d.ts +7 -0
  18. package/dist/computer/terminal-ui.d.ts +9 -0
  19. package/dist/computer.d.ts +2 -0
  20. package/dist/{connection-change-5F4WNCYV.js → connection-change-7ZV6O75Q.js} +3 -3
  21. package/dist/{connection-change-5F4WNCYV.js.map → connection-change-7ZV6O75Q.js.map} +1 -1
  22. package/dist/{controller-3SZI7TBW.js → controller-FBMGMSLM.js} +67 -9
  23. package/dist/controller-FBMGMSLM.js.map +1 -0
  24. package/dist/{controller-handoff-KV7WRDAI.js → controller-handoff-CJKXUFQI.js} +3 -3
  25. package/dist/{controller-handoff-KV7WRDAI.js.map → controller-handoff-CJKXUFQI.js.map} +1 -1
  26. package/dist/daemon-binary.d.ts +2 -0
  27. package/dist/index.cjs +41 -7
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.js +41 -7
  31. package/dist/index.js.map +1 -1
  32. package/dist/project-sync.d.ts +29 -0
  33. package/dist/surfaces.d.ts +20 -1
  34. package/dist/types.d.ts +2 -0
  35. package/package.json +1 -1
  36. package/dist/chunk-CKTVMUS4.js.map +0 -1
  37. package/dist/chunk-QODJKRFK.js +0 -20
  38. package/dist/chunk-QODJKRFK.js.map +0 -1
  39. package/dist/controller-3SZI7TBW.js.map +0 -1
package/README.md CHANGED
@@ -23,6 +23,22 @@ npm i mindwire
23
23
 
24
24
  ## Quick start
25
25
 
26
+ To connect this computer to the Mindwire mobile app, install globally and run
27
+ `mindwire connect`. Run `mindwire` for the interactive status and management menu.
28
+ On a Mac, desktop access is a separate opt-in:
29
+
30
+ ```sh
31
+ mindwire desktop enable # Guided local Screen Sharing approval
32
+ mindwire desktop # Check setup or update the saved Mac login
33
+ mindwire desktop disable # Close desktop access and forget its login
34
+ ```
35
+
36
+ The phone uses its existing paired SSH tunnel and never receives the Mac password.
37
+ Opening a workspace or checking status does not enable screen access. See the
38
+ [desktop contract](../../daemon/DESKTOP.md#personal-mac-desktop) for platform support,
39
+ permissions and the shared input protocol. Existing installations need a release
40
+ advertising `health().localDesktopVersion >= 1`.
41
+
26
42
  ```ts
27
43
  import { Mindwire } from "mindwire";
28
44
 
@@ -88,7 +88,7 @@ function computerPairingURI(invitation) {
88
88
  }
89
89
 
90
90
  // src/version.ts
91
- var SDK_VERSION = "0.1.38" ;
91
+ var SDK_VERSION = "0.1.40" ;
92
92
  function versionAtLeast(actual, desired) {
93
93
  if (actual === desired) return true;
94
94
  if (!actual || !/^\d+\.\d+\.\d+$/.test(actual) || !/^\d+\.\d+\.\d+$/.test(desired)) return false;
@@ -139,7 +139,7 @@ async function ensureDaemonBinary(opts = {}) {
139
139
  if (!request) throw new MindwireError("mindwire: fetch is unavailable; set daemonBin or MINDWIRE_DAEMON");
140
140
  const [checksums, binary] = await Promise.all([request(`${release}/checksums.txt`), request(`${release}/${asset}`)]);
141
141
  if (!checksums.ok || !binary.ok) {
142
- if (!opts.releaseBaseUrl && !proc.process?.env?.MINDWIRE_RELEASE_BASE_URL) {
142
+ if (!opts.exactVersion && !opts.releaseBaseUrl && !proc.process?.env?.MINDWIRE_RELEASE_BASE_URL) {
143
143
  const latest = await request("https://api.github.com/repos/oblien/mindwire/releases/latest");
144
144
  if (latest.ok) {
145
145
  const tag = (await latest.json()).tag_name;
@@ -1092,6 +1092,18 @@ var ProjectSyncError = class extends MindwireError {
1092
1092
  };
1093
1093
  var active = (o) => ["queued", "exporting", "preparing", "applying"].includes(o.status);
1094
1094
  var prefix = "/workspace/sync";
1095
+ var selectionPaths = (paths = []) => {
1096
+ const sorted = [...new Set(paths.map((path5) => path5.replace(/\/$/, "")))].sort();
1097
+ const selected = new Set(sorted);
1098
+ return sorted.filter((path5) => {
1099
+ let parent = path5;
1100
+ while (parent.includes("/")) {
1101
+ parent = parent.slice(0, parent.lastIndexOf("/"));
1102
+ if (selected.has(parent)) return false;
1103
+ }
1104
+ return true;
1105
+ });
1106
+ };
1095
1107
  function delay4(ms, signal) {
1096
1108
  signal?.throwIfAborted();
1097
1109
  return new Promise((resolve3, reject) => {
@@ -1114,7 +1126,16 @@ var ProjectSyncApi = class {
1114
1126
  }
1115
1127
  mw;
1116
1128
  flights = /* @__PURE__ */ new Map();
1117
- export(request, options = {}) {
1129
+ async requireSelectionSupport() {
1130
+ if (((await this.mw.health()).projectSyncVersion ?? 0) < 2)
1131
+ throw new MindwireError("Update Mindwire on both workspaces to review and switch selected project files.");
1132
+ }
1133
+ async preview(request, options = {}) {
1134
+ await this.requireSelectionSupport();
1135
+ return this.mw.http.request("POST", `${prefix}/preview`, { body: request, ...options });
1136
+ }
1137
+ async export(request, options = {}) {
1138
+ await this.requireSelectionSupport();
1118
1139
  return this.mw.http.request("POST", `${prefix}/exports`, { body: request, ...options });
1119
1140
  }
1120
1141
  import(request, options = {}) {
@@ -1199,6 +1220,7 @@ var ProjectSyncApi = class {
1199
1220
  * throws ProjectSyncError carrying the complete conflict/recovery operation.
1200
1221
  */
1201
1222
  switchTo(target, request, options = {}) {
1223
+ request = { ...request, includeIgnored: selectionPaths(request.includeIgnored) };
1202
1224
  const intent = JSON.stringify(request);
1203
1225
  const old = this.flights.get(request.id);
1204
1226
  if (old) {
@@ -1214,7 +1236,8 @@ var ProjectSyncApi = class {
1214
1236
  if (!(error instanceof ApiError) || error.status !== 404) throw error;
1215
1237
  }
1216
1238
  if (accepted) {
1217
- if ((accepted.path ?? "") !== (request.path ?? "")) throw new MindwireError("This sync ID belongs to a different destination folder.");
1239
+ if ((accepted.path ?? "") !== (request.path ?? "") || (accepted.selectionToken ?? "") !== (request.selectionToken ?? "") || JSON.stringify(selectionPaths(accepted.includeIgnored)) !== JSON.stringify(request.includeIgnored))
1240
+ throw new MindwireError("This sync ID belongs to a different destination folder or file selection.");
1218
1241
  const operation = await target.wait(accepted.id, {
1219
1242
  signal: options.signal,
1220
1243
  onUpdate: (operation2) => options.onProgress?.({ phase: "apply", transferredBytes: 0, operation: operation2 })
@@ -1223,11 +1246,11 @@ var ProjectSyncApi = class {
1223
1246
  return operation;
1224
1247
  }
1225
1248
  const health = await Promise.all([this.mw.health(), target.mw.health()]);
1226
- if (health.some((h) => (h.projectSyncVersion ?? 0) < 1)) throw new MindwireError("Update Mindwire on both workspaces to switch this project.");
1249
+ if (health.some((h) => (h.projectSyncVersion ?? 0) < 2)) throw new MindwireError("Update Mindwire on both workspaces to review and switch selected project files.");
1227
1250
  let bytes = 0;
1228
1251
  const emit2 = (phase, operation) => options.onProgress?.({ phase, transferredBytes: bytes, operation });
1229
1252
  emit2("checkpoint");
1230
- let o = await this.export({ id: `${request.id}-export`, projectId: request.projectId }, options);
1253
+ let o = await this.export({ id: `${request.id}-export`, projectId: request.projectId, includeIgnored: request.includeIgnored, selectionToken: request.selectionToken }, options);
1231
1254
  o = await this.wait(o.id, { signal: options.signal, onUpdate: (value) => emit2("checkpoint", value) });
1232
1255
  if (o.status !== "succeeded" || !o.resultCheckpointId) throw new ProjectSyncError(o);
1233
1256
  emit2("transfer");
@@ -1235,7 +1258,7 @@ var ProjectSyncApi = class {
1235
1258
  bytes += n;
1236
1259
  emit2("transfer");
1237
1260
  } });
1238
- o = await target.import({ id: `${request.id}-import`, checkpointId: o.resultCheckpointId, path: request.path }, options);
1261
+ o = await target.import({ id: `${request.id}-import`, checkpointId: o.resultCheckpointId, path: request.path, includeIgnored: request.includeIgnored, selectionToken: request.selectionToken }, options);
1239
1262
  o = await target.wait(o.id, { signal: options.signal, onUpdate: (value) => emit2("apply", value) });
1240
1263
  if (o.status !== "succeeded") throw new ProjectSyncError(o);
1241
1264
  return o;
@@ -1472,6 +1495,17 @@ var SurfacesApi = class {
1472
1495
  bind(binding) {
1473
1496
  return this.mw.http.request("PUT", "/surfaces/desktop/binding", { body: binding });
1474
1497
  }
1498
+ localStatus() {
1499
+ return this.mw.http.request("GET", "/surfaces/desktop/local");
1500
+ }
1501
+ /** Local CLI only. The separate 0600 control credential is not part of phone pairing. */
1502
+ configureLocal(settings, localControlToken) {
1503
+ if (!localControlToken) throw new Error("Run mindwire desktop on your Mac to manage desktop access.");
1504
+ return this.mw.http.request("PUT", "/surfaces/desktop/local", {
1505
+ body: settings,
1506
+ headers: { "X-Mindwire-Local-Control": localControlToken }
1507
+ });
1508
+ }
1475
1509
  open(request) {
1476
1510
  return this.mw.http.request("POST", "/surfaces/desktop/sessions", { body: request });
1477
1511
  }
@@ -2416,7 +2450,7 @@ var NotifyApi = class {
2416
2450
  };
2417
2451
 
2418
2452
  // src/computer/lifecycle.ts
2419
- var CONTROLLER_PROTOCOL = 3;
2453
+ var CONTROLLER_PROTOCOL = 4;
2420
2454
  var defaultStateDirectory = () => path4.join(homedir(), ".mindwire", "computer");
2421
2455
  var defaultComputerConfig = () => ({ directory: homedir(), bind: "0.0.0.0", sshPort: 8791, websocketPort: 8792, relay: { kind: "cloudflare" } });
2422
2456
  async function readJSON(file) {
@@ -2436,13 +2470,13 @@ async function writeJSON(file, value) {
2436
2470
  await fs2.rm(temp, { force: true });
2437
2471
  }
2438
2472
  }
2439
- async function computerClient(directory) {
2473
+ async function computerClient(directory, requestTimeoutMs = 3e3) {
2440
2474
  const runtime = await readJSON(path4.join(directory, "computer-runtime.json"));
2441
2475
  if (!runtime) throw new Error("Mindwire is not running. Run mindwire connect on the computer.");
2442
2476
  const url = new URL(`http://${runtime.apiAddress}`);
2443
2477
  if (!["127.0.0.1", "[::1]"].includes(url.hostname) || url.username || url.password) throw new Error("Invalid local Mindwire address.");
2444
2478
  const token = (await fs2.readFile(path4.join(directory, "daemon.token"), "utf8")).trim();
2445
- const client = new Mindwire({ target: remote(url.origin, { token }), requestTimeoutMs: 3e3 });
2479
+ const client = new Mindwire({ target: remote(url.origin, { token }), requestTimeoutMs });
2446
2480
  const info = await client.computer.info();
2447
2481
  if (info.computerId !== runtime.computerId || info.pid !== runtime.pid) throw new Error("The local Mindwire process changed. Retry the command.");
2448
2482
  return client;
@@ -2519,7 +2553,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
2519
2553
  if (!compatible(controller2) || !await processStateAlive(controller2)) {
2520
2554
  await ensureComputer(directory, cliPath, {}, onProgress, { ...options, waitForRoutes: false });
2521
2555
  }
2522
- const { changeComputerConnection } = await import('./connection-change-5F4WNCYV.js');
2556
+ const { changeComputerConnection } = await import('./connection-change-7ZV6O75Q.js');
2523
2557
  await changeComputerConnection(directory, Object.fromEntries(changed.map((key) => [key, patch[key]])), { signal: options.signal, onProgress });
2524
2558
  return computerClient(directory);
2525
2559
  }
@@ -2560,7 +2594,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
2560
2594
  let controller = await readJSON(path4.join(directory, "computer-controller.json"));
2561
2595
  if (existing && controller && !compatible(controller) && await processStateAlive(controller)) {
2562
2596
  onProgress?.("Refreshing the background connection service\u2026");
2563
- const { handoffController } = await import('./controller-handoff-KV7WRDAI.js');
2597
+ const { handoffController } = await import('./controller-handoff-CJKXUFQI.js');
2564
2598
  await handoffController(directory, controller, config, await existing.computer.info());
2565
2599
  controller = void 0;
2566
2600
  }
@@ -2594,7 +2628,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
2594
2628
  }
2595
2629
  }
2596
2630
  async function superviseComputer(directory) {
2597
- const controller = await import('./controller-3SZI7TBW.js');
2631
+ const controller = await import('./controller-FBMGMSLM.js');
2598
2632
  await controller.superviseComputer(directory);
2599
2633
  }
2600
2634
  async function stopComputer(directory, force = false) {
@@ -2618,6 +2652,6 @@ async function stopComputer(directory, force = false) {
2618
2652
  throw new Error("Mindwire is still stopping. Check computer.log.");
2619
2653
  }
2620
2654
 
2621
- export { CONTROLLER_PROTOCOL, ProviderConnectionError, RelayOutput, SDK_VERSION, acquireProcessLock, adoptProcess, adoptRelay, cloudflareCommand, computerClient, computerPairingQRData, computerPairingURI, currentProcessIdentity, defaultComputerConfig, defaultStateDirectory, directRoutes, ensureComputer, ensureDaemonBinary, hasCertificateError, ownChild, processIdentity, processStateAlive, providerFailure, providerNeedsAction, readJSON, startRelay, stopComputer, superviseComputer, websocketURL, writeJSON };
2622
- //# sourceMappingURL=chunk-CKTVMUS4.js.map
2623
- //# sourceMappingURL=chunk-CKTVMUS4.js.map
2655
+ export { CONTROLLER_PROTOCOL, ProviderConnectionError, RelayOutput, SDK_VERSION, acquireProcessLock, adoptProcess, adoptRelay, cloudflareCommand, computerClient, computerPairingQRData, computerPairingURI, currentProcessIdentity, defaultComputerConfig, defaultStateDirectory, directRoutes, ensureComputer, ensureDaemonBinary, hasCertificateError, ownChild, processIdentity, processStateAlive, providerFailure, providerNeedsAction, readJSON, startRelay, stopComputer, superviseComputer, versionAtLeast, websocketURL, writeJSON };
2656
+ //# sourceMappingURL=chunk-BJL5K6M7.js.map
2657
+ //# sourceMappingURL=chunk-BJL5K6M7.js.map