mindwire 0.1.36 → 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.
- package/README.md +16 -0
- package/dist/{chunk-RTGZDLSG.js → chunk-BJL5K6M7.js} +74 -21
- package/dist/chunk-BJL5K6M7.js.map +1 -0
- package/dist/chunk-ZP7F7LP7.js +306 -0
- package/dist/chunk-ZP7F7LP7.js.map +1 -0
- package/dist/cli.js +499 -250
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +6 -8
- package/dist/computer/dashboard.d.ts +1 -0
- package/dist/computer/desktop.d.ts +17 -0
- package/dist/computer/directory-http.d.ts +1 -1
- package/dist/computer/discovery.d.ts +22 -0
- package/dist/computer/inspection.d.ts +30 -0
- package/dist/computer/lifecycle.d.ts +4 -2
- package/dist/computer/runtime-version.d.ts +6 -0
- package/dist/computer/service-update.d.ts +26 -0
- package/dist/computer/setup-prompt.d.ts +2 -0
- package/dist/computer/startup.d.ts +7 -0
- package/dist/computer/terminal-ui.d.ts +9 -0
- package/dist/computer.d.ts +2 -0
- package/dist/{connection-change-IBNL42BL.js → connection-change-7ZV6O75Q.js} +3 -3
- package/dist/{connection-change-IBNL42BL.js.map → connection-change-7ZV6O75Q.js.map} +1 -1
- package/dist/{controller-2SJLZMJZ.js → controller-FBMGMSLM.js} +67 -9
- package/dist/controller-FBMGMSLM.js.map +1 -0
- package/dist/{controller-handoff-RUUHODNC.js → controller-handoff-CJKXUFQI.js} +3 -3
- package/dist/{controller-handoff-RUUHODNC.js.map → controller-handoff-CJKXUFQI.js.map} +1 -1
- package/dist/conversations.d.ts +57 -0
- package/dist/daemon-binary.d.ts +2 -0
- package/dist/index.cjs +66 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +66 -13
- package/dist/index.js.map +1 -1
- package/dist/project-sync.d.ts +29 -0
- package/dist/surfaces.d.ts +20 -1
- package/dist/types.d.ts +18 -0
- package/dist/workspace.d.ts +2 -0
- package/package.json +1 -1
- package/dist/chunk-67BNDGRK.js +0 -20
- package/dist/chunk-67BNDGRK.js.map +0 -1
- package/dist/chunk-RTGZDLSG.js.map +0 -1
- package/dist/controller-2SJLZMJZ.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.
|
|
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
|
-
|
|
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 ?? "")
|
|
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) <
|
|
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;
|
|
@@ -1246,6 +1269,23 @@ var ProjectSyncApi = class {
|
|
|
1246
1269
|
}
|
|
1247
1270
|
};
|
|
1248
1271
|
|
|
1272
|
+
// src/conversations.ts
|
|
1273
|
+
var ConversationsApi = class {
|
|
1274
|
+
constructor(mw) {
|
|
1275
|
+
this.mw = mw;
|
|
1276
|
+
}
|
|
1277
|
+
mw;
|
|
1278
|
+
/** Read-only; includes folders not registered as Mindwire projects. */
|
|
1279
|
+
list(query = {}) {
|
|
1280
|
+
return this.mw.http.request("GET", "/workspace/conversations", { query: { ...query } });
|
|
1281
|
+
}
|
|
1282
|
+
/** Idempotently associates the selected native session with its original folder.
|
|
1283
|
+
* Use chatId with messages()/turn() and the ordinary chat APIs afterward. */
|
|
1284
|
+
open(request) {
|
|
1285
|
+
return this.mw.http.request("POST", "/workspace/conversations/open", { body: request });
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
|
|
1249
1289
|
// src/workspace.ts
|
|
1250
1290
|
var ProjectOperationsApi = class {
|
|
1251
1291
|
constructor(mw) {
|
|
@@ -1317,6 +1357,7 @@ var WorkspaceCollection = class {
|
|
|
1317
1357
|
var WorkspaceApi = class {
|
|
1318
1358
|
constructor(mw) {
|
|
1319
1359
|
this.mw = mw;
|
|
1360
|
+
this.conversations = new ConversationsApi(mw);
|
|
1320
1361
|
this.sync = new ProjectSyncApi(mw);
|
|
1321
1362
|
this.git = new GitAccessApi(mw);
|
|
1322
1363
|
this.operations = new ProjectOperationsApi(mw);
|
|
@@ -1325,6 +1366,7 @@ var WorkspaceApi = class {
|
|
|
1325
1366
|
this.chats = new WorkspaceCollection(mw, "chats");
|
|
1326
1367
|
}
|
|
1327
1368
|
mw;
|
|
1369
|
+
conversations;
|
|
1328
1370
|
sync;
|
|
1329
1371
|
git;
|
|
1330
1372
|
operations;
|
|
@@ -1453,6 +1495,17 @@ var SurfacesApi = class {
|
|
|
1453
1495
|
bind(binding) {
|
|
1454
1496
|
return this.mw.http.request("PUT", "/surfaces/desktop/binding", { body: binding });
|
|
1455
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
|
+
}
|
|
1456
1509
|
open(request) {
|
|
1457
1510
|
return this.mw.http.request("POST", "/surfaces/desktop/sessions", { body: request });
|
|
1458
1511
|
}
|
|
@@ -1958,14 +2011,14 @@ var Mindwire = class _Mindwire {
|
|
|
1958
2011
|
}
|
|
1959
2012
|
/**
|
|
1960
2013
|
* `POST /chats/{id}/fork` — clone a chat into a new id (generated when `newChatId` is omitted).
|
|
1961
|
-
*
|
|
1962
|
-
*
|
|
1963
|
-
*
|
|
1964
|
-
*
|
|
2014
|
+
* Codex and Claude preserve native context. `beforeMessageId` excludes that prompt and every
|
|
2015
|
+
* later message; send the edited prompt to the returned chat with `turn`. Reuse `newChatId`
|
|
2016
|
+
* and the turn's `requestId` on retries. The source chat and filesystem are unchanged.
|
|
2017
|
+
* A source with a live turn returns 409; an unknown source returns 404.
|
|
1965
2018
|
*/
|
|
1966
2019
|
forkChat(chatId, opts = {}) {
|
|
1967
2020
|
return this.http.request("POST", `/chats/${encodeURIComponent(chatId)}/fork`, {
|
|
1968
|
-
body: opts
|
|
2021
|
+
body: opts
|
|
1969
2022
|
});
|
|
1970
2023
|
}
|
|
1971
2024
|
/**
|
|
@@ -2397,7 +2450,7 @@ var NotifyApi = class {
|
|
|
2397
2450
|
};
|
|
2398
2451
|
|
|
2399
2452
|
// src/computer/lifecycle.ts
|
|
2400
|
-
var CONTROLLER_PROTOCOL =
|
|
2453
|
+
var CONTROLLER_PROTOCOL = 4;
|
|
2401
2454
|
var defaultStateDirectory = () => path4.join(homedir(), ".mindwire", "computer");
|
|
2402
2455
|
var defaultComputerConfig = () => ({ directory: homedir(), bind: "0.0.0.0", sshPort: 8791, websocketPort: 8792, relay: { kind: "cloudflare" } });
|
|
2403
2456
|
async function readJSON(file) {
|
|
@@ -2417,13 +2470,13 @@ async function writeJSON(file, value) {
|
|
|
2417
2470
|
await fs2.rm(temp, { force: true });
|
|
2418
2471
|
}
|
|
2419
2472
|
}
|
|
2420
|
-
async function computerClient(directory) {
|
|
2473
|
+
async function computerClient(directory, requestTimeoutMs = 3e3) {
|
|
2421
2474
|
const runtime = await readJSON(path4.join(directory, "computer-runtime.json"));
|
|
2422
2475
|
if (!runtime) throw new Error("Mindwire is not running. Run mindwire connect on the computer.");
|
|
2423
2476
|
const url = new URL(`http://${runtime.apiAddress}`);
|
|
2424
2477
|
if (!["127.0.0.1", "[::1]"].includes(url.hostname) || url.username || url.password) throw new Error("Invalid local Mindwire address.");
|
|
2425
2478
|
const token = (await fs2.readFile(path4.join(directory, "daemon.token"), "utf8")).trim();
|
|
2426
|
-
const client = new Mindwire({ target: remote(url.origin, { token }), requestTimeoutMs
|
|
2479
|
+
const client = new Mindwire({ target: remote(url.origin, { token }), requestTimeoutMs });
|
|
2427
2480
|
const info = await client.computer.info();
|
|
2428
2481
|
if (info.computerId !== runtime.computerId || info.pid !== runtime.pid) throw new Error("The local Mindwire process changed. Retry the command.");
|
|
2429
2482
|
return client;
|
|
@@ -2500,7 +2553,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
|
|
|
2500
2553
|
if (!compatible(controller2) || !await processStateAlive(controller2)) {
|
|
2501
2554
|
await ensureComputer(directory, cliPath, {}, onProgress, { ...options, waitForRoutes: false });
|
|
2502
2555
|
}
|
|
2503
|
-
const { changeComputerConnection } = await import('./connection-change-
|
|
2556
|
+
const { changeComputerConnection } = await import('./connection-change-7ZV6O75Q.js');
|
|
2504
2557
|
await changeComputerConnection(directory, Object.fromEntries(changed.map((key) => [key, patch[key]])), { signal: options.signal, onProgress });
|
|
2505
2558
|
return computerClient(directory);
|
|
2506
2559
|
}
|
|
@@ -2541,7 +2594,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
|
|
|
2541
2594
|
let controller = await readJSON(path4.join(directory, "computer-controller.json"));
|
|
2542
2595
|
if (existing && controller && !compatible(controller) && await processStateAlive(controller)) {
|
|
2543
2596
|
onProgress?.("Refreshing the background connection service\u2026");
|
|
2544
|
-
const { handoffController } = await import('./controller-handoff-
|
|
2597
|
+
const { handoffController } = await import('./controller-handoff-CJKXUFQI.js');
|
|
2545
2598
|
await handoffController(directory, controller, config, await existing.computer.info());
|
|
2546
2599
|
controller = void 0;
|
|
2547
2600
|
}
|
|
@@ -2575,7 +2628,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
|
|
|
2575
2628
|
}
|
|
2576
2629
|
}
|
|
2577
2630
|
async function superviseComputer(directory) {
|
|
2578
|
-
const controller = await import('./controller-
|
|
2631
|
+
const controller = await import('./controller-FBMGMSLM.js');
|
|
2579
2632
|
await controller.superviseComputer(directory);
|
|
2580
2633
|
}
|
|
2581
2634
|
async function stopComputer(directory, force = false) {
|
|
@@ -2599,6 +2652,6 @@ async function stopComputer(directory, force = false) {
|
|
|
2599
2652
|
throw new Error("Mindwire is still stopping. Check computer.log.");
|
|
2600
2653
|
}
|
|
2601
2654
|
|
|
2602
|
-
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 };
|
|
2603
|
-
//# sourceMappingURL=chunk-
|
|
2604
|
-
//# sourceMappingURL=chunk-
|
|
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
|