@mastra/apple-container 0.3.0 → 0.4.0
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 +22 -0
- package/dist/index.cjs +817 -901
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +815 -898
- package/dist/index.js.map +1 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/package.json +9 -8
package/dist/index.cjs
CHANGED
|
@@ -1,948 +1,864 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let child_process = require("child_process");
|
|
3
|
+
let crypto = require("crypto");
|
|
4
|
+
let string_decoder = require("string_decoder");
|
|
5
|
+
let _mastra_core_workspace = require("@mastra/core/workspace");
|
|
6
|
+
//#region src/sandbox/index.ts
|
|
7
|
+
/**
|
|
8
|
+
* Apple container CLI sandbox provider.
|
|
9
|
+
*
|
|
10
|
+
* This provider maps Mastra's WorkspaceSandbox command execution contract to
|
|
11
|
+
* Apple's `container` CLI. It starts a long-lived OCI Linux container and uses
|
|
12
|
+
* `container exec` for commands.
|
|
13
|
+
*
|
|
14
|
+
* @see https://github.com/apple/container
|
|
15
|
+
*/
|
|
16
|
+
const DEFAULT_COMMAND_TIMEOUT_MS = 3e5;
|
|
17
|
+
const DEFAULT_IMAGE = "node:22-slim";
|
|
18
|
+
const DEFAULT_COMMAND = ["sleep", "infinity"];
|
|
19
|
+
const DEFAULT_WORKING_DIR = "/workspace";
|
|
20
|
+
const APPLE_CONTAINER_CLI_GRACE_TIMEOUT_MS = 1e4;
|
|
21
|
+
const APPLE_CONTAINER_READY_TIMEOUT_MS = 1e4;
|
|
22
|
+
const APPLE_CONTAINER_READY_EXEC_TIMEOUT_MS = 5e3;
|
|
23
|
+
const APPLE_CONTAINER_TIMEOUT_EXIT_CODE = 124;
|
|
24
|
+
const APPLE_CONTAINER_TIMEOUT_MARKER = "__MASTRA_APPLE_CONTAINER_TIMEOUT__";
|
|
18
25
|
var DefaultAppleContainerCommandRunner = class {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
binary;
|
|
27
|
+
constructor(binary = "container") {
|
|
28
|
+
this.binary = binary;
|
|
29
|
+
}
|
|
30
|
+
run(args, options = {}) {
|
|
31
|
+
return runAppleContainerCli(this.binary, args, options);
|
|
32
|
+
}
|
|
26
33
|
};
|
|
27
|
-
var AppleContainerSandbox = class
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
ssh: this._ssh,
|
|
443
|
-
init: this._init,
|
|
444
|
-
virtualization: this._virtualization,
|
|
445
|
-
capAdd: this._capAdd,
|
|
446
|
-
capDrop: this._capDrop,
|
|
447
|
-
tmpfs: this._tmpfs,
|
|
448
|
-
dns: this._dns,
|
|
449
|
-
dnsSearch: this._dnsSearch,
|
|
450
|
-
noDns: this._noDns,
|
|
451
|
-
labels: this._userLabels,
|
|
452
|
-
workingDir: this._workingDir,
|
|
453
|
-
timeout: this._timeout,
|
|
454
|
-
deleteOnDestroy: this._deleteOnDestroy
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
_assertSuccess(result, action) {
|
|
458
|
-
if (result.success) return;
|
|
459
|
-
throw new workspace.SandboxExecutionError(
|
|
460
|
-
`${action} failed with exit code ${result.exitCode}: ${result.stderr}`,
|
|
461
|
-
result.exitCode,
|
|
462
|
-
result.stdout,
|
|
463
|
-
result.stderr
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
_assertMastraOwned(inspect) {
|
|
467
|
-
if (isMastraOwned(inspect, this.id)) return;
|
|
468
|
-
throw new workspace.SandboxExecutionError(
|
|
469
|
-
`Refusing to manage Apple container ${this.containerId} because it is not labeled as Mastra sandbox ${this.id}`,
|
|
470
|
-
1,
|
|
471
|
-
"",
|
|
472
|
-
""
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
_assertCompatibleConfig(inspect) {
|
|
476
|
-
const existingHash = inspect.configuration?.labels?.["mastra.sandbox.config-hash"];
|
|
477
|
-
if (!existingHash || existingHash === this._configHash) return;
|
|
478
|
-
throw new workspace.SandboxExecutionError(
|
|
479
|
-
`Refusing to manage Apple container ${this.containerId} because its immutable configuration does not match sandbox ${this.id}`,
|
|
480
|
-
1,
|
|
481
|
-
"",
|
|
482
|
-
""
|
|
483
|
-
);
|
|
484
|
-
}
|
|
485
|
-
_runCli(args, options = {}) {
|
|
486
|
-
return this._runner.run(args, {
|
|
487
|
-
timeout: this._timeout,
|
|
488
|
-
...options
|
|
489
|
-
});
|
|
490
|
-
}
|
|
34
|
+
var AppleContainerSandbox = class AppleContainerSandbox extends _mastra_core_workspace.MastraSandbox {
|
|
35
|
+
id;
|
|
36
|
+
name = "AppleContainerSandbox";
|
|
37
|
+
provider = "apple-container";
|
|
38
|
+
status = "pending";
|
|
39
|
+
_containerName;
|
|
40
|
+
_configuredName;
|
|
41
|
+
_image;
|
|
42
|
+
_command;
|
|
43
|
+
_env;
|
|
44
|
+
_volumes;
|
|
45
|
+
_mounts;
|
|
46
|
+
_network;
|
|
47
|
+
_publishedPorts;
|
|
48
|
+
_publishedSockets;
|
|
49
|
+
_cpus;
|
|
50
|
+
_memory;
|
|
51
|
+
_platform;
|
|
52
|
+
_arch;
|
|
53
|
+
_os;
|
|
54
|
+
_rosetta;
|
|
55
|
+
_readonlyRootfs;
|
|
56
|
+
_ssh;
|
|
57
|
+
_init;
|
|
58
|
+
_virtualization;
|
|
59
|
+
_capAdd;
|
|
60
|
+
_capDrop;
|
|
61
|
+
_tmpfs;
|
|
62
|
+
_dns;
|
|
63
|
+
_dnsSearch;
|
|
64
|
+
_noDns;
|
|
65
|
+
_userLabels;
|
|
66
|
+
_labels;
|
|
67
|
+
_configHash;
|
|
68
|
+
_workingDir;
|
|
69
|
+
_timeout;
|
|
70
|
+
_deleteOnDestroy;
|
|
71
|
+
_runner;
|
|
72
|
+
_instructionsOverride;
|
|
73
|
+
_createdAt;
|
|
74
|
+
_constructorOptions;
|
|
75
|
+
_containerId;
|
|
76
|
+
constructor(options = {}) {
|
|
77
|
+
super({
|
|
78
|
+
...options,
|
|
79
|
+
name: "AppleContainerSandbox"
|
|
80
|
+
});
|
|
81
|
+
this.id = options.id ?? generateId();
|
|
82
|
+
this._configuredName = options.name;
|
|
83
|
+
this._containerName = sanitizeContainerName(options.name ?? this.id);
|
|
84
|
+
this._image = options.image ?? DEFAULT_IMAGE;
|
|
85
|
+
this._command = options.command ?? DEFAULT_COMMAND;
|
|
86
|
+
this._env = options.env ?? {};
|
|
87
|
+
this._volumes = options.volumes ?? {};
|
|
88
|
+
this._mounts = options.mounts ?? [];
|
|
89
|
+
this._network = options.network;
|
|
90
|
+
this._publishedPorts = options.publishedPorts ?? [];
|
|
91
|
+
this._publishedSockets = options.publishedSockets ?? [];
|
|
92
|
+
this._cpus = options.cpus;
|
|
93
|
+
this._memory = options.memory;
|
|
94
|
+
this._platform = options.platform;
|
|
95
|
+
this._arch = options.arch;
|
|
96
|
+
this._os = options.os;
|
|
97
|
+
this._rosetta = options.rosetta ?? false;
|
|
98
|
+
this._readonlyRootfs = options.readonlyRootfs ?? false;
|
|
99
|
+
this._ssh = options.ssh ?? false;
|
|
100
|
+
this._init = options.init ?? true;
|
|
101
|
+
this._virtualization = options.virtualization ?? false;
|
|
102
|
+
this._capAdd = options.capAdd ?? [];
|
|
103
|
+
this._capDrop = options.capDrop ?? [];
|
|
104
|
+
this._tmpfs = options.tmpfs ?? [];
|
|
105
|
+
validateTmpfsPaths(this._tmpfs);
|
|
106
|
+
this._dns = options.dns ?? [];
|
|
107
|
+
this._dnsSearch = options.dnsSearch ?? [];
|
|
108
|
+
this._noDns = options.noDns ?? false;
|
|
109
|
+
this._workingDir = options.workingDir ?? DEFAULT_WORKING_DIR;
|
|
110
|
+
this._userLabels = options.labels ?? {};
|
|
111
|
+
this._configHash = hashConfig(this._runtimeConfigForHash());
|
|
112
|
+
this._labels = {
|
|
113
|
+
...this._userLabels,
|
|
114
|
+
"mastra.sandbox": "true",
|
|
115
|
+
"mastra.sandbox.id": this.id,
|
|
116
|
+
"mastra.sandbox.config-hash": this._configHash
|
|
117
|
+
};
|
|
118
|
+
this._timeout = options.timeout ?? DEFAULT_COMMAND_TIMEOUT_MS;
|
|
119
|
+
this._deleteOnDestroy = options.deleteOnDestroy ?? true;
|
|
120
|
+
this._runner = options.runner ?? new DefaultAppleContainerCommandRunner(options.containerBinary);
|
|
121
|
+
this._instructionsOverride = options.instructions;
|
|
122
|
+
this._createdAt = /* @__PURE__ */ new Date();
|
|
123
|
+
this._constructorOptions = { ...options };
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Construct a sibling `AppleContainerSandbox` that inherits this sandbox's
|
|
127
|
+
* configuration (image, resources, network, security options, labels) with
|
|
128
|
+
* per-instance overrides.
|
|
129
|
+
*
|
|
130
|
+
* Performs no I/O — the sandbox clone provisions (or reconnects to an
|
|
131
|
+
* existing container labelled with the same logical `id`) on its own
|
|
132
|
+
* `start()`. Use it when one configured sandbox acts as the template for a
|
|
133
|
+
* fleet of independent sandboxes (e.g. one per project).
|
|
134
|
+
*
|
|
135
|
+
* `options.idleTimeoutMinutes` is ignored (Apple containers have no
|
|
136
|
+
* provider-side idle teardown; `timeout` here is a command timeout), and
|
|
137
|
+
* `options.sandboxId` is ignored because reconnection is by logical `id`.
|
|
138
|
+
*/
|
|
139
|
+
clone(options = {}) {
|
|
140
|
+
const { id: _id, name: _name, ...base } = this._constructorOptions;
|
|
141
|
+
return new AppleContainerSandbox({
|
|
142
|
+
...base,
|
|
143
|
+
...options.id !== void 0 && { id: options.id },
|
|
144
|
+
...options.env !== void 0 && { env: options.env }
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
get containerId() {
|
|
148
|
+
return this._containerId ?? this._containerName;
|
|
149
|
+
}
|
|
150
|
+
async start() {
|
|
151
|
+
await this._runPlainLifecycle("starting", "running", () => this._startContainer());
|
|
152
|
+
}
|
|
153
|
+
async stop() {
|
|
154
|
+
await this._runPlainLifecycle("stopping", "stopped", () => this._stopContainer());
|
|
155
|
+
}
|
|
156
|
+
async destroy() {
|
|
157
|
+
await this._runPlainLifecycle("destroying", "destroyed", () => this._destroyContainer());
|
|
158
|
+
}
|
|
159
|
+
async _startContainer() {
|
|
160
|
+
const existing = await this._inspectContainer();
|
|
161
|
+
if (existing) {
|
|
162
|
+
this._assertMastraOwned(existing);
|
|
163
|
+
this._assertCompatibleConfig(existing);
|
|
164
|
+
this._containerId = existing.configuration?.id ?? this._containerName;
|
|
165
|
+
if (!isRunning(existing)) {
|
|
166
|
+
const result = await this._runCli(["start", this.containerId]);
|
|
167
|
+
this._assertSuccess(result, `start Apple container ${this.containerId}`);
|
|
168
|
+
await this._waitUntilContainerReady(`start Apple container ${this.containerId}`);
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const env = envFlags(this._env);
|
|
173
|
+
const result = await this._runCli(this._buildRunArgs(env.args), { env: env.env });
|
|
174
|
+
this._assertSuccess(result, `create Apple container ${this._containerName}`);
|
|
175
|
+
this._containerId = this._containerName;
|
|
176
|
+
try {
|
|
177
|
+
await this._waitUntilContainerReady(`create Apple container ${this._containerName}`);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (this._deleteOnDestroy) await this._deleteContainerIgnoringMissing();
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async _stopContainer() {
|
|
184
|
+
const existing = await this._inspectContainer();
|
|
185
|
+
if (!existing) return;
|
|
186
|
+
this._assertMastraOwned(existing);
|
|
187
|
+
if (!isRunning(existing)) return;
|
|
188
|
+
const result = await this._runCli(["stop", this.containerId]);
|
|
189
|
+
if (!result.success && !isMissingContainerMessage(result.stderr)) this._assertSuccess(result, `stop Apple container ${this.containerId}`);
|
|
190
|
+
}
|
|
191
|
+
async _destroyContainer() {
|
|
192
|
+
if (!this._deleteOnDestroy) {
|
|
193
|
+
await this._stopContainer();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const existing = await this._inspectContainer();
|
|
197
|
+
if (!existing) return;
|
|
198
|
+
this._assertMastraOwned(existing);
|
|
199
|
+
await this._deleteContainerIgnoringMissing();
|
|
200
|
+
}
|
|
201
|
+
async executeCommand(command, args = [], options = {}) {
|
|
202
|
+
await this.ensureRunning();
|
|
203
|
+
const commandTimeout = options.timeout ?? this._timeout;
|
|
204
|
+
const hasCommandTimeout = Number.isFinite(commandTimeout) && commandTimeout > 0;
|
|
205
|
+
const fullCommand = buildShellCommand(command, args);
|
|
206
|
+
const shellCommand = hasCommandTimeout ? buildTimeoutShellCommand(fullCommand, commandTimeout) : fullCommand;
|
|
207
|
+
const env = envFlags({
|
|
208
|
+
...this._env,
|
|
209
|
+
...options.env
|
|
210
|
+
});
|
|
211
|
+
const cliArgs = [
|
|
212
|
+
"exec",
|
|
213
|
+
...env.args,
|
|
214
|
+
"--workdir",
|
|
215
|
+
options.cwd ?? this._workingDir,
|
|
216
|
+
this.containerId,
|
|
217
|
+
"sh",
|
|
218
|
+
"-lc",
|
|
219
|
+
shellCommand
|
|
220
|
+
];
|
|
221
|
+
const result = await this._runner.run(cliArgs, {
|
|
222
|
+
timeout: hasCommandTimeout ? commandTimeout + APPLE_CONTAINER_CLI_GRACE_TIMEOUT_MS : void 0,
|
|
223
|
+
env: env.env,
|
|
224
|
+
abortSignal: options.abortSignal,
|
|
225
|
+
onStdout: options.onStdout,
|
|
226
|
+
onStderr: options.onStderr,
|
|
227
|
+
maxRetainedBytes: options.maxRetainedBytes
|
|
228
|
+
});
|
|
229
|
+
const timedOut = result.exitCode === APPLE_CONTAINER_TIMEOUT_EXIT_CODE && result.stderr.includes(APPLE_CONTAINER_TIMEOUT_MARKER);
|
|
230
|
+
const stderr = timedOut ? stripTimeoutMarker(result.stderr) : result.stderr;
|
|
231
|
+
return {
|
|
232
|
+
...result,
|
|
233
|
+
stderr,
|
|
234
|
+
...timedOut && {
|
|
235
|
+
timedOut: true,
|
|
236
|
+
killed: true
|
|
237
|
+
},
|
|
238
|
+
command: fullCommand,
|
|
239
|
+
args
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
async getInfo() {
|
|
243
|
+
const resources = (this._containerId ? await this._inspectContainer() : void 0)?.configuration?.resources;
|
|
244
|
+
return {
|
|
245
|
+
id: this.id,
|
|
246
|
+
name: this.name,
|
|
247
|
+
provider: this.provider,
|
|
248
|
+
status: this.status,
|
|
249
|
+
createdAt: this._createdAt,
|
|
250
|
+
resources: resources ? {
|
|
251
|
+
cpuCores: resources.cpus,
|
|
252
|
+
memoryMB: resources.memoryInBytes ? Math.round(resources.memoryInBytes / 1024 / 1024) : void 0
|
|
253
|
+
} : void 0,
|
|
254
|
+
metadata: { ...this._serializableConfig() }
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
getInstructions(opts) {
|
|
258
|
+
const defaultInstructions = this._buildDefaultInstructions();
|
|
259
|
+
if (typeof this._instructionsOverride === "string") return this._instructionsOverride;
|
|
260
|
+
if (typeof this._instructionsOverride === "function") return this._instructionsOverride({
|
|
261
|
+
defaultInstructions,
|
|
262
|
+
requestContext: opts?.requestContext
|
|
263
|
+
});
|
|
264
|
+
return defaultInstructions;
|
|
265
|
+
}
|
|
266
|
+
_buildDefaultInstructions() {
|
|
267
|
+
const parts = [`Apple container sandbox: commands run inside a local OCI Linux container from image ${this._image}.`, `Working directory: ${this._workingDir}.`];
|
|
268
|
+
const volumeCount = Object.keys(this._volumes).length + this._mounts.length;
|
|
269
|
+
if (volumeCount > 0) parts.push(`${volumeCount} host mount(s) are configured.`);
|
|
270
|
+
if (this._timeout > 0) parts.push(`Default command timeout: ${Math.ceil(this._timeout / 1e3)}s.`);
|
|
271
|
+
return parts.join(" ");
|
|
272
|
+
}
|
|
273
|
+
async _runPlainLifecycle(activeStatus, completeStatus, operation) {
|
|
274
|
+
const managedByBaseWrapper = this.status === activeStatus;
|
|
275
|
+
if (!managedByBaseWrapper) this.status = activeStatus;
|
|
276
|
+
try {
|
|
277
|
+
await operation();
|
|
278
|
+
if (!managedByBaseWrapper) this.status = completeStatus;
|
|
279
|
+
} catch (error) {
|
|
280
|
+
if (!managedByBaseWrapper) this.status = "error";
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
async _inspectContainer() {
|
|
285
|
+
const result = await this._runCli(["inspect", this.containerId]);
|
|
286
|
+
if (!result.success) {
|
|
287
|
+
if (isMissingContainerMessage(result.stderr)) return void 0;
|
|
288
|
+
this._assertSuccess(result, `inspect Apple container ${this.containerId}`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
const parsed = JSON.parse(result.stdout);
|
|
293
|
+
return Array.isArray(parsed) ? parsed[0] : parsed;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
throw new _mastra_core_workspace.SandboxExecutionError(`Failed to parse Apple container inspect output for ${this.containerId}: ${error instanceof Error ? error.message : String(error)}`, 1, result.stdout, result.stderr);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
_buildRunArgs(envArgs) {
|
|
299
|
+
const args = [
|
|
300
|
+
"run",
|
|
301
|
+
"-d",
|
|
302
|
+
"--name",
|
|
303
|
+
this._containerName,
|
|
304
|
+
"--workdir",
|
|
305
|
+
this._workingDir
|
|
306
|
+
];
|
|
307
|
+
args.push(...envArgs);
|
|
308
|
+
for (const [hostPath, containerPath] of Object.entries(this._volumes)) args.push("--volume", `${hostPath}:${containerPath}`);
|
|
309
|
+
for (const mount of this._mounts) args.push("--mount", mount);
|
|
310
|
+
for (const [key, value] of Object.entries(this._labels)) args.push("--label", `${key}=${value}`);
|
|
311
|
+
for (const port of this._publishedPorts) args.push("--publish", port);
|
|
312
|
+
for (const socket of this._publishedSockets) args.push("--publish-socket", socket);
|
|
313
|
+
for (const cap of this._capAdd) args.push("--cap-add", cap);
|
|
314
|
+
for (const cap of this._capDrop) args.push("--cap-drop", cap);
|
|
315
|
+
for (const tmpfs of this._tmpfs) args.push("--tmpfs", tmpfs);
|
|
316
|
+
for (const dns of this._dns) args.push("--dns", dns);
|
|
317
|
+
for (const domain of this._dnsSearch) args.push("--dns-search", domain);
|
|
318
|
+
if (this._network) args.push("--network", this._network);
|
|
319
|
+
if (this._cpus !== void 0) args.push("--cpus", String(this._cpus));
|
|
320
|
+
if (this._memory !== void 0) args.push("--memory", this._memory);
|
|
321
|
+
if (this._platform) args.push("--platform", this._platform);
|
|
322
|
+
if (this._arch) args.push("--arch", this._arch);
|
|
323
|
+
if (this._os) args.push("--os", this._os);
|
|
324
|
+
if (this._rosetta) args.push("--rosetta");
|
|
325
|
+
if (this._readonlyRootfs) args.push("--read-only");
|
|
326
|
+
if (this._ssh) args.push("--ssh");
|
|
327
|
+
if (this._init) args.push("--init");
|
|
328
|
+
if (this._virtualization) args.push("--virtualization");
|
|
329
|
+
if (this._noDns) args.push("--no-dns");
|
|
330
|
+
args.push(this._image, ...this._command);
|
|
331
|
+
return args;
|
|
332
|
+
}
|
|
333
|
+
async _waitUntilContainerReady(action) {
|
|
334
|
+
const deadline = Date.now() + APPLE_CONTAINER_READY_TIMEOUT_MS;
|
|
335
|
+
let lastResult;
|
|
336
|
+
while (Date.now() < deadline) {
|
|
337
|
+
const inspect = await this._inspectContainer();
|
|
338
|
+
if (!inspect) throw new _mastra_core_workspace.SandboxExecutionError(`${action} failed because Apple container ${this.containerId} disappeared`, 1, "", "");
|
|
339
|
+
this._assertMastraOwned(inspect);
|
|
340
|
+
this._assertCompatibleConfig(inspect);
|
|
341
|
+
if (!isRunning(inspect)) {
|
|
342
|
+
const state = getContainerState(inspect) ?? "not running";
|
|
343
|
+
throw new _mastra_core_workspace.SandboxExecutionError(`${action} failed because Apple container ${this.containerId} is ${state}`, 1, "", "");
|
|
344
|
+
}
|
|
345
|
+
lastResult = await this._runCli([
|
|
346
|
+
"exec",
|
|
347
|
+
this.containerId,
|
|
348
|
+
"sh",
|
|
349
|
+
"-lc",
|
|
350
|
+
"true"
|
|
351
|
+
], { timeout: APPLE_CONTAINER_READY_EXEC_TIMEOUT_MS });
|
|
352
|
+
if (lastResult.success) return;
|
|
353
|
+
if (!isMissingContainerMessage(lastResult.stderr) && !/not running|not yet running/i.test(lastResult.stderr)) break;
|
|
354
|
+
await delay(100);
|
|
355
|
+
}
|
|
356
|
+
throw new _mastra_core_workspace.SandboxExecutionError(`${action} failed because Apple container ${this.containerId} did not become ready for exec`, lastResult?.exitCode ?? 1, lastResult?.stdout ?? "", lastResult?.stderr ?? "");
|
|
357
|
+
}
|
|
358
|
+
async _deleteContainerIgnoringMissing() {
|
|
359
|
+
const result = await this._runCli([
|
|
360
|
+
"delete",
|
|
361
|
+
"--force",
|
|
362
|
+
this.containerId
|
|
363
|
+
]);
|
|
364
|
+
if (!result.success && !isMissingContainerMessage(result.stderr)) this._assertSuccess(result, `delete Apple container ${this.containerId}`);
|
|
365
|
+
}
|
|
366
|
+
_runtimeConfigForHash() {
|
|
367
|
+
return {
|
|
368
|
+
image: this._image,
|
|
369
|
+
command: this._command,
|
|
370
|
+
env: this._env,
|
|
371
|
+
volumes: this._volumes,
|
|
372
|
+
mounts: this._mounts,
|
|
373
|
+
network: this._network,
|
|
374
|
+
publishedPorts: this._publishedPorts,
|
|
375
|
+
publishedSockets: this._publishedSockets,
|
|
376
|
+
cpus: this._cpus,
|
|
377
|
+
memory: this._memory,
|
|
378
|
+
platform: this._platform,
|
|
379
|
+
arch: this._arch,
|
|
380
|
+
os: this._os,
|
|
381
|
+
rosetta: this._rosetta,
|
|
382
|
+
readonlyRootfs: this._readonlyRootfs,
|
|
383
|
+
ssh: this._ssh,
|
|
384
|
+
init: this._init,
|
|
385
|
+
virtualization: this._virtualization,
|
|
386
|
+
capAdd: this._capAdd,
|
|
387
|
+
capDrop: this._capDrop,
|
|
388
|
+
tmpfs: this._tmpfs,
|
|
389
|
+
dns: this._dns,
|
|
390
|
+
dnsSearch: this._dnsSearch,
|
|
391
|
+
noDns: this._noDns,
|
|
392
|
+
labels: this._userLabels,
|
|
393
|
+
workingDir: this._workingDir
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
_serializableConfig() {
|
|
397
|
+
return compactConfig({
|
|
398
|
+
id: this.id,
|
|
399
|
+
name: this._configuredName,
|
|
400
|
+
image: this._image,
|
|
401
|
+
command: this._command,
|
|
402
|
+
env: this._env,
|
|
403
|
+
volumes: this._volumes,
|
|
404
|
+
mounts: this._mounts,
|
|
405
|
+
network: this._network,
|
|
406
|
+
publishedPorts: this._publishedPorts,
|
|
407
|
+
publishedSockets: this._publishedSockets,
|
|
408
|
+
cpus: this._cpus,
|
|
409
|
+
memory: this._memory,
|
|
410
|
+
platform: this._platform,
|
|
411
|
+
arch: this._arch,
|
|
412
|
+
os: this._os,
|
|
413
|
+
rosetta: this._rosetta,
|
|
414
|
+
readonlyRootfs: this._readonlyRootfs,
|
|
415
|
+
ssh: this._ssh,
|
|
416
|
+
init: this._init,
|
|
417
|
+
virtualization: this._virtualization,
|
|
418
|
+
capAdd: this._capAdd,
|
|
419
|
+
capDrop: this._capDrop,
|
|
420
|
+
tmpfs: this._tmpfs,
|
|
421
|
+
dns: this._dns,
|
|
422
|
+
dnsSearch: this._dnsSearch,
|
|
423
|
+
noDns: this._noDns,
|
|
424
|
+
labels: this._userLabels,
|
|
425
|
+
workingDir: this._workingDir,
|
|
426
|
+
timeout: this._timeout,
|
|
427
|
+
deleteOnDestroy: this._deleteOnDestroy
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
_assertSuccess(result, action) {
|
|
431
|
+
if (result.success) return;
|
|
432
|
+
throw new _mastra_core_workspace.SandboxExecutionError(`${action} failed with exit code ${result.exitCode}: ${result.stderr}`, result.exitCode, result.stdout, result.stderr);
|
|
433
|
+
}
|
|
434
|
+
_assertMastraOwned(inspect) {
|
|
435
|
+
if (isMastraOwned(inspect, this.id)) return;
|
|
436
|
+
throw new _mastra_core_workspace.SandboxExecutionError(`Refusing to manage Apple container ${this.containerId} because it is not labeled as Mastra sandbox ${this.id}`, 1, "", "");
|
|
437
|
+
}
|
|
438
|
+
_assertCompatibleConfig(inspect) {
|
|
439
|
+
const existingHash = inspect.configuration?.labels?.["mastra.sandbox.config-hash"];
|
|
440
|
+
if (!existingHash || existingHash === this._configHash) return;
|
|
441
|
+
throw new _mastra_core_workspace.SandboxExecutionError(`Refusing to manage Apple container ${this.containerId} because its immutable configuration does not match sandbox ${this.id}`, 1, "", "");
|
|
442
|
+
}
|
|
443
|
+
_runCli(args, options = {}) {
|
|
444
|
+
return this._runner.run(args, {
|
|
445
|
+
timeout: this._timeout,
|
|
446
|
+
...options
|
|
447
|
+
});
|
|
448
|
+
}
|
|
491
449
|
};
|
|
492
450
|
function runAppleContainerCli(binary, args, options = {}) {
|
|
493
|
-
|
|
494
|
-
return handle.wait();
|
|
451
|
+
return new AppleContainerCliProcess(binary, args, options).wait();
|
|
495
452
|
}
|
|
496
|
-
var AppleContainerCliProcess = class extends
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
453
|
+
var AppleContainerCliProcess = class extends _mastra_core_workspace.ProcessHandle {
|
|
454
|
+
pid;
|
|
455
|
+
exitCode;
|
|
456
|
+
child;
|
|
457
|
+
waitPromise;
|
|
458
|
+
startedAt = Date.now();
|
|
459
|
+
killed = false;
|
|
460
|
+
timedOut = false;
|
|
461
|
+
forceKillTimeout;
|
|
462
|
+
constructor(binary, args, options = {}) {
|
|
463
|
+
super({
|
|
464
|
+
maxRetainedBytes: options.maxRetainedBytes,
|
|
465
|
+
onStdout: options.onStdout,
|
|
466
|
+
onStderr: options.onStderr
|
|
467
|
+
});
|
|
468
|
+
this.child = (0, child_process.spawn)(binary, args, {
|
|
469
|
+
stdio: [
|
|
470
|
+
"ignore",
|
|
471
|
+
"pipe",
|
|
472
|
+
"pipe"
|
|
473
|
+
],
|
|
474
|
+
env: options.env ? {
|
|
475
|
+
...process.env,
|
|
476
|
+
...options.env
|
|
477
|
+
} : process.env
|
|
478
|
+
});
|
|
479
|
+
this.pid = this.child.pid ? String(this.child.pid) : `${binary}:${args.join(" ")}`;
|
|
480
|
+
let settled = false;
|
|
481
|
+
const stdoutDecoder = new string_decoder.StringDecoder();
|
|
482
|
+
const stderrDecoder = new string_decoder.StringDecoder();
|
|
483
|
+
let stdoutDecoderEnded = false;
|
|
484
|
+
let stderrDecoderEnded = false;
|
|
485
|
+
let timeout;
|
|
486
|
+
const onAbort = () => {
|
|
487
|
+
this.kill();
|
|
488
|
+
};
|
|
489
|
+
const flushStdout = () => {
|
|
490
|
+
if (stdoutDecoderEnded) return;
|
|
491
|
+
stdoutDecoderEnded = true;
|
|
492
|
+
const data = stdoutDecoder.end();
|
|
493
|
+
if (data) this.emitStdout(data);
|
|
494
|
+
};
|
|
495
|
+
const flushStderr = () => {
|
|
496
|
+
if (stderrDecoderEnded) return;
|
|
497
|
+
stderrDecoderEnded = true;
|
|
498
|
+
const data = stderrDecoder.end();
|
|
499
|
+
if (data) this.emitStderr(data);
|
|
500
|
+
};
|
|
501
|
+
const finish = (exitCode) => {
|
|
502
|
+
this.exitCode = exitCode;
|
|
503
|
+
return {
|
|
504
|
+
success: exitCode === 0,
|
|
505
|
+
exitCode,
|
|
506
|
+
stdout: this.stdout,
|
|
507
|
+
stderr: this.stderr,
|
|
508
|
+
executionTimeMs: Date.now() - this.startedAt,
|
|
509
|
+
killed: this.killed,
|
|
510
|
+
timedOut: this.timedOut
|
|
511
|
+
};
|
|
512
|
+
};
|
|
513
|
+
const cleanup = () => {
|
|
514
|
+
if (timeout) clearTimeout(timeout);
|
|
515
|
+
if (this.forceKillTimeout) clearTimeout(this.forceKillTimeout);
|
|
516
|
+
options.abortSignal?.removeEventListener("abort", onAbort);
|
|
517
|
+
};
|
|
518
|
+
this.waitPromise = new Promise((resolve, reject) => {
|
|
519
|
+
const settle = (callback) => {
|
|
520
|
+
if (settled) return;
|
|
521
|
+
settled = true;
|
|
522
|
+
cleanup();
|
|
523
|
+
callback();
|
|
524
|
+
};
|
|
525
|
+
this.child.stdout.on("data", (chunk) => {
|
|
526
|
+
const data = stdoutDecoder.write(chunk);
|
|
527
|
+
if (data) this.emitStdout(data);
|
|
528
|
+
});
|
|
529
|
+
this.child.stderr.on("data", (chunk) => {
|
|
530
|
+
const data = stderrDecoder.write(chunk);
|
|
531
|
+
if (data) this.emitStderr(data);
|
|
532
|
+
});
|
|
533
|
+
this.child.stdout.on("end", flushStdout);
|
|
534
|
+
this.child.stderr.on("end", flushStderr);
|
|
535
|
+
this.child.on("error", (error) => {
|
|
536
|
+
settle(() => {
|
|
537
|
+
flushStdout();
|
|
538
|
+
flushStderr();
|
|
539
|
+
reject(error instanceof Error && "code" in error && error.code === "ENOENT" ? new _mastra_core_workspace.SandboxExecutionError(`Apple container CLI not found: ${binary}`, 127, this.stdout, error.message) : error);
|
|
540
|
+
});
|
|
541
|
+
});
|
|
542
|
+
this.child.on("close", (code) => {
|
|
543
|
+
settle(() => {
|
|
544
|
+
flushStdout();
|
|
545
|
+
flushStderr();
|
|
546
|
+
resolve(finish(code ?? (this.killed ? 137 : 1)));
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
timeout = options.timeout && options.timeout > 0 ? setTimeout(() => {
|
|
551
|
+
this.timedOut = true;
|
|
552
|
+
this.kill();
|
|
553
|
+
}, options.timeout) : void 0;
|
|
554
|
+
if (options.abortSignal) if (options.abortSignal.aborted) this.kill();
|
|
555
|
+
else options.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
556
|
+
}
|
|
557
|
+
async wait() {
|
|
558
|
+
return this.waitPromise;
|
|
559
|
+
}
|
|
560
|
+
async kill() {
|
|
561
|
+
if (this.exitCode !== void 0 || this.child.killed) return false;
|
|
562
|
+
this.killed = true;
|
|
563
|
+
this.child.kill("SIGTERM");
|
|
564
|
+
this.forceKillTimeout = setTimeout(() => {
|
|
565
|
+
if (this.exitCode === void 0 && this.child.exitCode === null && this.child.signalCode === null) this.child.kill("SIGKILL");
|
|
566
|
+
}, 1e3);
|
|
567
|
+
this.forceKillTimeout.unref();
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
async sendStdin() {
|
|
571
|
+
throw new Error("Apple container CLI runner does not support stdin");
|
|
572
|
+
}
|
|
573
|
+
async closeStdin() {
|
|
574
|
+
throw new _mastra_core_workspace.UnsupportedStdinCloseError("Apple container CLI runner does not support closing stdin");
|
|
575
|
+
}
|
|
618
576
|
};
|
|
619
577
|
function generateId() {
|
|
620
|
-
|
|
578
|
+
return `apple-container-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
621
579
|
}
|
|
622
580
|
function sanitizeContainerName(name) {
|
|
623
|
-
|
|
624
|
-
|
|
581
|
+
const sanitized = name.replace(/[^a-zA-Z0-9_.-]/g, "-");
|
|
582
|
+
return /^[a-zA-Z0-9]/.test(sanitized) ? sanitized : `c-${sanitized}`;
|
|
625
583
|
}
|
|
626
584
|
function buildShellCommand(command, args) {
|
|
627
|
-
|
|
585
|
+
return args.length > 0 ? [command, ...args].map(shellQuote).join(" ") : command;
|
|
628
586
|
}
|
|
629
587
|
function buildTimeoutShellCommand(command, timeoutMs) {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
`case "$timeout_code" in 124|137|143) printf '%s\\n' ${shellQuote(APPLE_CONTAINER_TIMEOUT_MARKER)} >&2; exit ${APPLE_CONTAINER_TIMEOUT_EXIT_CODE};; *) exit "$timeout_code";; esac`
|
|
647
|
-
].join("; ");
|
|
588
|
+
return [
|
|
589
|
+
"result_file=\"/tmp/.mastra-apple-container-exit-$$\"",
|
|
590
|
+
"rm -f \"$result_file\"",
|
|
591
|
+
`MASTRA_TIMEOUT_RESULT_FILE="$result_file" timeout ${formatTimeoutSeconds(timeoutMs)}s sh -lc ${shellQuote([
|
|
592
|
+
`sh -lc ${shellQuote(command)} & child=$!`,
|
|
593
|
+
`trap 'kill -TERM "$child" 2>/dev/null; wait "$child" 2>/dev/null; exit ${APPLE_CONTAINER_TIMEOUT_EXIT_CODE}' TERM INT`,
|
|
594
|
+
"wait \"$child\"; code=$?",
|
|
595
|
+
"trap - TERM INT",
|
|
596
|
+
"printf \"%s\" \"$code\" > \"$MASTRA_TIMEOUT_RESULT_FILE\"",
|
|
597
|
+
"exit \"$code\""
|
|
598
|
+
].join("; "))}`,
|
|
599
|
+
"timeout_code=$?",
|
|
600
|
+
"if [ -f \"$result_file\" ]; then code=\"$(cat \"$result_file\")\"; rm -f \"$result_file\"; exit \"$code\"; fi",
|
|
601
|
+
"rm -f \"$result_file\"",
|
|
602
|
+
`case "$timeout_code" in 124|137|143) printf '%s\\n' ${shellQuote(APPLE_CONTAINER_TIMEOUT_MARKER)} >&2; exit ${APPLE_CONTAINER_TIMEOUT_EXIT_CODE};; *) exit "$timeout_code";; esac`
|
|
603
|
+
].join("; ");
|
|
648
604
|
}
|
|
649
605
|
function formatTimeoutSeconds(timeoutMs) {
|
|
650
|
-
|
|
606
|
+
return Math.max(timeoutMs / 1e3, .001).toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
|
|
651
607
|
}
|
|
652
608
|
function shellQuote(arg) {
|
|
653
|
-
|
|
654
|
-
|
|
609
|
+
if (/^[a-zA-Z0-9._\-\/=:@]+$/.test(arg)) return arg;
|
|
610
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
655
611
|
}
|
|
656
612
|
function stripTimeoutMarker(stderr) {
|
|
657
|
-
|
|
613
|
+
return stderr.split("\n").filter((line) => line.trim() !== APPLE_CONTAINER_TIMEOUT_MARKER).join("\n").replace(/^\n+|\n+$/g, "");
|
|
658
614
|
}
|
|
659
615
|
function envFlags(env) {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
616
|
+
const args = [];
|
|
617
|
+
const childEnv = {};
|
|
618
|
+
for (const [key, value] of Object.entries(env)) {
|
|
619
|
+
if (value === void 0) continue;
|
|
620
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`Invalid environment variable name for Apple container command: ${key}`);
|
|
621
|
+
args.push("--env", key);
|
|
622
|
+
childEnv[key] = value;
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
args,
|
|
626
|
+
env: childEnv
|
|
627
|
+
};
|
|
671
628
|
}
|
|
672
629
|
function isRunning(inspect) {
|
|
673
|
-
|
|
630
|
+
return getContainerState(inspect) === "running";
|
|
674
631
|
}
|
|
675
632
|
function getContainerState(inspect) {
|
|
676
|
-
|
|
633
|
+
return typeof inspect.status === "string" ? inspect.status : inspect.status?.state;
|
|
677
634
|
}
|
|
678
635
|
function isMastraOwned(inspect, sandboxId) {
|
|
679
|
-
|
|
680
|
-
|
|
636
|
+
const labels = inspect.configuration?.labels;
|
|
637
|
+
return labels?.["mastra.sandbox"] === "true" && labels["mastra.sandbox.id"] === sandboxId;
|
|
681
638
|
}
|
|
682
639
|
function isMissingContainerMessage(message) {
|
|
683
|
-
|
|
640
|
+
return /not found|no such|does not exist|unknown container/i.test(message);
|
|
684
641
|
}
|
|
685
642
|
function validateTmpfsPaths(tmpfs) {
|
|
686
|
-
|
|
687
|
-
if (!entry.startsWith("/") || /[:,]/.test(entry)) {
|
|
688
|
-
throw new Error(
|
|
689
|
-
`Invalid Apple container tmpfs path "${entry}". Apple container --tmpfs accepts container paths only, for example "/tmp".`
|
|
690
|
-
);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
643
|
+
for (const entry of tmpfs) if (!entry.startsWith("/") || /[:,]/.test(entry)) throw new Error(`Invalid Apple container tmpfs path "${entry}". Apple container --tmpfs accepts container paths only, for example "/tmp".`);
|
|
693
644
|
}
|
|
694
645
|
function compactConfig(config) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
646
|
+
const result = {};
|
|
647
|
+
for (const [key, value] of Object.entries(config)) {
|
|
648
|
+
if (value === void 0) continue;
|
|
649
|
+
if (Array.isArray(value) && value.length === 0) continue;
|
|
650
|
+
if (isPlainRecord(value) && Object.keys(value).length === 0) continue;
|
|
651
|
+
result[key] = value;
|
|
652
|
+
}
|
|
653
|
+
return result;
|
|
703
654
|
}
|
|
704
655
|
function hashConfig(config) {
|
|
705
|
-
|
|
656
|
+
return (0, crypto.createHash)("sha256").update(stableStringify(compactConfig(config))).digest("hex").slice(0, 16);
|
|
706
657
|
}
|
|
707
658
|
function stableStringify(value) {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
if (isPlainRecord(value)) {
|
|
712
|
-
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(",")}}`;
|
|
713
|
-
}
|
|
714
|
-
return JSON.stringify(value);
|
|
659
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
660
|
+
if (isPlainRecord(value)) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(",")}}`;
|
|
661
|
+
return JSON.stringify(value);
|
|
715
662
|
}
|
|
716
663
|
function isPlainRecord(value) {
|
|
717
|
-
|
|
664
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
718
665
|
}
|
|
719
666
|
function delay(ms) {
|
|
720
|
-
|
|
667
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
721
668
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
image,
|
|
912
|
-
name,
|
|
913
|
-
command,
|
|
914
|
-
env,
|
|
915
|
-
volumes,
|
|
916
|
-
mounts,
|
|
917
|
-
network,
|
|
918
|
-
publishedPorts,
|
|
919
|
-
publishedSockets,
|
|
920
|
-
cpus,
|
|
921
|
-
memory,
|
|
922
|
-
platform,
|
|
923
|
-
arch,
|
|
924
|
-
os,
|
|
925
|
-
rosetta,
|
|
926
|
-
readonlyRootfs,
|
|
927
|
-
ssh,
|
|
928
|
-
init,
|
|
929
|
-
virtualization,
|
|
930
|
-
capAdd,
|
|
931
|
-
capDrop,
|
|
932
|
-
tmpfs,
|
|
933
|
-
dns,
|
|
934
|
-
dnsSearch,
|
|
935
|
-
noDns,
|
|
936
|
-
labels,
|
|
937
|
-
workingDir,
|
|
938
|
-
timeout,
|
|
939
|
-
deleteOnDestroy
|
|
940
|
-
});
|
|
941
|
-
}
|
|
669
|
+
//#endregion
|
|
670
|
+
//#region src/provider.ts
|
|
671
|
+
const appleContainerSandboxProvider = {
|
|
672
|
+
id: "apple-container",
|
|
673
|
+
name: "Apple Container Sandbox",
|
|
674
|
+
description: "Local OCI Linux container sandbox powered by Apple container",
|
|
675
|
+
configSchema: {
|
|
676
|
+
type: "object",
|
|
677
|
+
additionalProperties: false,
|
|
678
|
+
properties: {
|
|
679
|
+
id: {
|
|
680
|
+
type: "string",
|
|
681
|
+
description: "Stable sandbox ID used for reconnecting to the same Apple container."
|
|
682
|
+
},
|
|
683
|
+
image: {
|
|
684
|
+
type: "string",
|
|
685
|
+
description: "OCI image to use",
|
|
686
|
+
default: "node:22-slim"
|
|
687
|
+
},
|
|
688
|
+
name: {
|
|
689
|
+
type: "string",
|
|
690
|
+
description: "Apple container name. Defaults to the sandbox ID."
|
|
691
|
+
},
|
|
692
|
+
command: {
|
|
693
|
+
type: "array",
|
|
694
|
+
description: "Container init command. Must keep the container alive for exec-based command execution.",
|
|
695
|
+
items: { type: "string" }
|
|
696
|
+
},
|
|
697
|
+
env: {
|
|
698
|
+
type: "object",
|
|
699
|
+
description: "Environment variables",
|
|
700
|
+
additionalProperties: { type: "string" }
|
|
701
|
+
},
|
|
702
|
+
volumes: {
|
|
703
|
+
type: "object",
|
|
704
|
+
description: "Host-to-container bind mounts (host path -> container path)",
|
|
705
|
+
additionalProperties: { type: "string" }
|
|
706
|
+
},
|
|
707
|
+
mounts: {
|
|
708
|
+
type: "array",
|
|
709
|
+
description: "Raw Apple container --mount specs",
|
|
710
|
+
items: { type: "string" }
|
|
711
|
+
},
|
|
712
|
+
network: {
|
|
713
|
+
type: "string",
|
|
714
|
+
description: "Apple container network attachment spec"
|
|
715
|
+
},
|
|
716
|
+
publishedPorts: {
|
|
717
|
+
type: "array",
|
|
718
|
+
description: "Port publish specs",
|
|
719
|
+
items: { type: "string" }
|
|
720
|
+
},
|
|
721
|
+
publishedSockets: {
|
|
722
|
+
type: "array",
|
|
723
|
+
description: "Socket publish specs",
|
|
724
|
+
items: { type: "string" }
|
|
725
|
+
},
|
|
726
|
+
cpus: {
|
|
727
|
+
anyOf: [{ type: "number" }, { type: "string" }],
|
|
728
|
+
description: "Number of CPUs to allocate"
|
|
729
|
+
},
|
|
730
|
+
memory: {
|
|
731
|
+
type: "string",
|
|
732
|
+
description: "Memory allocation, for example 1G"
|
|
733
|
+
},
|
|
734
|
+
platform: {
|
|
735
|
+
type: "string",
|
|
736
|
+
description: "OCI platform, for example linux/arm64"
|
|
737
|
+
},
|
|
738
|
+
arch: {
|
|
739
|
+
type: "string",
|
|
740
|
+
description: "Image architecture for multi-arch images"
|
|
741
|
+
},
|
|
742
|
+
os: {
|
|
743
|
+
type: "string",
|
|
744
|
+
description: "Operating system for multi-platform images"
|
|
745
|
+
},
|
|
746
|
+
rosetta: {
|
|
747
|
+
type: "boolean",
|
|
748
|
+
description: "Enable Rosetta in the container",
|
|
749
|
+
default: false
|
|
750
|
+
},
|
|
751
|
+
readonlyRootfs: {
|
|
752
|
+
type: "boolean",
|
|
753
|
+
description: "Mount the container root filesystem as read-only",
|
|
754
|
+
default: false
|
|
755
|
+
},
|
|
756
|
+
ssh: {
|
|
757
|
+
type: "boolean",
|
|
758
|
+
description: "Forward the host SSH agent socket",
|
|
759
|
+
default: false
|
|
760
|
+
},
|
|
761
|
+
init: {
|
|
762
|
+
type: "boolean",
|
|
763
|
+
description: "Enable Apple's init process in the container",
|
|
764
|
+
default: true
|
|
765
|
+
},
|
|
766
|
+
virtualization: {
|
|
767
|
+
type: "boolean",
|
|
768
|
+
description: "Expose virtualization capabilities to the container",
|
|
769
|
+
default: false
|
|
770
|
+
},
|
|
771
|
+
capAdd: {
|
|
772
|
+
type: "array",
|
|
773
|
+
description: "Linux capabilities to add",
|
|
774
|
+
items: { type: "string" }
|
|
775
|
+
},
|
|
776
|
+
capDrop: {
|
|
777
|
+
type: "array",
|
|
778
|
+
description: "Linux capabilities to drop",
|
|
779
|
+
items: { type: "string" }
|
|
780
|
+
},
|
|
781
|
+
tmpfs: {
|
|
782
|
+
type: "array",
|
|
783
|
+
description: "tmpfs destination paths",
|
|
784
|
+
items: { type: "string" }
|
|
785
|
+
},
|
|
786
|
+
dns: {
|
|
787
|
+
type: "array",
|
|
788
|
+
description: "DNS nameserver IPs",
|
|
789
|
+
items: { type: "string" }
|
|
790
|
+
},
|
|
791
|
+
dnsSearch: {
|
|
792
|
+
type: "array",
|
|
793
|
+
description: "DNS search domains",
|
|
794
|
+
items: { type: "string" }
|
|
795
|
+
},
|
|
796
|
+
noDns: {
|
|
797
|
+
type: "boolean",
|
|
798
|
+
description: "Do not configure DNS in the container",
|
|
799
|
+
default: false
|
|
800
|
+
},
|
|
801
|
+
labels: {
|
|
802
|
+
type: "object",
|
|
803
|
+
description: "Container labels",
|
|
804
|
+
additionalProperties: { type: "string" }
|
|
805
|
+
},
|
|
806
|
+
workingDir: {
|
|
807
|
+
type: "string",
|
|
808
|
+
description: "Working directory inside the container",
|
|
809
|
+
default: "/workspace"
|
|
810
|
+
},
|
|
811
|
+
timeout: {
|
|
812
|
+
type: "number",
|
|
813
|
+
description: "Default command timeout in milliseconds",
|
|
814
|
+
default: 3e5
|
|
815
|
+
},
|
|
816
|
+
deleteOnDestroy: {
|
|
817
|
+
type: "boolean",
|
|
818
|
+
description: "Delete the Apple container on destroy",
|
|
819
|
+
default: true
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
},
|
|
823
|
+
createSandbox: (config) => {
|
|
824
|
+
const { id, image, name, command, env, volumes, mounts, network, publishedPorts, publishedSockets, cpus, memory, platform, arch, os, rosetta, readonlyRootfs, ssh, init, virtualization, capAdd, capDrop, tmpfs, dns, dnsSearch, noDns, labels, workingDir, timeout, deleteOnDestroy } = config;
|
|
825
|
+
return new AppleContainerSandbox({
|
|
826
|
+
id,
|
|
827
|
+
image,
|
|
828
|
+
name,
|
|
829
|
+
command,
|
|
830
|
+
env,
|
|
831
|
+
volumes,
|
|
832
|
+
mounts,
|
|
833
|
+
network,
|
|
834
|
+
publishedPorts,
|
|
835
|
+
publishedSockets,
|
|
836
|
+
cpus,
|
|
837
|
+
memory,
|
|
838
|
+
platform,
|
|
839
|
+
arch,
|
|
840
|
+
os,
|
|
841
|
+
rosetta,
|
|
842
|
+
readonlyRootfs,
|
|
843
|
+
ssh,
|
|
844
|
+
init,
|
|
845
|
+
virtualization,
|
|
846
|
+
capAdd,
|
|
847
|
+
capDrop,
|
|
848
|
+
tmpfs,
|
|
849
|
+
dns,
|
|
850
|
+
dnsSearch,
|
|
851
|
+
noDns,
|
|
852
|
+
labels,
|
|
853
|
+
workingDir,
|
|
854
|
+
timeout,
|
|
855
|
+
deleteOnDestroy
|
|
856
|
+
});
|
|
857
|
+
}
|
|
942
858
|
};
|
|
943
|
-
|
|
859
|
+
//#endregion
|
|
944
860
|
exports.AppleContainerSandbox = AppleContainerSandbox;
|
|
945
861
|
exports.DefaultAppleContainerCommandRunner = DefaultAppleContainerCommandRunner;
|
|
946
862
|
exports.appleContainerSandboxProvider = appleContainerSandboxProvider;
|
|
947
|
-
|
|
863
|
+
|
|
948
864
|
//# sourceMappingURL=index.cjs.map
|