mindwire 0.1.19 → 0.1.22

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/dist/index.cjs CHANGED
@@ -1,61 +1,136 @@
1
1
  'use strict';
2
2
 
3
3
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+
4
14
  // src/errors.ts
5
- var MindwireError = class extends Error {
6
- constructor(message, options) {
7
- super(message, options);
8
- this.name = "MindwireError";
15
+ exports.MindwireError = void 0; exports.ApiError = void 0; exports.RunFailedError = void 0; exports.TimeoutError = void 0;
16
+ var init_errors = __esm({
17
+ "src/errors.ts"() {
18
+ exports.MindwireError = class extends Error {
19
+ constructor(message, options) {
20
+ super(message, options);
21
+ this.name = "MindwireError";
22
+ }
23
+ };
24
+ exports.ApiError = class _ApiError extends exports.MindwireError {
25
+ status;
26
+ url;
27
+ method;
28
+ body;
29
+ constructor(args) {
30
+ super(_ApiError.messageFor(args));
31
+ this.name = "ApiError";
32
+ this.status = args.status;
33
+ this.url = args.url;
34
+ this.method = args.method;
35
+ this.body = args.body;
36
+ }
37
+ static messageFor({
38
+ status,
39
+ method,
40
+ url,
41
+ body
42
+ }) {
43
+ const detail = body && typeof body === "object" && "error" in body && typeof body.error === "string" ? body.error : typeof body === "string" && body.trim() !== "" ? body.trim() : "";
44
+ const base = `${method} ${url} failed with ${status}`;
45
+ return detail ? `${base}: ${detail}` : base;
46
+ }
47
+ };
48
+ exports.RunFailedError = class extends exports.MindwireError {
49
+ status;
50
+ runId;
51
+ constructor(runId, status, detail) {
52
+ super(detail ? `run ${runId} ${status}: ${detail}` : `run ${runId} ${status}`);
53
+ this.name = "RunFailedError";
54
+ this.runId = runId;
55
+ this.status = status;
56
+ }
57
+ };
58
+ exports.TimeoutError = class extends exports.MindwireError {
59
+ method;
60
+ path;
61
+ timeoutMs;
62
+ constructor(method, path, timeoutMs) {
63
+ super(`mindwire: ${method} ${path} timed out after ${timeoutMs}ms`);
64
+ this.name = "TimeoutError";
65
+ this.method = method;
66
+ this.path = path;
67
+ this.timeoutMs = timeoutMs;
68
+ }
69
+ };
9
70
  }
10
- };
11
- var ApiError = class _ApiError extends MindwireError {
12
- status;
13
- url;
14
- method;
15
- body;
16
- constructor(args) {
17
- super(_ApiError.messageFor(args));
18
- this.name = "ApiError";
19
- this.status = args.status;
20
- this.url = args.url;
21
- this.method = args.method;
22
- this.body = args.body;
23
- }
24
- static messageFor({
25
- status,
26
- method,
27
- url,
28
- body
29
- }) {
30
- const detail = body && typeof body === "object" && "error" in body && typeof body.error === "string" ? body.error : typeof body === "string" && body.trim() !== "" ? body.trim() : "";
31
- const base = `${method} ${url} failed with ${status}`;
32
- return detail ? `${base}: ${detail}` : base;
71
+ });
72
+
73
+ // src/binary-cache.ts
74
+ var binary_cache_exports = {};
75
+ __export(binary_cache_exports, {
76
+ binaryCacheDirectory: () => binaryCacheDirectory,
77
+ cacheExecutable: () => cacheExecutable,
78
+ cachedExecutable: () => cachedExecutable,
79
+ executableChecksum: () => executableChecksum,
80
+ verifyReleaseBytes: () => verifyReleaseBytes
81
+ });
82
+ async function binaryCacheDirectory(platform = process.platform) {
83
+ const path = await import('path');
84
+ const { homedir } = await import('os');
85
+ const homeDirectory = homedir();
86
+ return platform === "darwin" ? path.join(homeDirectory, "Library", "Caches", "mindwire") : platform === "win32" ? path.join(process.env.LOCALAPPDATA ?? homeDirectory, "mindwire", "Cache") : path.join(process.env.XDG_CACHE_HOME ?? path.join(homeDirectory, ".cache"), "mindwire");
87
+ }
88
+ async function executableChecksum(bytes) {
89
+ const { createHash } = await import('crypto');
90
+ return createHash("sha256").update(bytes).digest("hex");
91
+ }
92
+ async function verifyReleaseBytes(bytes, expected, name) {
93
+ if (!/^[a-f0-9]{64}$/i.test(expected) || await executableChecksum(bytes) !== expected.toLowerCase()) {
94
+ throw new exports.MindwireError(`mindwire: checksum verification failed for ${name}`);
33
95
  }
34
- };
35
- var RunFailedError = class extends MindwireError {
36
- status;
37
- runId;
38
- constructor(runId, status, detail) {
39
- super(detail ? `run ${runId} ${status}: ${detail}` : `run ${runId} ${status}`);
40
- this.name = "RunFailedError";
41
- this.runId = runId;
42
- this.status = status;
96
+ }
97
+ async function cachedExecutable(bin) {
98
+ const fs = await import('fs/promises');
99
+ try {
100
+ const [bytes, checksum] = await Promise.all([fs.readFile(bin), fs.readFile(`${bin}.sha256`, "utf8")]);
101
+ await verifyReleaseBytes(bytes, checksum.trim(), bin);
102
+ return bin;
103
+ } catch {
104
+ return void 0;
43
105
  }
44
- };
45
- var TimeoutError = class extends MindwireError {
46
- method;
47
- path;
48
- timeoutMs;
49
- constructor(method, path, timeoutMs) {
50
- super(`mindwire: ${method} ${path} timed out after ${timeoutMs}ms`);
51
- this.name = "TimeoutError";
52
- this.method = method;
53
- this.path = path;
54
- this.timeoutMs = timeoutMs;
106
+ }
107
+ async function cacheExecutable(bin, bytes, expected) {
108
+ await verifyReleaseBytes(bytes, expected, bin);
109
+ const fs = await import('fs/promises');
110
+ const { dirname } = await import('path');
111
+ const { randomUUID } = await import('crypto');
112
+ await fs.mkdir(dirname(bin), { recursive: true, mode: 448 });
113
+ const temp = `${bin}.${randomUUID()}.tmp`;
114
+ try {
115
+ await fs.writeFile(temp, bytes, { mode: 493, flag: "wx" });
116
+ await fs.writeFile(`${temp}.sha256`, `${expected.toLowerCase()}
117
+ `, { mode: 384, flag: "wx" });
118
+ await fs.rename(temp, bin);
119
+ await fs.rename(`${temp}.sha256`, `${bin}.sha256`);
120
+ return bin;
121
+ } finally {
122
+ await fs.rm(temp, { force: true });
123
+ await fs.rm(`${temp}.sha256`, { force: true });
55
124
  }
56
- };
125
+ }
126
+ var init_binary_cache = __esm({
127
+ "src/binary-cache.ts"() {
128
+ init_errors();
129
+ }
130
+ });
57
131
 
58
132
  // src/http.ts
133
+ init_errors();
59
134
  var DEFAULT_TIMEOUT_MS = 12e4;
60
135
  function isAbortError(e) {
61
136
  return typeof e === "object" && e !== null && e.name === "AbortError";
@@ -70,7 +145,7 @@ var Http = class {
70
145
  constructor(opts) {
71
146
  const f = opts.fetch ?? globalThis.fetch;
72
147
  if (!f) {
73
- throw new MindwireError(
148
+ throw new exports.MindwireError(
74
149
  "mindwire: no global fetch found \u2014 pass a `fetch` implementation in the client options"
75
150
  );
76
151
  }
@@ -93,7 +168,7 @@ var Http = class {
93
168
  };
94
169
  };
95
170
  } else {
96
- throw new MindwireError("mindwire: Http requires a baseUrl or a resolveBase");
171
+ throw new exports.MindwireError("mindwire: Http requires a baseUrl or a resolveBase");
97
172
  }
98
173
  }
99
174
  /**
@@ -107,7 +182,7 @@ var Http = class {
107
182
  } catch (e) {
108
183
  const aborted = init.signal?.aborted ?? false;
109
184
  if (aborted || isAbortError(e)) throw e;
110
- throw new MindwireError(`mindwire: ${method} ${path} \u2014 network request failed`, { cause: e });
185
+ throw new exports.MindwireError(`mindwire: ${method} ${path} \u2014 network request failed`, { cause: e });
111
186
  }
112
187
  }
113
188
  /**
@@ -134,7 +209,7 @@ var Http = class {
134
209
  try {
135
210
  return await this.fetchOnce(f, url, { ...init, signal: ctrl.signal }, method, path);
136
211
  } catch (e) {
137
- if (timedOut) throw new TimeoutError(method, path, this.timeoutMs);
212
+ if (timedOut) throw new exports.TimeoutError(method, path, this.timeoutMs);
138
213
  if (userSignal?.aborted) throw userSignal.reason ?? e;
139
214
  throw e;
140
215
  } finally {
@@ -215,7 +290,7 @@ var Http = class {
215
290
  try {
216
291
  return JSON.parse(text);
217
292
  } catch (e) {
218
- throw new MindwireError(`mindwire: ${method} ${path} returned a non-JSON body`, { cause: e });
293
+ throw new exports.MindwireError(`mindwire: ${method} ${path} returned a non-JSON body`, { cause: e });
219
294
  }
220
295
  }
221
296
  /** Open a streaming response (SSE). Caller owns the body. */
@@ -229,7 +304,8 @@ var Http = class {
229
304
  url,
230
305
  {
231
306
  method,
232
- headers: this.headers(await this.authToken(base, force), extra),
307
+ headers: this.headers(await this.authToken(base, force), extra, init.body !== void 0),
308
+ ...init.body !== void 0 ? { body: JSON.stringify(init.body) } : {},
233
309
  ...init.signal ? { signal: init.signal } : {}
234
310
  },
235
311
  method,
@@ -239,7 +315,7 @@ var Http = class {
239
315
  if (res.status === 401 && base.getToken) res = await send(true);
240
316
  if (!res.ok) throw await this.toApiError(method, res);
241
317
  if (!res.body)
242
- throw new MindwireError(`mindwire: ${method} ${path} returned no response body to stream`);
318
+ throw new exports.MindwireError(`mindwire: ${method} ${path} returned no response body to stream`);
243
319
  return res;
244
320
  }
245
321
  async toApiError(method, res) {
@@ -253,7 +329,7 @@ var Http = class {
253
329
  }
254
330
  } catch {
255
331
  }
256
- return new ApiError({ status: res.status, url: res.url, method, body });
332
+ return new exports.ApiError({ status: res.status, url: res.url, method, body });
257
333
  }
258
334
  };
259
335
 
@@ -321,6 +397,7 @@ function parseEvent(block) {
321
397
  }
322
398
 
323
399
  // src/run.ts
400
+ init_errors();
324
401
  var TERMINAL = /* @__PURE__ */ new Set(["done", "error", "cancelled"]);
325
402
  var Run = class _Run {
326
403
  data;
@@ -464,10 +541,10 @@ var Run = class _Run {
464
541
  if (opts.throwOnError !== false) {
465
542
  if (TERMINAL.has(run.status)) {
466
543
  if (run.status !== "done") {
467
- throw new RunFailedError(run.id, run.status, run.error ?? streamError);
544
+ throw new exports.RunFailedError(run.id, run.status, run.error ?? streamError);
468
545
  }
469
546
  } else {
470
- throw new RunFailedError(
547
+ throw new exports.RunFailedError(
471
548
  run.id,
472
549
  run.status,
473
550
  streamError ?? "event stream ended before the run reached a terminal state"
@@ -590,6 +667,15 @@ var GitAccessApi = class {
590
667
  this.mw = mw;
591
668
  }
592
669
  mw;
670
+ /** Reads attribution independently of GitHub authentication. Requires gitIdentityVersion >= 1. */
671
+ identity(context = {}) {
672
+ return this.mw.http.request("GET", "/workspace/git/identity", { query: context });
673
+ }
674
+ /** Saves settings only; never stages or commits. all_workspaces installs this
675
+ * workspace's copy of a client-managed default; the client handles fan-out. */
676
+ setIdentity(update, context = {}) {
677
+ return this.mw.http.request("PUT", "/workspace/git/identity", { query: context, body: update });
678
+ }
593
679
  state() {
594
680
  return this.mw.http.request("GET", "/workspace/git");
595
681
  }
@@ -734,13 +820,132 @@ var ServiceApi = class {
734
820
  }
735
821
  };
736
822
 
823
+ // src/execution.ts
824
+ var ExecutionApi = class {
825
+ constructor(client) {
826
+ this.client = client;
827
+ this.terminals = new TerminalsApi(client);
828
+ }
829
+ client;
830
+ terminals;
831
+ host() {
832
+ return this.client.http.request("GET", "/workspace/host");
833
+ }
834
+ resources() {
835
+ return this.client.http.request("GET", "/workspace/resources");
836
+ }
837
+ files(path = "", query) {
838
+ return this.client.http.request("GET", "/workspace/files", { query: { path, query } });
839
+ }
840
+ read(path) {
841
+ return this.client.http.request("GET", "/workspace/file", { query: { path } });
842
+ }
843
+ write(path, content) {
844
+ return this.client.http.request("PUT", "/workspace/file", { body: { path, content } });
845
+ }
846
+ remove(path) {
847
+ return this.client.http.request("DELETE", "/workspace/file", { query: { path } });
848
+ }
849
+ exec(command, signal) {
850
+ return this.client.http.request("POST", "/workspace/exec", { body: command, signal });
851
+ }
852
+ /** Output data is base64, preserving partial UTF-8 chunks. Cancelling stops this command. */
853
+ async *stream(command, signal) {
854
+ const response = await this.client.http.open("POST", "/workspace/exec/stream", { body: command, signal });
855
+ yield* readSSE(response.body, signal);
856
+ }
857
+ };
858
+ var TerminalsApi = class {
859
+ constructor(client) {
860
+ this.client = client;
861
+ }
862
+ client;
863
+ list(directory) {
864
+ return this.client.http.request("GET", "/workspace/terminals", { query: { directory } });
865
+ }
866
+ open(request) {
867
+ return this.client.http.request("POST", "/workspace/terminals", { body: request });
868
+ }
869
+ get(id) {
870
+ return this.client.http.request("GET", this.path(id));
871
+ }
872
+ close(id) {
873
+ return this.client.http.request("DELETE", this.path(id));
874
+ }
875
+ input(id, input) {
876
+ return this.client.http.request("POST", `${this.path(id)}/input`, { body: input });
877
+ }
878
+ resize(id, columns, rows) {
879
+ return this.client.http.request("PUT", `${this.path(id)}/size`, { body: { columns, rows } });
880
+ }
881
+ /** Detaching only closes the subscription. Resume from the last sequence; reset replaces the screen. */
882
+ async *events(id, after = 0, signal) {
883
+ const response = await this.client.http.open("GET", `${this.path(id)}/events`, { query: { after }, signal });
884
+ yield* readSSE(response.body, signal);
885
+ }
886
+ path(id) {
887
+ return `/workspace/terminals/${encodeURIComponent(id)}`;
888
+ }
889
+ };
890
+
891
+ // src/computer.ts
892
+ var ComputerApi = class {
893
+ constructor(client) {
894
+ this.client = client;
895
+ }
896
+ client;
897
+ info() {
898
+ return this.client.http.request("GET", "/computer");
899
+ }
900
+ setRoutes(routes) {
901
+ return this.client.http.request("PUT", "/computer/routes", { body: { routes } });
902
+ }
903
+ updateStatus() {
904
+ return this.client.http.request("GET", "/computer/update");
905
+ }
906
+ requestUpdate(version) {
907
+ return this.client.http.request("POST", "/computer/update", { body: { version } });
908
+ }
909
+ invite(routes) {
910
+ return this.client.http.request("POST", "/computer/pairings", { body: { routes } });
911
+ }
912
+ pairing(id) {
913
+ return this.client.http.request("GET", `/computer/pairings/${encodeURIComponent(id)}`);
914
+ }
915
+ completePairing(id, requestId) {
916
+ return this.client.http.request("POST", `/computer/pairings/${encodeURIComponent(id)}/complete`, { body: { requestId } });
917
+ }
918
+ decide(id, requestId, approve) {
919
+ return this.client.http.request("POST", `/computer/pairings/${encodeURIComponent(id)}/decision`, { body: { requestId, approve } });
920
+ }
921
+ devices() {
922
+ return this.client.http.request("GET", "/computer/devices");
923
+ }
924
+ revoke(id) {
925
+ return this.client.http.request("DELETE", `/computer/devices/${encodeURIComponent(id)}`);
926
+ }
927
+ };
928
+ function computerPairingURI(invitation) {
929
+ const bytes = new TextEncoder().encode(JSON.stringify(invitation));
930
+ let binary = "";
931
+ for (const byte of bytes) binary += String.fromCharCode(byte);
932
+ const encoded = btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
933
+ return `mindwire://pair?v=1#${encoded}`;
934
+ }
935
+
936
+ // src/embedded.ts
937
+ init_errors();
938
+
939
+ // src/daemon-binary.ts
940
+ init_errors();
941
+
737
942
  // src/version.ts
738
- var SDK_VERSION = "0.1.19" ;
943
+ var SDK_VERSION = "0.1.22" ;
739
944
 
740
945
  // src/daemon-binary.ts
741
946
  function supported(platform, arch) {
742
947
  if (!["darwin", "linux", "win32"].includes(platform) || !["x64", "arm64"].includes(arch)) {
743
- throw new MindwireError(`mindwire: no daemon release for ${platform}-${arch}`);
948
+ throw new exports.MindwireError(`mindwire: no daemon release for ${platform}-${arch}`);
744
949
  }
745
950
  }
746
951
  function assetName(version, platform, arch) {
@@ -762,27 +967,19 @@ async function ensureDaemonBinary(opts = {}) {
762
967
  const daemonArch = arch;
763
968
  const version = opts.version ?? SDK_VERSION;
764
969
  if (!/^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
765
- throw new MindwireError(`mindwire: cannot download daemon for non-release SDK version ${version}`);
970
+ throw new exports.MindwireError(`mindwire: cannot download daemon for non-release SDK version ${version}`);
766
971
  }
767
- const fs = await import('fs/promises');
768
972
  const path = await import('path');
769
- const os = await import('os');
770
- const crypto = await import('crypto');
771
- const home = os.homedir();
772
- const defaultCache = daemonPlatform === "darwin" ? path.join(home, "Library", "Caches", "mindwire") : daemonPlatform === "win32" ? path.join(proc.process?.env?.LOCALAPPDATA ?? home, "mindwire", "Cache") : path.join(proc.process?.env?.XDG_CACHE_HOME ?? path.join(home, ".cache"), "mindwire");
773
- const dir = path.join(opts.cacheDir ?? defaultCache, version, `${daemonPlatform}-${daemonArch}`);
973
+ const { binaryCacheDirectory: binaryCacheDirectory2, cachedExecutable: cachedExecutable2, cacheExecutable: cacheExecutable2 } = await Promise.resolve().then(() => (init_binary_cache(), binary_cache_exports));
974
+ const dir = path.join(opts.cacheDir ?? await binaryCacheDirectory2(daemonPlatform), version, `${daemonPlatform}-${daemonArch}`);
774
975
  const asset = assetName(version, daemonPlatform, daemonArch);
775
976
  const bin = path.join(dir, asset);
776
- const shaFile = `${bin}.sha256`;
777
- try {
778
- const [bytes2, expected2] = await Promise.all([fs.readFile(bin), fs.readFile(shaFile, "utf8")]);
779
- if (crypto.createHash("sha256").update(bytes2).digest("hex") === expected2.trim()) return bin;
780
- } catch {
781
- }
977
+ const cached = await cachedExecutable2(bin);
978
+ if (cached) return cached;
782
979
  const base = (opts.releaseBaseUrl ?? proc.process?.env?.MINDWIRE_RELEASE_BASE_URL ?? "https://github.com/oblien/mindwire/releases/download").replace(/\/$/, "");
783
980
  const release = `${base}/v${version}`;
784
981
  const request = opts.fetch ?? globalThis.fetch;
785
- if (!request) throw new MindwireError("mindwire: fetch is unavailable; set daemonBin or MINDWIRE_DAEMON");
982
+ if (!request) throw new exports.MindwireError("mindwire: fetch is unavailable; set daemonBin or MINDWIRE_DAEMON");
786
983
  const [checksums, binary] = await Promise.all([request(`${release}/checksums.txt`), request(`${release}/${asset}`)]);
787
984
  if (!checksums.ok || !binary.ok) {
788
985
  if (!opts.releaseBaseUrl && !proc.process?.env?.MINDWIRE_RELEASE_BASE_URL) {
@@ -795,22 +992,12 @@ async function ensureDaemonBinary(opts = {}) {
795
992
  }
796
993
  }
797
994
  }
798
- throw new MindwireError(`mindwire: failed to download daemon v${version} for ${daemonPlatform}-${daemonArch}`);
995
+ throw new exports.MindwireError(`mindwire: failed to download daemon v${version} for ${daemonPlatform}-${daemonArch}`);
799
996
  }
800
997
  const expected = checksumFor(await checksums.text(), asset);
801
- if (!expected) throw new MindwireError(`mindwire: release v${version} has no checksum for ${asset}`);
998
+ if (!expected) throw new exports.MindwireError(`mindwire: release v${version} has no checksum for ${asset}`);
802
999
  const bytes = new Uint8Array(await binary.arrayBuffer());
803
- const actual = crypto.createHash("sha256").update(bytes).digest("hex");
804
- if (actual !== expected) throw new MindwireError(`mindwire: checksum verification failed for ${asset}`);
805
- await fs.mkdir(dir, { recursive: true });
806
- const temp = `${bin}.${process.pid}.tmp`;
807
- await fs.writeFile(temp, bytes, { mode: 493 });
808
- await fs.writeFile(`${shaFile}.${process.pid}.tmp`, `${expected}
809
- `);
810
- await fs.rename(temp, bin);
811
- await fs.rename(`${shaFile}.${process.pid}.tmp`, shaFile);
812
- if (daemonPlatform !== "win32") await fs.chmod(bin, 493);
813
- return bin;
1000
+ return cacheExecutable2(bin, bytes, expected);
814
1001
  }
815
1002
 
816
1003
  // src/embedded.ts
@@ -839,7 +1026,7 @@ function isServerRuntime() {
839
1026
  }
840
1027
  async function spawnDaemon(opts) {
841
1028
  if (!isServerRuntime()) {
842
- throw new MindwireError(
1029
+ throw new exports.MindwireError(
843
1030
  "MindWire embedded mode needs a server runtime (Node/Bun/Deno). In the browser or an edge runtime, pass { baseUrl } to connect to a running daemon."
844
1031
  );
845
1032
  }
@@ -935,7 +1122,7 @@ async function waitHealthy(baseUrl, token, getError, resolved, timeoutMs = 15e3)
935
1122
  while (Date.now() < deadline) {
936
1123
  const err = getError();
937
1124
  if (err) {
938
- throw new MindwireError(daemonStartError(resolved, err), { cause: err });
1125
+ throw new exports.MindwireError(daemonStartError(resolved, err), { cause: err });
939
1126
  }
940
1127
  try {
941
1128
  const res = await fetch(`${baseUrl}/healthz`, { headers: { Authorization: `Bearer ${token}` } });
@@ -944,7 +1131,7 @@ async function waitHealthy(baseUrl, token, getError, resolved, timeoutMs = 15e3)
944
1131
  }
945
1132
  await new Promise((r) => setTimeout(r, 150));
946
1133
  }
947
- throw new MindwireError("mindwire embedded daemon did not become healthy in time.");
1134
+ throw new exports.MindwireError("mindwire embedded daemon did not become healthy in time.");
948
1135
  }
949
1136
 
950
1137
  // src/target/index.ts
@@ -997,6 +1184,8 @@ var Mindwire = class _Mindwire {
997
1184
  workspace;
998
1185
  surfaces;
999
1186
  service;
1187
+ execution;
1188
+ computer;
1000
1189
  http;
1001
1190
  /** The default agent type applied to agent-scoped calls, if set. */
1002
1191
  defaultAgent;
@@ -1033,6 +1222,8 @@ var Mindwire = class _Mindwire {
1033
1222
  this.workspace = new WorkspaceApi(this);
1034
1223
  this.surfaces = new SurfacesApi(this);
1035
1224
  this.service = new ServiceApi(this);
1225
+ this.execution = new ExecutionApi(this);
1226
+ this.computer = new ComputerApi(this);
1036
1227
  this.auth = new AuthApi(this);
1037
1228
  this.prompts = new PromptsApi(this);
1038
1229
  this.mcp = new McpApi(this);
@@ -1056,6 +1247,8 @@ var Mindwire = class _Mindwire {
1056
1247
  clone.workspace = new WorkspaceApi(clone);
1057
1248
  clone.surfaces = new SurfacesApi(clone);
1058
1249
  clone.service = new ServiceApi(clone);
1250
+ clone.execution = new ExecutionApi(clone);
1251
+ clone.computer = new ComputerApi(clone);
1059
1252
  clone.auth = new AuthApi(clone);
1060
1253
  clone.prompts = new PromptsApi(clone);
1061
1254
  clone.mcp = new McpApi(clone);
@@ -1588,7 +1781,11 @@ var NotifyApi = class {
1588
1781
  }
1589
1782
  };
1590
1783
 
1784
+ // src/target/ssh.ts
1785
+ init_errors();
1786
+
1591
1787
  // src/target/host.ts
1788
+ init_errors();
1592
1789
  function versionAtLeast(actual, desired) {
1593
1790
  if (actual === desired) return true;
1594
1791
  if (!actual || !/^\d+\.\d+\.\d+$/.test(actual) || !/^\d+\.\d+\.\d+$/.test(desired)) return false;
@@ -1620,7 +1817,7 @@ async function daemonDirectory(host) {
1620
1817
  const result = await host.exec(["sh", "-lc", 'printf "<<MW_HOME>>%s<<MW_HOME>>" "$HOME"'], { timeoutSeconds: 15 });
1621
1818
  const runtimeHome = result.stdout?.match(/<<MW_HOME>>([\s\S]*?)<<MW_HOME>>/)?.[1];
1622
1819
  if (!runtimeHome?.startsWith("/") || runtimeHome.length > 4096 || /[\x00-\x1f\x7f]/.test(runtimeHome)) {
1623
- throw new MindwireError("mindwire: cannot resolve the runtime user's home directory");
1820
+ throw new exports.MindwireError("mindwire: cannot resolve the runtime user's home directory");
1624
1821
  }
1625
1822
  return runtimeHome.replace(/\/+$/, "") + "/.mindwire";
1626
1823
  }
@@ -1652,7 +1849,7 @@ async function ensureDaemon(host, cfg) {
1652
1849
  return token;
1653
1850
  }
1654
1851
  if ((health.serviceUpdateVersion ?? 0) < 1) {
1655
- if (cfg.forceDeploy) throw new MindwireError("This legacy service cannot reserve an idle update. Upgrade it explicitly or stop it after its work finishes before deploying.");
1852
+ if (cfg.forceDeploy) throw new exports.MindwireError("This legacy service cannot reserve an idle update. Upgrade it explicitly or stop it after its work finishes before deploying.");
1656
1853
  emit2({ phase: "skip", message: "automatic update deferred: upgrade this legacy service explicitly to enable idle updates", version: health.version });
1657
1854
  return token;
1658
1855
  }
@@ -1691,7 +1888,7 @@ async function deploy(host, cfg, emit2, token, directory, requireLease) {
1691
1888
  acquire = `mv -f ${shellQuote(stagedUpload)} ${BIN_NEW}`;
1692
1889
  } else {
1693
1890
  if (!/^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/.test(desired)) {
1694
- throw new MindwireError(`mindwire: cannot download daemon for non-release SDK version ${desired}`);
1891
+ throw new exports.MindwireError(`mindwire: cannot download daemon for non-release SDK version ${desired}`);
1695
1892
  }
1696
1893
  const asset = `mindwired-v${desired}-${platform}-${arch}`;
1697
1894
  const release = `https://github.com/oblien/mindwire/releases/download/v${desired}`;
@@ -1799,12 +1996,12 @@ async function deploy(host, cfg, emit2, token, directory, requireLease) {
1799
1996
  const res = await host.exec(["bash", "-lc", script], { timeoutSeconds: 420 });
1800
1997
  const out = res.stdout ?? "";
1801
1998
  if (out.includes("MINDWIRE_UPDATE_DEFERRED")) {
1802
- if (cfg.forceDeploy) throw new MindwireError("The workspace is busy. Wait for its operations to finish before deploying the service.");
1999
+ if (cfg.forceDeploy) throw new exports.MindwireError("The workspace is busy. Wait for its operations to finish before deploying the service.");
1803
2000
  emit2({ phase: "skip", message: "service update deferred while workspace operations are running" });
1804
2001
  return;
1805
2002
  }
1806
2003
  if (!out.includes("MINDWIRE_READY")) {
1807
- throw new MindwireError(
2004
+ throw new exports.MindwireError(
1808
2005
  "mindwire: the in-sandbox daemon did not become healthy after deploy.\n" + (out || res.stderr || res.error || "(no output)").trim()
1809
2006
  );
1810
2007
  }
@@ -1832,7 +2029,7 @@ async function probePlatform(host) {
1832
2029
  const rawArch = ((res.stdout ?? "").match(/<<ARCH:([^>]*)>>/)?.[1] ?? "").trim();
1833
2030
  const arch = rawArch === "aarch64" || rawArch === "arm64" ? "arm64" : rawArch === "x86_64" || rawArch === "amd64" ? "amd64" : void 0;
1834
2031
  if (os !== "linux" && os !== "darwin" || !arch) {
1835
- throw new MindwireError(`mindwire: unsupported workspace platform ${os || "unknown"}/${rawArch || "unknown"}; expected Linux or macOS on amd64 or arm64`);
2032
+ throw new exports.MindwireError(`mindwire: unsupported workspace platform ${os || "unknown"}/${rawArch || "unknown"}; expected Linux or macOS on amd64 or arm64`);
1836
2033
  }
1837
2034
  return { platform: os, arch };
1838
2035
  }
@@ -1848,7 +2045,7 @@ async function waitHostReady(host, timeoutMs = 6e4) {
1848
2045
  }
1849
2046
  await sleep(1e3);
1850
2047
  }
1851
- throw new MindwireError(
2048
+ throw new exports.MindwireError(
1852
2049
  "mindwire: the sandbox runtime did not become ready in time.",
1853
2050
  lastErr ? { cause: lastErr } : void 0
1854
2051
  );
@@ -1861,7 +2058,7 @@ async function resolveHostDaemon(explicit, platform, arch) {
1861
2058
  if (explicit) {
1862
2059
  const resolved = explicit.replaceAll("{os}", platform).replaceAll("{arch}", arch);
1863
2060
  if (!fs.existsSync(resolved)) {
1864
- throw new MindwireError(`mindwire: sandbox daemonBin not found at ${resolved}`);
2061
+ throw new exports.MindwireError(`mindwire: sandbox daemonBin not found at ${resolved}`);
1865
2062
  }
1866
2063
  return resolved;
1867
2064
  }
@@ -1882,6 +2079,7 @@ function formatMiB(bytes) {
1882
2079
  }
1883
2080
 
1884
2081
  // src/target/container.ts
2082
+ init_errors();
1885
2083
  async function provisionContainer(host, cfg, onLog) {
1886
2084
  const target = cfg.target ?? "container";
1887
2085
  const emit2 = (e) => {
@@ -1944,7 +2142,7 @@ async function ensureDockerReady(host, install, emit2) {
1944
2142
  return;
1945
2143
  }
1946
2144
  if (state.status === "denied") {
1947
- throw new MindwireError(
2145
+ throw new exports.MindwireError(
1948
2146
  "mindwire: connected to the host, but this user can't reach the Docker daemon socket (permission denied). Connect as root, or add the SSH user to the `docker` group."
1949
2147
  );
1950
2148
  }
@@ -1956,10 +2154,10 @@ async function ensureDockerReady(host, install, emit2) {
1956
2154
  emit2({ phase: "install", message: `docker started (v${state.version ?? "?"})`, version: state.version });
1957
2155
  return;
1958
2156
  }
1959
- throw new MindwireError("mindwire: Docker is installed on the host but could not be started.");
2157
+ throw new exports.MindwireError("mindwire: Docker is installed on the host but could not be started.");
1960
2158
  }
1961
2159
  if (install !== "ifMissing") {
1962
- throw new MindwireError(
2160
+ throw new exports.MindwireError(
1963
2161
  'mindwire: Docker is not installed on the remote host, and mindwire won\'t install system packages unless you opt in. Pass docker: { install: "ifMissing" } to have it run the official get.docker.com script (`curl -fsSL https://get.docker.com | sh`) and enable the service \u2014 or install Docker on the host yourself.'
1964
2162
  );
1965
2163
  }
@@ -1968,7 +2166,7 @@ async function ensureDockerReady(host, install, emit2) {
1968
2166
  await startDocker(host);
1969
2167
  state = await detectDocker(host);
1970
2168
  if (state.status !== "running") {
1971
- throw new MindwireError(
2169
+ throw new exports.MindwireError(
1972
2170
  "mindwire: ran the get.docker.com install script, but the Docker daemon did not come up."
1973
2171
  );
1974
2172
  }
@@ -1995,7 +2193,7 @@ async function installDocker(host) {
1995
2193
  timeoutSeconds: 600
1996
2194
  });
1997
2195
  if ((res.exitCode ?? 0) !== 0) {
1998
- throw new MindwireError(
2196
+ throw new exports.MindwireError(
1999
2197
  "mindwire: the Docker install script (get.docker.com) failed.\n" + (res.stderr || res.stdout || "(no output)").trim()
2000
2198
  );
2001
2199
  }
@@ -2018,7 +2216,7 @@ async function runContainer(host, cfg, emit2) {
2018
2216
  return { containerId: cfg.container, hostPort: hostPort2, created: false };
2019
2217
  }
2020
2218
  if (!cfg.image) {
2021
- throw new MindwireError(
2219
+ throw new exports.MindwireError(
2022
2220
  "mindwire: running the daemon in a container needs an image (docker.image) to create one, or an existing container (docker.container) to attach to."
2023
2221
  );
2024
2222
  }
@@ -2030,7 +2228,7 @@ async function runContainer(host, cfg, emit2) {
2030
2228
  const res = await host.exec(runArgs, { timeoutSeconds: 120 });
2031
2229
  const containerId = (res.stdout ?? "").trim().split(/\s+/).pop() ?? "";
2032
2230
  if (!containerId || (res.exitCode ?? 0) !== 0) {
2033
- throw new MindwireError(
2231
+ throw new exports.MindwireError(
2034
2232
  "mindwire: `docker run` did not start a container.\n" + (res.stderr || res.stdout || "(no output)").trim()
2035
2233
  );
2036
2234
  }
@@ -2046,7 +2244,7 @@ async function resolveHostPort(host, containerId, port) {
2046
2244
  const line = (res.stdout ?? "").split("\n").map((s) => s.trim()).find(Boolean);
2047
2245
  const hostPort = line ? Number.parseInt(line.match(/:(\d+)\s*$/)?.[1] ?? "", 10) : NaN;
2048
2246
  if (!Number.isFinite(hostPort) || hostPort <= 0) {
2049
- throw new MindwireError(
2247
+ throw new exports.MindwireError(
2050
2248
  `mindwire: could not resolve the published host port for ${port}/tcp on container ${containerId.slice(0, 12)}. ` + cfgHint(res) + `docker port output: ${JSON.stringify((res.stdout ?? "").trim())}`
2051
2249
  );
2052
2250
  }
@@ -2224,7 +2422,7 @@ async function openConnection(mod, opts) {
2224
2422
  if (settled) return;
2225
2423
  settled = true;
2226
2424
  reject(
2227
- new MindwireError(
2425
+ new exports.MindwireError(
2228
2426
  `mindwire: SSH connection to ${opts.username}@${opts.host}:${opts.port ?? 22} failed: ${err.message}`,
2229
2427
  { cause: err }
2230
2428
  )
@@ -2259,7 +2457,7 @@ async function createTunnel(net, client, daemonPort) {
2259
2457
  client.forwardOut("127.0.0.1", 0, "127.0.0.1", daemonPort, (err, stream) => {
2260
2458
  if (err) {
2261
2459
  reject(
2262
- new MindwireError(
2460
+ new exports.MindwireError(
2263
2461
  `mindwire: the SSH server refused a port-forward to 127.0.0.1:${daemonPort} (direct-tcpip). Enable \`AllowTcpForwarding yes\` in the remote sshd_config \u2014 mindwire tunnels the daemon's HTTP/SSE over the SSH connection.`,
2264
2462
  { cause: err }
2265
2463
  )
@@ -2323,7 +2521,7 @@ async function importSsh2() {
2323
2521
  );
2324
2522
  return mod.default && mod.default.Client ? mod.default : mod;
2325
2523
  } catch (err) {
2326
- throw new MindwireError(
2524
+ throw new exports.MindwireError(
2327
2525
  "mindwire: the SSH target needs the optional `ssh2` package. Install it (`npm i ssh2`). It's an optional peer dependency, so the core SDK stays dependency-free.",
2328
2526
  { cause: err }
2329
2527
  );
@@ -2335,6 +2533,7 @@ function env(key) {
2335
2533
  }
2336
2534
 
2337
2535
  // src/target/docker.ts
2536
+ init_errors();
2338
2537
  function docker(config = {}) {
2339
2538
  return { name: "docker", connect: (spec) => connectDocker(config, spec) };
2340
2539
  }
@@ -2416,7 +2615,7 @@ async function provisionDocker(docker2, config = {}, onLog) {
2416
2615
  const binding = info.NetworkSettings?.Ports?.[`${port}/tcp`];
2417
2616
  const hostPort = binding?.[0]?.HostPort;
2418
2617
  if (!hostPort) {
2419
- throw new MindwireError(
2618
+ throw new exports.MindwireError(
2420
2619
  `mindwire: the Docker container does not publish a host port for ${port}/tcp. ` + (created ? "This is unexpected for a container mindwire created." : "Attach to a container started with that port published (e.g. `-p 0:" + port + "`).")
2421
2620
  );
2422
2621
  }
@@ -2468,7 +2667,7 @@ async function ensureImage(docker2, image, policy, onLog) {
2468
2667
  } catch (error) {
2469
2668
  const detail = error instanceof Error ? error.message : String(error);
2470
2669
  emit2(`failed to pull runtime image ${image}`, detail);
2471
- throw new MindwireError(`mindwire: failed to pull Docker image ${image}: ${detail}`, { cause: error });
2670
+ throw new exports.MindwireError(`mindwire: failed to pull Docker image ${image}: ${detail}`, { cause: error });
2472
2671
  }
2473
2672
  }
2474
2673
  function tarSingleFile(name, data, mode) {
@@ -2502,7 +2701,7 @@ async function importDockerode() {
2502
2701
  );
2503
2702
  return mod.default ?? mod;
2504
2703
  } catch (err) {
2505
- throw new MindwireError(
2704
+ throw new exports.MindwireError(
2506
2705
  "mindwire: the Docker sandbox adapter needs the optional `dockerode` package. Install it (`npm i dockerode`). It's an optional peer dependency, so the core SDK stays dependency-free.",
2507
2706
  { cause: err }
2508
2707
  );
@@ -2510,6 +2709,7 @@ async function importDockerode() {
2510
2709
  }
2511
2710
 
2512
2711
  // src/target/oblien.ts
2712
+ init_errors();
2513
2713
  function oblien(config = {}) {
2514
2714
  return { name: "oblien", connect: (spec) => connectOblien(config, spec) };
2515
2715
  }
@@ -2546,7 +2746,7 @@ async function connectOblien(config, spec) {
2546
2746
  const clientId = config.clientId ?? env2("MINDWIRE_SANDBOX_CLIENT_ID") ?? env2("OBLIEN_CLIENT_ID");
2547
2747
  const clientSecret = config.clientSecret ?? env2("MINDWIRE_SANDBOX_CLIENT_SECRET") ?? env2("OBLIEN_CLIENT_SECRET");
2548
2748
  if (!clientId || !clientSecret) {
2549
- throw new MindwireError(
2749
+ throw new exports.MindwireError(
2550
2750
  "mindwire: the Oblien target needs credentials \u2014 pass oblien({ clientId, clientSecret }) or set MINDWIRE_SANDBOX_CLIENT_ID / MINDWIRE_SANDBOX_CLIENT_SECRET (OBLIEN_CLIENT_ID / OBLIEN_CLIENT_SECRET are also accepted)."
2551
2751
  );
2552
2752
  }
@@ -2622,7 +2822,7 @@ async function importOblien() {
2622
2822
  spec
2623
2823
  );
2624
2824
  } catch (err) {
2625
- throw new MindwireError(
2825
+ throw new exports.MindwireError(
2626
2826
  "mindwire: sandbox mode with the default (Oblien) adapter needs the optional `oblien` package. Install it (`npm i oblien`). It's an optional peer dependency, so the core SDK stays dependency-free.",
2627
2827
  { cause: err }
2628
2828
  );
@@ -2718,31 +2918,34 @@ function clearCatalogCache() {
2718
2918
  inflight = null;
2719
2919
  }
2720
2920
 
2721
- exports.ApiError = ApiError;
2921
+ // src/index.ts
2922
+ init_errors();
2923
+
2722
2924
  exports.AuthApi = AuthApi;
2925
+ exports.ComputerApi = ComputerApi;
2723
2926
  exports.ContainerHost = ContainerHost;
2927
+ exports.ExecutionApi = ExecutionApi;
2724
2928
  exports.GitAccessApi = GitAccessApi;
2725
2929
  exports.Http = Http;
2726
2930
  exports.MODELS_DEV_URL = MODELS_DEV_URL;
2727
2931
  exports.McpApi = McpApi;
2728
2932
  exports.Mindwire = Mindwire;
2729
- exports.MindwireError = MindwireError;
2730
2933
  exports.NotifyApi = NotifyApi;
2731
2934
  exports.ProjectOperationsApi = ProjectOperationsApi;
2732
2935
  exports.PromptsApi = PromptsApi;
2733
2936
  exports.ProvidersApi = ProvidersApi;
2734
2937
  exports.Run = Run;
2735
- exports.RunFailedError = RunFailedError;
2736
2938
  exports.SDK_VERSION = SDK_VERSION;
2737
2939
  exports.ServiceApi = ServiceApi;
2738
2940
  exports.SurfacesApi = SurfacesApi;
2739
- exports.TimeoutError = TimeoutError;
2941
+ exports.TerminalsApi = TerminalsApi;
2740
2942
  exports.WorkspaceApi = WorkspaceApi;
2741
2943
  exports.WorkspaceCollection = WorkspaceCollection;
2742
2944
  exports.catalogModels = catalogModels;
2743
2945
  exports.catalogProvider = catalogProvider;
2744
2946
  exports.catalogProviders = catalogProviders;
2745
2947
  exports.clearCatalogCache = clearCatalogCache;
2948
+ exports.computerPairingURI = computerPairingURI;
2746
2949
  exports.docker = docker;
2747
2950
  exports.ensureDaemon = ensureDaemon;
2748
2951
  exports.ensureDaemonBinary = ensureDaemonBinary;