@opengeni/runtime 4.6.0 → 4.7.0-canary.37090756480001
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/agent-instructions/modules/media.d.ts +3 -0
- package/dist/anthropic-messages.d.ts +13 -3
- package/dist/anthropic-request-error.d.ts +10 -0
- package/dist/assets/codemode-client.json +1 -1
- package/dist/{chunk-A22BKN4P.js → chunk-LJNCGUMB.js} +3 -3
- package/dist/chunk-LJNCGUMB.js.map +1 -0
- package/dist/{chunk-GTWKWJ67.js → chunk-P2OVGKDG.js} +505 -100
- package/dist/chunk-P2OVGKDG.js.map +1 -0
- package/dist/{chunk-D5DPVA2C.js → chunk-R25L27T3.js} +2047 -1275
- package/dist/chunk-R25L27T3.js.map +1 -0
- package/dist/claude-subscription-usage.d.ts +14 -4
- package/dist/context-compaction.d.ts +7 -7
- package/dist/index.d.ts +2 -0
- package/dist/index.js +13 -3
- package/dist/interaction-tools.d.ts +1 -1
- package/dist/mcp-network.js +1 -1
- package/dist/runtime-skills.d.ts +1 -0
- package/dist/sandbox/channel-a.d.ts +3 -0
- package/dist/sandbox/index.d.ts +3 -1
- package/dist/sandbox/index.js +7 -1
- package/dist/sandbox/provider-command-session.d.ts +21 -0
- package/dist/sandbox/providers/modal-command-argv.d.ts +4 -0
- package/dist/sandbox/providers/modal-command-control.d.ts +17 -5
- package/dist/sandbox/providers/modal-command-observation-errors.d.ts +3 -0
- package/dist/sandbox/providers/modal-command-raw-page.d.ts +100 -0
- package/dist/sandbox/providers/modal-command-router-wire.d.ts +17 -0
- package/dist/sandbox/routing/routing-session.d.ts +10 -0
- package/dist/sandbox/turn-tool-cancellation.d.ts +4 -0
- package/dist/workspace-tool-gateway.js +3 -3
- package/package.json +12 -12
- package/src/agent-instructions/PROMPT_CHANGELOG.md +23 -1
- package/src/agent-instructions/compose.ts +2 -0
- package/src/agent-instructions/modules/media.ts +20 -0
- package/src/agent-instructions/runtime-mechanics.ts +8 -0
- package/src/anthropic-messages.ts +223 -31
- package/src/anthropic-request-error.ts +45 -0
- package/src/bundled_default_skills/opengeni-client/SKILL.md +9 -7
- package/src/bundled_default_skills/opengeni-client/references/agent-recipes.md +1 -1
- package/src/bundled_default_skills/opengeni-client/references/api-workflows.md +61 -0
- package/src/bundled_default_skills/opengeni-client/references/compatibility-and-troubleshooting.md +86 -0
- package/src/bundled_default_skills/opengeni-client/references/data-tools-and-credentials.md +82 -0
- package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +32 -25
- package/src/bundled_default_skills/opengeni-client/references/external-users-and-connect.md +17 -0
- package/src/bundled_default_skills/opengeni-client/references/product-shapes-and-ui.md +156 -0
- package/src/bundled_schedule_skills/opengeni-schedules/SKILL.md +56 -0
- package/src/claude-subscription-usage.ts +55 -9
- package/src/context-compaction.ts +16 -9
- package/src/index.ts +85 -18
- package/src/interaction-tools.ts +113 -3
- package/src/lazy-tool-transport.ts +26 -10
- package/src/mcp-network.ts +4 -2
- package/src/model-provider-client.ts +11 -3
- package/src/model-provider-routing.ts +4 -0
- package/src/runtime-skills.ts +8 -0
- package/src/sandbox/channel-a.ts +3 -0
- package/src/sandbox/index.ts +11 -1
- package/src/sandbox/provider-command-session.ts +58 -0
- package/src/sandbox/provider-errors.ts +43 -9
- package/src/sandbox/providers/modal-command-argv.ts +20 -0
- package/src/sandbox/providers/modal-command-control.ts +422 -116
- package/src/sandbox/providers/modal-command-observation-errors.ts +65 -0
- package/src/sandbox/providers/modal-command-raw-page.ts +147 -0
- package/src/sandbox/providers/modal-command-router-wire.ts +104 -12
- package/src/sandbox/providers/modal-command-session.ts +26 -4
- package/src/sandbox/providers/modal-legacy-command-control.ts +2 -9
- package/src/sandbox/providers/modal-materialization-verification.ts +70 -6
- package/src/sandbox/routing/routing-session.ts +140 -41
- package/src/sandbox/run-credentials.ts +62 -19
- package/src/sandbox/turn-tool-cancellation.ts +159 -42
- package/dist/chunk-A22BKN4P.js.map +0 -1
- package/dist/chunk-D5DPVA2C.js.map +0 -1
- package/dist/chunk-GTWKWJ67.js.map +0 -1
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
assertShellEnvironmentName,
|
|
56
56
|
deserializeHostPathGrantRedactionMetadata,
|
|
57
57
|
deserializeManifest,
|
|
58
|
+
external_exports,
|
|
58
59
|
getRecordedExposedPortEndpoint,
|
|
59
60
|
getRunStateSessionTrustedConfig,
|
|
60
61
|
isDir,
|
|
@@ -113,6 +114,50 @@ var ProviderCommandStartOutcomeUnknownError = class extends Error {
|
|
|
113
114
|
this.name = "ProviderCommandStartOutcomeUnknownError";
|
|
114
115
|
}
|
|
115
116
|
};
|
|
117
|
+
var ProviderCommandInputOutcomeUnknownError = class extends Error {
|
|
118
|
+
constructor(command, byteOffset, byteLength2, cause) {
|
|
119
|
+
super(
|
|
120
|
+
"Provider command stdin outcome is unknown; the input was not resent. Do not resend stdin; inspect the original command with empty input.",
|
|
121
|
+
{ cause }
|
|
122
|
+
);
|
|
123
|
+
this.command = command;
|
|
124
|
+
this.byteOffset = byteOffset;
|
|
125
|
+
this.byteLength = byteLength2;
|
|
126
|
+
this.name = "ProviderCommandInputOutcomeUnknownError";
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
var ProviderCommandObservationUnavailableError = class extends Error {
|
|
130
|
+
constructor(command, cause, readRetryAllowed = true) {
|
|
131
|
+
super("Provider command observation unavailable; do not replay the invocation", { cause });
|
|
132
|
+
this.command = command;
|
|
133
|
+
this.readRetryAllowed = readRetryAllowed;
|
|
134
|
+
this.name = "ProviderCommandObservationUnavailableError";
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
function isProviderCommandObservationUnavailableError(error) {
|
|
138
|
+
const pending = [error];
|
|
139
|
+
const seen = /* @__PURE__ */ new Set();
|
|
140
|
+
for (let count = 0; pending.length && count < 32; count++) {
|
|
141
|
+
const current = pending.pop();
|
|
142
|
+
if (!current || typeof current !== "object" || seen.has(current)) continue;
|
|
143
|
+
seen.add(current);
|
|
144
|
+
if (current instanceof ProviderCommandObservationUnavailableError) return true;
|
|
145
|
+
try {
|
|
146
|
+
for (const key of ["cause", "error"]) {
|
|
147
|
+
const property = Object.getOwnPropertyDescriptor(current, key);
|
|
148
|
+
if (property && "value" in property) pending.push(property.value);
|
|
149
|
+
}
|
|
150
|
+
const errors = Object.getOwnPropertyDescriptor(current, "errors");
|
|
151
|
+
if (errors && "value" in errors && Array.isArray(errors.value) && errors.value.length <= 16)
|
|
152
|
+
for (let index = 0; index < errors.value.length; index++) {
|
|
153
|
+
const item = Object.getOwnPropertyDescriptor(errors.value, String(index));
|
|
154
|
+
if (item && "value" in item) pending.push(item.value);
|
|
155
|
+
}
|
|
156
|
+
} catch {
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
116
161
|
var admission = new AsyncLocalStorage();
|
|
117
162
|
var pendingSupervision = new AsyncLocalStorage();
|
|
118
163
|
function withPendingCommandSupervision(state, fn) {
|
|
@@ -152,6 +197,878 @@ function admittedProviderCommandHandle() {
|
|
|
152
197
|
// src/sandbox/index.ts
|
|
153
198
|
import { collectSandboxEnvironment, parseExposedPorts } from "@opengeni/config";
|
|
154
199
|
|
|
200
|
+
// src/sandbox/providers/modal-command-raw-page.ts
|
|
201
|
+
import { isDeepStrictEqual } from "util";
|
|
202
|
+
import { ModalRouterProviderCommand as ModalRouterProviderCommand2 } from "@opengeni/contracts";
|
|
203
|
+
|
|
204
|
+
// src/sandbox/providers/modal-legacy-command-control.ts
|
|
205
|
+
import { posix } from "path";
|
|
206
|
+
import { ModalClient } from "modal";
|
|
207
|
+
|
|
208
|
+
// src/sandbox/providers/modal-command-start-errors.ts
|
|
209
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
210
|
+
import { ModalRouterProviderCommand } from "@opengeni/contracts";
|
|
211
|
+
var boundaryBrand = Symbol.for("opengeni.modal.command-start.boundary.v1");
|
|
212
|
+
var invocationBrand = Symbol.for("opengeni.modal.command-start.invocation.v1");
|
|
213
|
+
var contextBrand = Symbol.for("opengeni.modal.command-start.context.v1");
|
|
214
|
+
var startSignal = new AsyncLocalStorage2();
|
|
215
|
+
function withModalCommandStartSignal(signal, operation) {
|
|
216
|
+
signal.throwIfAborted();
|
|
217
|
+
return startSignal.run(signal, operation);
|
|
218
|
+
}
|
|
219
|
+
function installModalCommandStartContext(modal) {
|
|
220
|
+
if (Object.getOwnPropertyDescriptor(modal, contextBrand)) return;
|
|
221
|
+
Object.defineProperty(modal, contextBrand, { value: () => startSignal.getStore() });
|
|
222
|
+
}
|
|
223
|
+
function modalCommandStartOwnData(value, key) {
|
|
224
|
+
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
225
|
+
return property && "value" in property ? property.value : void 0;
|
|
226
|
+
}
|
|
227
|
+
function modalCommandStartHasOwnAccessor(value, key) {
|
|
228
|
+
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
229
|
+
return !!property && !("value" in property);
|
|
230
|
+
}
|
|
231
|
+
function getModalCommandStartInvocation(error) {
|
|
232
|
+
const pending = [{ value: error, depth: 0 }];
|
|
233
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
234
|
+
let result = null;
|
|
235
|
+
let inspected = 0;
|
|
236
|
+
while (pending.length) {
|
|
237
|
+
if (++inspected > 64) return null;
|
|
238
|
+
const { value, depth } = pending.shift();
|
|
239
|
+
if (!value || typeof value !== "object" || seen.has(value)) continue;
|
|
240
|
+
if (depth > 8) return null;
|
|
241
|
+
seen.add(value);
|
|
242
|
+
try {
|
|
243
|
+
if (["cause", "error", "errors"].some((key) => modalCommandStartHasOwnAccessor(value, key)))
|
|
244
|
+
return null;
|
|
245
|
+
if (hasModalCommandStartBoundary(value, "outcome-unknown")) {
|
|
246
|
+
const descriptor = modalCommandStartOwnData(value, invocationBrand);
|
|
247
|
+
if (!descriptor || typeof descriptor !== "object" || !Object.isFrozen(descriptor))
|
|
248
|
+
return null;
|
|
249
|
+
const sandboxId = modalCommandStartOwnData(descriptor, "sandboxId");
|
|
250
|
+
const taskId = modalCommandStartOwnData(descriptor, "taskId");
|
|
251
|
+
const execId = modalCommandStartOwnData(descriptor, "execId");
|
|
252
|
+
const observe = modalCommandStartOwnData(descriptor, "observe");
|
|
253
|
+
const ptyProperty = Object.getOwnPropertyDescriptor(descriptor, "pty");
|
|
254
|
+
if (ptyProperty && (!("value" in ptyProperty) || typeof ptyProperty.value !== "boolean"))
|
|
255
|
+
return null;
|
|
256
|
+
if (typeof sandboxId !== "string" || !sandboxId || typeof taskId !== "string" || !taskId || typeof execId !== "string" || !execId || typeof observe !== "function")
|
|
257
|
+
return null;
|
|
258
|
+
if (result && result !== descriptor) return null;
|
|
259
|
+
result = descriptor;
|
|
260
|
+
}
|
|
261
|
+
const nested = [
|
|
262
|
+
modalCommandStartOwnData(value, "cause"),
|
|
263
|
+
modalCommandStartOwnData(value, "error")
|
|
264
|
+
].filter((child) => child !== void 0);
|
|
265
|
+
const errors = modalCommandStartOwnData(value, "errors");
|
|
266
|
+
if (errors !== void 0) {
|
|
267
|
+
if (!Array.isArray(errors)) return null;
|
|
268
|
+
const length = modalCommandStartOwnData(errors, "length");
|
|
269
|
+
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 1 || length > 32)
|
|
270
|
+
return null;
|
|
271
|
+
for (let index = 0; index < length; index++) {
|
|
272
|
+
const property = Object.getOwnPropertyDescriptor(errors, String(index));
|
|
273
|
+
if (!property || !("value" in property) || !property.value || typeof property.value !== "object")
|
|
274
|
+
return null;
|
|
275
|
+
nested.push(property.value);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (depth === 8 && nested.length) return null;
|
|
279
|
+
for (const child of nested) pending.push({ value: child, depth: depth + 1 });
|
|
280
|
+
} catch {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
function modalCommandStartRetainedError(error) {
|
|
287
|
+
if (error instanceof ProviderCommandStartOutcomeUnknownError) return error;
|
|
288
|
+
const invocation = getModalCommandStartInvocation(error);
|
|
289
|
+
if (!invocation) return error;
|
|
290
|
+
const cursor = () => ({ byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null });
|
|
291
|
+
const command = ModalRouterProviderCommand.safeParse({
|
|
292
|
+
kind: "modal-router-v1",
|
|
293
|
+
sandboxId: invocation.sandboxId,
|
|
294
|
+
taskId: invocation.taskId,
|
|
295
|
+
execId: invocation.execId,
|
|
296
|
+
...invocation.pty === void 0 ? {} : { pty: invocation.pty },
|
|
297
|
+
streams: { stdout: cursor(), stderr: cursor() }
|
|
298
|
+
});
|
|
299
|
+
return command.success ? new ProviderCommandStartOutcomeUnknownError(command.data, error) : error;
|
|
300
|
+
}
|
|
301
|
+
function hasModalCommandStartOutcomeUnknownBoundary(error) {
|
|
302
|
+
const pending = [{ value: error, depth: 0 }];
|
|
303
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
304
|
+
for (let inspected = 0; pending.length && inspected < 64; inspected++) {
|
|
305
|
+
const { value, depth } = pending.shift();
|
|
306
|
+
if (!value || typeof value !== "object" || seen.has(value)) continue;
|
|
307
|
+
seen.add(value);
|
|
308
|
+
if (hasModalCommandStartBoundary(value, "outcome-unknown")) return true;
|
|
309
|
+
if (depth >= 8) continue;
|
|
310
|
+
try {
|
|
311
|
+
for (const key of ["cause", "error"]) {
|
|
312
|
+
const nested = modalCommandStartOwnData(value, key);
|
|
313
|
+
if (nested !== void 0) pending.push({ value: nested, depth: depth + 1 });
|
|
314
|
+
}
|
|
315
|
+
const errors = modalCommandStartOwnData(value, "errors");
|
|
316
|
+
if (Array.isArray(errors))
|
|
317
|
+
for (let index = 0; index < Math.min(errors.length, 32); index++)
|
|
318
|
+
pending.push({
|
|
319
|
+
value: modalCommandStartOwnData(errors, String(index)),
|
|
320
|
+
depth: depth + 1
|
|
321
|
+
});
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
function modalCommandStartCleanupIsSafe(error) {
|
|
328
|
+
const pending = [{ value: error, depth: 0 }];
|
|
329
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
330
|
+
let inspected = 0;
|
|
331
|
+
while (pending.length) {
|
|
332
|
+
if (++inspected > 64) return false;
|
|
333
|
+
const { value, depth } = pending.shift();
|
|
334
|
+
if (!value || typeof value !== "object" && typeof value !== "function") continue;
|
|
335
|
+
if (seen.has(value)) continue;
|
|
336
|
+
if (depth > 8) return false;
|
|
337
|
+
seen.add(value);
|
|
338
|
+
try {
|
|
339
|
+
if (value instanceof ProviderCommandStartOutcomeUnknownError || hasModalCommandStartBoundary(value, "outcome-unknown") || [boundaryBrand, "cause", "error", "errors"].some(
|
|
340
|
+
(key) => modalCommandStartHasOwnAccessor(value, key)
|
|
341
|
+
))
|
|
342
|
+
return false;
|
|
343
|
+
const nested = [
|
|
344
|
+
modalCommandStartOwnData(value, "cause"),
|
|
345
|
+
modalCommandStartOwnData(value, "error")
|
|
346
|
+
].filter((child) => child !== void 0 && child !== null);
|
|
347
|
+
const errors = modalCommandStartOwnData(value, "errors");
|
|
348
|
+
if (errors !== void 0) {
|
|
349
|
+
if (!Array.isArray(errors)) return false;
|
|
350
|
+
const length = modalCommandStartOwnData(errors, "length");
|
|
351
|
+
if (typeof length !== "number" || !Number.isSafeInteger(length) || length > 32)
|
|
352
|
+
return false;
|
|
353
|
+
for (let index = 0; index < length; index++) {
|
|
354
|
+
const property = Object.getOwnPropertyDescriptor(errors, String(index));
|
|
355
|
+
if (!property || !("value" in property) || !property.value || typeof property.value !== "object" && typeof property.value !== "function")
|
|
356
|
+
return false;
|
|
357
|
+
nested.push(property.value);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (depth === 8 && nested.length) return false;
|
|
361
|
+
for (const child of nested) pending.push({ value: child, depth: depth + 1 });
|
|
362
|
+
} catch {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
function installModalCommandStartRetention(session) {
|
|
369
|
+
for (const name of [
|
|
370
|
+
"execCommand",
|
|
371
|
+
"applyManifest",
|
|
372
|
+
"materializeEntry",
|
|
373
|
+
"hydrateWorkspace",
|
|
374
|
+
"persistWorkspace",
|
|
375
|
+
"runDirectCommand",
|
|
376
|
+
"runAsCommandRunner"
|
|
377
|
+
]) {
|
|
378
|
+
const operation = Reflect.get(session, name);
|
|
379
|
+
if (typeof operation !== "function") continue;
|
|
380
|
+
Reflect.set(session, name, async function(...args) {
|
|
381
|
+
try {
|
|
382
|
+
return await operation.apply(session, args);
|
|
383
|
+
} catch (error) {
|
|
384
|
+
throw modalCommandStartRetainedError(error);
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function hasModalCommandStartBoundary(error, kind) {
|
|
390
|
+
if (!error || typeof error !== "object") return false;
|
|
391
|
+
try {
|
|
392
|
+
const property = Object.getOwnPropertyDescriptor(error, boundaryBrand);
|
|
393
|
+
return property?.value === kind && property.writable === false && property.configurable === false;
|
|
394
|
+
} catch {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
var ModalCommandStartOutcomeUnknownError = class extends Error {
|
|
399
|
+
constructor(taskId, execId, cause) {
|
|
400
|
+
super("Modal command Start outcome unknown; do not replay this invocation", { cause });
|
|
401
|
+
this.taskId = taskId;
|
|
402
|
+
this.execId = execId;
|
|
403
|
+
this.name = "CommandStartOutcomeUnknownError";
|
|
404
|
+
Object.defineProperty(this, boundaryBrand, { value: "outcome-unknown" });
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
// src/sandbox/providers/modal-legacy-command-control.ts
|
|
409
|
+
import { status as status2 } from "@grpc/grpc-js";
|
|
410
|
+
|
|
411
|
+
// src/sandbox/providers/modal-command-router-wire.ts
|
|
412
|
+
import { Client, Metadata, credentials, status } from "@grpc/grpc-js";
|
|
413
|
+
import protobuf from "protobufjs";
|
|
414
|
+
var modalRouterWire = protobuf.parse(`syntax = "proto3";
|
|
415
|
+
message Identity { string task_id = 1; string exec_id = 2; }
|
|
416
|
+
message Pty {
|
|
417
|
+
bool enabled = 1; uint32 winsz_rows = 2; uint32 winsz_cols = 3;
|
|
418
|
+
string env_term = 4; string env_colorterm = 5; string env_term_program = 6;
|
|
419
|
+
int32 pty_type = 7; bool no_terminate_on_idle_stdin = 8;
|
|
420
|
+
}
|
|
421
|
+
message Start {
|
|
422
|
+
string task_id = 1; string exec_id = 2; repeated string command_args = 3;
|
|
423
|
+
int32 stdout_config = 4; int32 stderr_config = 5;
|
|
424
|
+
optional uint32 timeout_secs = 6; optional string workdir = 7;
|
|
425
|
+
repeated string secret_ids = 8; optional Pty pty_info = 9;
|
|
426
|
+
bool runtime_debug = 10; string container_id = 11; map<string,string> env = 12;
|
|
427
|
+
}
|
|
428
|
+
message Read {
|
|
429
|
+
string task_id = 1; string exec_id = 2; uint64 offset = 3; int32 file_descriptor = 4;
|
|
430
|
+
}
|
|
431
|
+
message Data { bytes data = 1; }
|
|
432
|
+
message Poll { optional int32 code = 1; optional int32 signal = 2; }
|
|
433
|
+
message Write {
|
|
434
|
+
string task_id = 1; string exec_id = 2; uint64 offset = 3; bytes data = 4; bool eof = 5;
|
|
435
|
+
}
|
|
436
|
+
message Empty {}
|
|
437
|
+
`).root;
|
|
438
|
+
var prefix = "/modal.task_command_router.TaskCommandRouter/";
|
|
439
|
+
var MODAL_ROUTER_READ_PAGE_BYTES = 1024 * 1024;
|
|
440
|
+
var maxWireBytes = 4 * 1024 * 1024;
|
|
441
|
+
var ModalCommandStartRejectedError = class extends ProviderCommandStartRejectedError {
|
|
442
|
+
constructor(code, cause) {
|
|
443
|
+
super(cause);
|
|
444
|
+
this.code = code;
|
|
445
|
+
this.name = "ModalCommandStartRejectedError";
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
var ModalCommandStartPreDispatchUnavailableError = class _ModalCommandStartPreDispatchUnavailableError extends Error {
|
|
449
|
+
constructor(cause) {
|
|
450
|
+
super("Modal command router was not ready before Start dispatch", { cause });
|
|
451
|
+
this.name = "ModalCommandStartPreDispatchUnavailableError";
|
|
452
|
+
}
|
|
453
|
+
/** The supplied operation must contain only read-only preparation, never
|
|
454
|
+
* Start itself. Its transport failure therefore proves non-dispatch. */
|
|
455
|
+
static async beforeDispatch(operation, signal) {
|
|
456
|
+
signal?.throwIfAborted();
|
|
457
|
+
try {
|
|
458
|
+
return await operation();
|
|
459
|
+
} catch (error) {
|
|
460
|
+
signal?.throwIfAborted();
|
|
461
|
+
const code = error?.code;
|
|
462
|
+
if (error instanceof Error && (code === status.UNAVAILABLE || code === status.DEADLINE_EXCEEDED))
|
|
463
|
+
throw new _ModalCommandStartPreDispatchUnavailableError(error);
|
|
464
|
+
throw error;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
static async ensureReady(client, signal) {
|
|
468
|
+
signal?.throwIfAborted();
|
|
469
|
+
await new Promise((resolve7, reject) => {
|
|
470
|
+
let settled = false;
|
|
471
|
+
const finish = (error) => {
|
|
472
|
+
if (settled) return;
|
|
473
|
+
settled = true;
|
|
474
|
+
signal?.removeEventListener("abort", abort);
|
|
475
|
+
if (signal?.aborted) reject(signal.reason);
|
|
476
|
+
else if (error) reject(new _ModalCommandStartPreDispatchUnavailableError(error));
|
|
477
|
+
else resolve7();
|
|
478
|
+
};
|
|
479
|
+
const abort = () => finish();
|
|
480
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
481
|
+
client.waitForReady(Date.now() + 5e3, finish);
|
|
482
|
+
if (signal?.aborted) abort();
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
var ModalCommandStartNotDispatchedError = class extends Error {
|
|
487
|
+
constructor(cause) {
|
|
488
|
+
super(cause instanceof Error ? cause.message : "Modal command Start was never dispatched", {
|
|
489
|
+
cause
|
|
490
|
+
});
|
|
491
|
+
this.name = "ModalCommandStartNotDispatchedError";
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
function prepareStartRequest(request) {
|
|
495
|
+
const { taskId, execId, commandArgs, workdir, env, ptyInfo } = request;
|
|
496
|
+
if (!taskId || !execId || !Array.isArray(commandArgs) || !commandArgs.length || typeof workdir !== "string" || !env || typeof env !== "object" || Array.isArray(env))
|
|
497
|
+
throw new Error("Invalid Modal command Start request");
|
|
498
|
+
const snapshot = {
|
|
499
|
+
taskId,
|
|
500
|
+
execId,
|
|
501
|
+
commandArgs: [...commandArgs],
|
|
502
|
+
workdir,
|
|
503
|
+
env: { ...env },
|
|
504
|
+
...ptyInfo ? {
|
|
505
|
+
ptyInfo: {
|
|
506
|
+
enabled: ptyInfo.enabled,
|
|
507
|
+
winszRows: ptyInfo.winszRows,
|
|
508
|
+
winszCols: ptyInfo.winszCols,
|
|
509
|
+
envTerm: ptyInfo.envTerm,
|
|
510
|
+
ptyType: ptyInfo.ptyType,
|
|
511
|
+
noTerminateOnIdleStdin: ptyInfo.noTerminateOnIdleStdin
|
|
512
|
+
}
|
|
513
|
+
} : {},
|
|
514
|
+
stdoutConfig: 1,
|
|
515
|
+
stderrConfig: 1
|
|
516
|
+
};
|
|
517
|
+
if (modalRouterWire.lookupType("Start").verify(snapshot))
|
|
518
|
+
throw new Error("Invalid Modal command Start request");
|
|
519
|
+
if (encode("Start", snapshot).length > maxWireBytes)
|
|
520
|
+
throw new Error("Modal command Start request exceeds the wire limit");
|
|
521
|
+
Object.freeze(snapshot.commandArgs);
|
|
522
|
+
Object.freeze(snapshot.env);
|
|
523
|
+
if (snapshot.ptyInfo) Object.freeze(snapshot.ptyInfo);
|
|
524
|
+
return Object.freeze(snapshot);
|
|
525
|
+
}
|
|
526
|
+
function encode(type, value) {
|
|
527
|
+
const codec = modalRouterWire.lookupType(type);
|
|
528
|
+
return Buffer.from(codec.encode(codec.fromObject(value)).finish());
|
|
529
|
+
}
|
|
530
|
+
var ModalCommandRouterWire = class {
|
|
531
|
+
client;
|
|
532
|
+
metadata;
|
|
533
|
+
#preparedStarts = /* @__PURE__ */ new WeakMap();
|
|
534
|
+
closed = false;
|
|
535
|
+
constructor(access, trustedRoots) {
|
|
536
|
+
const url = new URL(access.url);
|
|
537
|
+
if (url.protocol !== "https:" || url.username || url.password || !access.jwt)
|
|
538
|
+
throw new Error("Modal command router requires authenticated TLS");
|
|
539
|
+
this.client = new Client(
|
|
540
|
+
`${url.hostname}:${url.port || "443"}`,
|
|
541
|
+
credentials.createSsl(trustedRoots),
|
|
542
|
+
{
|
|
543
|
+
"grpc.max_receive_message_length": maxWireBytes,
|
|
544
|
+
"grpc.max_send_message_length": maxWireBytes,
|
|
545
|
+
"grpc.enable_retries": 0,
|
|
546
|
+
// The HTTP/2 default 64 KiB window caps one read at 64 KiB per round
|
|
547
|
+
// trip. Two pages lets stdout and stderr each fill a page in one trip
|
|
548
|
+
// while bounding bytes discarded when a full read cancels its stream.
|
|
549
|
+
"grpc-node.flow_control_window": 2 * MODAL_ROUTER_READ_PAGE_BYTES
|
|
550
|
+
}
|
|
551
|
+
);
|
|
552
|
+
this.metadata = new Metadata();
|
|
553
|
+
this.metadata.set("authorization", `Bearer ${access.jwt}`);
|
|
554
|
+
}
|
|
555
|
+
close() {
|
|
556
|
+
this.closed = true;
|
|
557
|
+
this.client.close();
|
|
558
|
+
}
|
|
559
|
+
async unary(method, requestType, responseType, request, signal) {
|
|
560
|
+
signal?.throwIfAborted();
|
|
561
|
+
if (this.closed) throw new Error("Modal command router is closed");
|
|
562
|
+
return await new Promise((resolve7, reject) => {
|
|
563
|
+
const call = this.client.makeUnaryRequest(
|
|
564
|
+
prefix + method,
|
|
565
|
+
(value) => encode(requestType, value),
|
|
566
|
+
(bytes) => modalRouterWire.lookupType(responseType).decode(bytes),
|
|
567
|
+
request,
|
|
568
|
+
this.metadata,
|
|
569
|
+
{ deadline: Date.now() + 3e4 },
|
|
570
|
+
(error, result) => {
|
|
571
|
+
signal?.removeEventListener("abort", abort);
|
|
572
|
+
if (signal?.aborted) reject(signal.reason);
|
|
573
|
+
else if (error) reject(error);
|
|
574
|
+
else if (result) resolve7(result);
|
|
575
|
+
else reject(new Error("Modal command router returned no response"));
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
const abort = () => call.cancel();
|
|
579
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
580
|
+
if (signal?.aborted) abort();
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
/** Read-only transport preparation. It sends neither Start nor stdin and
|
|
584
|
+
* does not invoke a caller's dispatch/admission callback. Prevalidation is not
|
|
585
|
+
* wire proof: gRPC still serializes at RPC invocation after dispatch begins. */
|
|
586
|
+
async prepareStart(request, signal) {
|
|
587
|
+
try {
|
|
588
|
+
signal?.throwIfAborted();
|
|
589
|
+
if (this.closed) throw new Error("Modal command router is closed");
|
|
590
|
+
const snapshot = prepareStartRequest(request);
|
|
591
|
+
await ModalCommandStartPreDispatchUnavailableError.ensureReady(this.client, signal);
|
|
592
|
+
signal?.throwIfAborted();
|
|
593
|
+
if (this.closed) throw new Error("Modal command router is closed");
|
|
594
|
+
const prepared = Object.freeze({
|
|
595
|
+
taskId: snapshot.taskId,
|
|
596
|
+
execId: snapshot.execId
|
|
597
|
+
});
|
|
598
|
+
this.#preparedStarts.set(prepared, { request: snapshot, spent: false });
|
|
599
|
+
return prepared;
|
|
600
|
+
} catch (error) {
|
|
601
|
+
if (this.closed)
|
|
602
|
+
throw new ModalCommandStartNotDispatchedError(
|
|
603
|
+
new Error("Modal command router is closed", { cause: error })
|
|
604
|
+
);
|
|
605
|
+
if (error instanceof ModalCommandStartPreDispatchUnavailableError) throw error;
|
|
606
|
+
throw new ModalCommandStartNotDispatchedError(error);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
/** No readiness, route lookup or retry here. Consume the authentic local
|
|
610
|
+
* handle synchronously before RPC, including when cancellation/closure wins.
|
|
611
|
+
* Once spent it never resets, even if no acknowledgement was received. */
|
|
612
|
+
async dispatchPreparedStart(prepared, signal) {
|
|
613
|
+
const entry = this.#preparedStarts.get(prepared);
|
|
614
|
+
if (!entry || entry.spent)
|
|
615
|
+
throw new Error("Invalid or consumed Modal prepared Start handle");
|
|
616
|
+
entry.spent = true;
|
|
617
|
+
try {
|
|
618
|
+
signal?.throwIfAborted();
|
|
619
|
+
if (this.closed) throw new Error("Modal command router is closed");
|
|
620
|
+
} catch (error) {
|
|
621
|
+
throw new ModalCommandStartNotDispatchedError(error);
|
|
622
|
+
}
|
|
623
|
+
const request = entry.request;
|
|
624
|
+
try {
|
|
625
|
+
await this.unary("TaskExecStart", "Start", "Empty", request, signal);
|
|
626
|
+
} catch (error) {
|
|
627
|
+
const code = error?.code;
|
|
628
|
+
if (typeof code === "number" && [
|
|
629
|
+
status.INVALID_ARGUMENT,
|
|
630
|
+
status.NOT_FOUND,
|
|
631
|
+
status.PERMISSION_DENIED,
|
|
632
|
+
status.UNAUTHENTICATED,
|
|
633
|
+
status.UNIMPLEMENTED
|
|
634
|
+
].includes(code))
|
|
635
|
+
throw new ModalCommandStartRejectedError(code, error);
|
|
636
|
+
throw new ModalCommandStartOutcomeUnknownError(request.taskId, request.execId, error);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
async start(request, signal) {
|
|
640
|
+
const prepared = await this.prepareStart(request, signal);
|
|
641
|
+
await this.dispatchPreparedStart(prepared, signal);
|
|
642
|
+
}
|
|
643
|
+
async write(identity, offset, data, signal) {
|
|
644
|
+
if (!Number.isSafeInteger(offset) || offset < 0)
|
|
645
|
+
throw new Error("Invalid Modal stdin byte offset");
|
|
646
|
+
await this.unary(
|
|
647
|
+
"TaskExecStdinWrite",
|
|
648
|
+
"Write",
|
|
649
|
+
"Empty",
|
|
650
|
+
{ ...identity, offset, data, eof: false },
|
|
651
|
+
signal
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
async poll(identity, signal) {
|
|
655
|
+
const value = await this.unary("TaskExecPoll", "Identity", "Poll", identity, signal);
|
|
656
|
+
const decoded = modalRouterWire.lookupType("Poll").toObject(value);
|
|
657
|
+
if (decoded.code !== void 0) return decoded.code;
|
|
658
|
+
if (decoded.signal !== void 0) return 128 + decoded.signal;
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
async read(identity, stream, offset, waitMs, signal) {
|
|
662
|
+
signal?.throwIfAborted();
|
|
663
|
+
if (this.closed) throw new Error("Modal command router is closed");
|
|
664
|
+
if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isFinite(waitMs) || waitMs < 0 || waitMs > 5e4)
|
|
665
|
+
throw new Error("Invalid Modal output read bounds");
|
|
666
|
+
const chunks = [];
|
|
667
|
+
let length = 0;
|
|
668
|
+
let limited = false;
|
|
669
|
+
return await new Promise((resolve7, reject) => {
|
|
670
|
+
const call = this.client.makeServerStreamRequest(
|
|
671
|
+
prefix + "TaskExecStdioRead",
|
|
672
|
+
(value) => encode("Read", value),
|
|
673
|
+
(bytes) => modalRouterWire.lookupType("Data").decode(bytes),
|
|
674
|
+
{ ...identity, offset, fileDescriptor: stream === "stdout" ? 0 : 1 },
|
|
675
|
+
this.metadata,
|
|
676
|
+
{ deadline: Date.now() + Math.max(1, waitMs) }
|
|
677
|
+
);
|
|
678
|
+
const abort = () => call.cancel();
|
|
679
|
+
const finish = (eof, error) => {
|
|
680
|
+
signal?.removeEventListener("abort", abort);
|
|
681
|
+
if (signal?.aborted) reject(signal.reason);
|
|
682
|
+
else if (error) reject(error);
|
|
683
|
+
else resolve7({ bytes: Buffer.concat(chunks, length), eof });
|
|
684
|
+
};
|
|
685
|
+
call.on("data", (value) => {
|
|
686
|
+
if (limited) return;
|
|
687
|
+
const part = Buffer.from(value.data).subarray(0, MODAL_ROUTER_READ_PAGE_BYTES - length);
|
|
688
|
+
if (part.length) {
|
|
689
|
+
chunks.push(part);
|
|
690
|
+
length += part.length;
|
|
691
|
+
}
|
|
692
|
+
if (length === MODAL_ROUTER_READ_PAGE_BYTES) {
|
|
693
|
+
limited = true;
|
|
694
|
+
call.cancel();
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
call.once("error", (error) => {
|
|
698
|
+
if (limited && error.code === status.CANCELLED || error.code === status.DEADLINE_EXCEEDED)
|
|
699
|
+
finish(false);
|
|
700
|
+
else finish(false, error);
|
|
701
|
+
});
|
|
702
|
+
call.once("end", () => finish(!limited));
|
|
703
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
704
|
+
if (signal?.aborted) abort();
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
// src/sandbox/providers/modal-legacy-command-control.ts
|
|
710
|
+
import { ModalLegacyProviderCommand } from "@opengeni/contracts";
|
|
711
|
+
|
|
712
|
+
// src/sandbox/providers/modal-command-argv.ts
|
|
713
|
+
function modalCommandArgv(args) {
|
|
714
|
+
const command = [
|
|
715
|
+
args.shell ?? "/bin/sh",
|
|
716
|
+
args.shell && (args.login ?? true) ? "-lc" : "-c",
|
|
717
|
+
args.cmd
|
|
718
|
+
];
|
|
719
|
+
if (!args.runAs) return command;
|
|
720
|
+
return [
|
|
721
|
+
"/bin/sh",
|
|
722
|
+
"-c",
|
|
723
|
+
`user=$1; shift; if [ "$(id -u)" = "$user" ] || [ "$(id -un 2>/dev/null)" = "$user" ]; then exec "$@"; elif [ "$(id -u)" = 0 ]; then exec su -s /bin/sh -c 'exec "$@"' -- "$user" sh "$@"; else exec sudo -n -u "$user" -- "$@"; fi`,
|
|
724
|
+
"opengeni-run-as",
|
|
725
|
+
args.runAs,
|
|
726
|
+
...command
|
|
727
|
+
];
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// src/sandbox/providers/modal-legacy-command-control.ts
|
|
731
|
+
var modalCommandAbortMiddleware = async function* (call, options) {
|
|
732
|
+
options.signal?.throwIfAborted();
|
|
733
|
+
return yield* call.next(call.request, options);
|
|
734
|
+
};
|
|
735
|
+
var ModalClientBase = ModalClient;
|
|
736
|
+
var ModalCommandClient = class extends ModalClientBase {
|
|
737
|
+
retryMiddleware() {
|
|
738
|
+
return modalCommandAbortMiddleware;
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
var controlClients = /* @__PURE__ */ new WeakMap();
|
|
742
|
+
function commandControlPlane(client) {
|
|
743
|
+
if (!client.profile) return client.cpClient;
|
|
744
|
+
if (typeof Reflect.get(ModalClient.prototype, "retryMiddleware") !== "function")
|
|
745
|
+
throw new Error("Verified Modal command cancellation contract is unavailable");
|
|
746
|
+
let controlled = controlClients.get(client);
|
|
747
|
+
if (!controlled) {
|
|
748
|
+
const profile = client.profile;
|
|
749
|
+
if (!profile.tokenId || !profile.tokenSecret)
|
|
750
|
+
throw new Error("Modal command control requires its original authenticated profile");
|
|
751
|
+
controlled = new ModalCommandClient({
|
|
752
|
+
tokenId: profile.tokenId,
|
|
753
|
+
tokenSecret: profile.tokenSecret,
|
|
754
|
+
endpoint: profile.serverUrl,
|
|
755
|
+
environment: profile.environment ?? "",
|
|
756
|
+
...profile.maxThrottleWaitSecs !== void 0 ? { maxThrottleWaitSecs: profile.maxThrottleWaitSecs } : {},
|
|
757
|
+
...client.logger ? { logger: client.logger } : {}
|
|
758
|
+
});
|
|
759
|
+
controlClients.set(client, controlled);
|
|
760
|
+
}
|
|
761
|
+
return controlled.cpClient;
|
|
762
|
+
}
|
|
763
|
+
function decodePage(prior, input, terminal) {
|
|
764
|
+
const bytes = Buffer.concat([Buffer.from(prior, "base64"), ...input]);
|
|
765
|
+
let boundary = bytes.length;
|
|
766
|
+
if (!terminal) {
|
|
767
|
+
for (let start = Math.max(0, bytes.length - 3); start < bytes.length; start++) {
|
|
768
|
+
const first = bytes[start];
|
|
769
|
+
const width = first >= 194 && first <= 223 ? 2 : first >= 224 && first <= 239 ? 3 : first >= 240 && first <= 244 ? 4 : 0;
|
|
770
|
+
if (!width || bytes.length - start >= width) continue;
|
|
771
|
+
const suffix = bytes.subarray(start + 1);
|
|
772
|
+
if (!suffix.every((byte) => byte >= 128 && byte <= 191)) continue;
|
|
773
|
+
const second = suffix[0];
|
|
774
|
+
if (second !== void 0 && (first === 224 && second < 160 || first === 237 && second > 159 || first === 240 && second < 144 || first === 244 && second > 143))
|
|
775
|
+
continue;
|
|
776
|
+
boundary = start;
|
|
777
|
+
break;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
return {
|
|
781
|
+
text: bytes.subarray(0, boundary).toString("utf8"),
|
|
782
|
+
remainder: bytes.subarray(boundary).toString("base64")
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
var ModalCommandControl = class _ModalCommandControl {
|
|
786
|
+
constructor(client, sandboxIdentity, root, environment = {}) {
|
|
787
|
+
this.client = client;
|
|
788
|
+
this.sandboxIdentity = sandboxIdentity;
|
|
789
|
+
this.root = root;
|
|
790
|
+
this.environment = environment;
|
|
791
|
+
}
|
|
792
|
+
static forSandbox(client, sandboxId, root, environment = {}) {
|
|
793
|
+
if (client.version() !== "0.9.0")
|
|
794
|
+
throw new Error("Modal command control requires the verified 0.9.0 SDK contract");
|
|
795
|
+
return new _ModalCommandControl(commandControlPlane(client), sandboxId, root, environment);
|
|
796
|
+
}
|
|
797
|
+
get sandboxId() {
|
|
798
|
+
return typeof this.sandboxIdentity === "function" ? this.sandboxIdentity() : this.sandboxIdentity;
|
|
799
|
+
}
|
|
800
|
+
async start(args, signal) {
|
|
801
|
+
signal?.throwIfAborted();
|
|
802
|
+
const workdir = posix.resolve(this.root, args.workdir ?? this.root);
|
|
803
|
+
if (workdir !== this.root && !workdir.startsWith(`${this.root.replace(/\/$/u, "")}/`))
|
|
804
|
+
throw new Error("Command workdir is outside the sandbox workspace");
|
|
805
|
+
const sandboxId = this.sandboxId;
|
|
806
|
+
const task = await ModalCommandStartPreDispatchUnavailableError.beforeDispatch(
|
|
807
|
+
() => this.client.sandboxGetTaskId({ sandboxId }, signal ? { signal } : void 0),
|
|
808
|
+
signal
|
|
809
|
+
);
|
|
810
|
+
if (!task.taskId || task.taskResult) throw new Error("Modal command task is unavailable");
|
|
811
|
+
if (sandboxId !== this.sandboxId)
|
|
812
|
+
throw new Error("Modal sandbox changed during command preparation");
|
|
813
|
+
let command = modalCommandArgv(args);
|
|
814
|
+
const environment = typeof this.environment === "function" ? this.environment() : this.environment;
|
|
815
|
+
if (Object.keys(environment).length) {
|
|
816
|
+
command = [
|
|
817
|
+
"/usr/bin/env",
|
|
818
|
+
"--",
|
|
819
|
+
...Object.entries(environment).map(([key, value]) => `${key}=${value}`),
|
|
820
|
+
...command
|
|
821
|
+
];
|
|
822
|
+
}
|
|
823
|
+
const result = await this.client.containerExec(
|
|
824
|
+
{
|
|
825
|
+
taskId: task.taskId,
|
|
826
|
+
command,
|
|
827
|
+
terminateContainerOnExit: false,
|
|
828
|
+
runtimeDebug: false,
|
|
829
|
+
stdoutOutput: 2,
|
|
830
|
+
stderrOutput: 2,
|
|
831
|
+
timeoutSecs: 0,
|
|
832
|
+
workdir,
|
|
833
|
+
secretIds: [],
|
|
834
|
+
...args.tty ? {
|
|
835
|
+
ptyInfo: {
|
|
836
|
+
enabled: true,
|
|
837
|
+
winszRows: 24,
|
|
838
|
+
winszCols: 80,
|
|
839
|
+
envTerm: "xterm",
|
|
840
|
+
envColorterm: "",
|
|
841
|
+
envTermProgram: "",
|
|
842
|
+
ptyType: 1,
|
|
843
|
+
noTerminateOnIdleStdin: true
|
|
844
|
+
}
|
|
845
|
+
} : {}
|
|
846
|
+
},
|
|
847
|
+
{ retries: 0, ...signal ? { signal } : {} }
|
|
848
|
+
).catch((error) => {
|
|
849
|
+
const code = error?.code;
|
|
850
|
+
if (typeof code === "number" && [
|
|
851
|
+
status2.INVALID_ARGUMENT,
|
|
852
|
+
status2.NOT_FOUND,
|
|
853
|
+
status2.PERMISSION_DENIED,
|
|
854
|
+
status2.UNAUTHENTICATED,
|
|
855
|
+
status2.UNIMPLEMENTED
|
|
856
|
+
].includes(code))
|
|
857
|
+
throw new ProviderCommandStartRejectedError(error);
|
|
858
|
+
throw new ModalCommandStartOutcomeUnknownError(task.taskId, "", error);
|
|
859
|
+
});
|
|
860
|
+
if (!result.execId)
|
|
861
|
+
throw new ModalCommandStartOutcomeUnknownError(
|
|
862
|
+
task.taskId,
|
|
863
|
+
"",
|
|
864
|
+
new Error("Modal command start returned no execution identity")
|
|
865
|
+
);
|
|
866
|
+
return {
|
|
867
|
+
kind: "modal-control-v1",
|
|
868
|
+
sandboxId,
|
|
869
|
+
taskId: task.taskId,
|
|
870
|
+
execId: result.execId,
|
|
871
|
+
...args.tty ? { pty: true } : {},
|
|
872
|
+
streams: {
|
|
873
|
+
stdout: { batchIndex: 0, utf8Remainder: "", exitCode: null },
|
|
874
|
+
stderr: { batchIndex: 0, utf8Remainder: "", exitCode: null }
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
async read(command, yieldTimeMs, signal) {
|
|
879
|
+
return this.readOutput(command, yieldTimeMs, signal);
|
|
880
|
+
}
|
|
881
|
+
/** Fixed internal probes own their cancellation controller and must drain
|
|
882
|
+
* both reads before relinquishing the surrounding provider-operation gate.
|
|
883
|
+
* Retained-command readers keep their existing signal/receipt contract.
|
|
884
|
+
*/
|
|
885
|
+
async readProbe(command, yieldTimeMs, cancellation) {
|
|
886
|
+
return this.readOutput(
|
|
887
|
+
command,
|
|
888
|
+
yieldTimeMs,
|
|
889
|
+
cancellation.signal,
|
|
890
|
+
(error) => cancellation.abort(error)
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
async readOutput(command, yieldTimeMs, signal, cancelSiblings) {
|
|
894
|
+
signal?.throwIfAborted();
|
|
895
|
+
this.assertIdentity(command);
|
|
896
|
+
const next = structuredClone(command);
|
|
897
|
+
let failure;
|
|
898
|
+
const reads = ["stdout", "stderr"].map(async (stream) => {
|
|
899
|
+
const cursor = command.streams[stream];
|
|
900
|
+
if (cursor.exitCode !== null) return null;
|
|
901
|
+
const descriptor = stream === "stdout" ? 1 : 2;
|
|
902
|
+
for await (const batch of this.client.containerExecGetOutput(
|
|
903
|
+
{
|
|
904
|
+
execId: command.execId,
|
|
905
|
+
timeout: Math.max(0, yieldTimeMs) / 1e3,
|
|
906
|
+
lastBatchIndex: cursor.batchIndex,
|
|
907
|
+
fileDescriptor: descriptor,
|
|
908
|
+
getRawBytes: true
|
|
909
|
+
},
|
|
910
|
+
signal ? { signal } : void 0
|
|
911
|
+
)) {
|
|
912
|
+
if (batch.batchIndex <= cursor.batchIndex) continue;
|
|
913
|
+
if (!Number.isSafeInteger(batch.batchIndex))
|
|
914
|
+
throw new Error("Invalid Modal output cursor");
|
|
915
|
+
const terminal = batch.exitCode !== void 0;
|
|
916
|
+
if (terminal && !Number.isSafeInteger(batch.exitCode))
|
|
917
|
+
throw new Error("Invalid Modal exit status");
|
|
918
|
+
const decoded = decodePage(
|
|
919
|
+
cursor.utf8Remainder,
|
|
920
|
+
batch.items.filter((item) => item.fileDescriptor === descriptor).map((item) => item.messageBytes),
|
|
921
|
+
terminal
|
|
922
|
+
);
|
|
923
|
+
next.streams[stream] = {
|
|
924
|
+
batchIndex: batch.batchIndex,
|
|
925
|
+
utf8Remainder: decoded.remainder,
|
|
926
|
+
exitCode: terminal ? batch.exitCode : null
|
|
927
|
+
};
|
|
928
|
+
return {
|
|
929
|
+
stream,
|
|
930
|
+
chunkId: `modal:${command.execId}:${stream}:${cursor.batchIndex}:${batch.batchIndex}`,
|
|
931
|
+
text: decoded.text
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
return null;
|
|
935
|
+
}).map(
|
|
936
|
+
(read) => !cancelSiblings ? read : read.catch((error) => {
|
|
937
|
+
failure ??= { error };
|
|
938
|
+
cancelSiblings(error);
|
|
939
|
+
throw error;
|
|
940
|
+
})
|
|
941
|
+
);
|
|
942
|
+
const pages = cancelSiblings ? await Promise.allSettled(reads).then((results) => {
|
|
943
|
+
if (failure) throw failure.error;
|
|
944
|
+
return results.map((result) => {
|
|
945
|
+
if (result.status === "rejected") throw result.reason;
|
|
946
|
+
return result.value;
|
|
947
|
+
});
|
|
948
|
+
}) : await Promise.all(reads);
|
|
949
|
+
const stdoutExit = next.streams.stdout.exitCode;
|
|
950
|
+
const stderrExit = next.streams.stderr.exitCode;
|
|
951
|
+
if (stdoutExit !== null && stderrExit !== null && stdoutExit !== stderrExit)
|
|
952
|
+
throw new Error("Modal output streams disagree about command exit status");
|
|
953
|
+
return {
|
|
954
|
+
command: next,
|
|
955
|
+
streamFidelity: command.pty ? "merged" : "separate",
|
|
956
|
+
chunks: pages.filter((page) => page !== null),
|
|
957
|
+
exitCode: stdoutExit !== null && stderrExit !== null ? stdoutExit : null
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
async write(command, chars, messageIndex) {
|
|
961
|
+
this.assertIdentity(command);
|
|
962
|
+
if (!chars) return;
|
|
963
|
+
if (!Number.isSafeInteger(messageIndex) || messageIndex < 1)
|
|
964
|
+
throw new Error("Modal stdin requires a protected monotonic message index");
|
|
965
|
+
await this.client.containerExecPutInput(
|
|
966
|
+
{
|
|
967
|
+
execId: command.execId,
|
|
968
|
+
input: { message: Buffer.from(chars), messageIndex, eof: false }
|
|
969
|
+
},
|
|
970
|
+
{ retries: 0 }
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
assertIdentity(command) {
|
|
974
|
+
ModalLegacyProviderCommand.parse(command);
|
|
975
|
+
if (command.kind !== "modal-control-v1" || command.sandboxId !== this.sandboxId || !command.taskId || !command.execId)
|
|
976
|
+
throw new Error("Modal command locator does not match the original sandbox");
|
|
977
|
+
}
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
// src/sandbox/providers/modal-command-raw-page.ts
|
|
981
|
+
var RawStream = external_exports.object({
|
|
982
|
+
bytes: external_exports.instanceof(Uint8Array).transform((bytes) => bytes).refine(
|
|
983
|
+
(bytes) => bytes.byteLength <= MODAL_ROUTER_READ_PAGE_BYTES,
|
|
984
|
+
"Raw page exceeded its bound"
|
|
985
|
+
),
|
|
986
|
+
eof: external_exports.boolean()
|
|
987
|
+
}).strict();
|
|
988
|
+
var RawExit = external_exports.discriminatedUnion("source", [
|
|
989
|
+
external_exports.object({ source: external_exports.literal("router_poll"), code: external_exports.number().int().nullable() }).strict(),
|
|
990
|
+
external_exports.object({ source: external_exports.literal("retained_terminal"), code: external_exports.number().int() }).strict()
|
|
991
|
+
]);
|
|
992
|
+
var RawPage = external_exports.object({
|
|
993
|
+
protocol: external_exports.literal("modal-router-raw-page-v1"),
|
|
994
|
+
expected: ModalRouterProviderCommand2,
|
|
995
|
+
command: ModalRouterProviderCommand2,
|
|
996
|
+
streams: external_exports.object({ stdout: RawStream, stderr: RawStream }).strict(),
|
|
997
|
+
exit: RawExit
|
|
998
|
+
}).strict();
|
|
999
|
+
function project(expected, streams, exit) {
|
|
1000
|
+
const command = structuredClone(expected);
|
|
1001
|
+
const chunks = [];
|
|
1002
|
+
for (const stream of ["stdout", "stderr"]) {
|
|
1003
|
+
const old = expected.streams[stream];
|
|
1004
|
+
const page = streams[stream];
|
|
1005
|
+
const decoded = decodePage(old.utf8Remainder, [page.bytes], page.eof);
|
|
1006
|
+
const byteOffset = old.byteOffset + page.bytes.byteLength;
|
|
1007
|
+
if (!Number.isSafeInteger(byteOffset)) throw new Error("Modal output offset exhausted");
|
|
1008
|
+
command.streams[stream] = {
|
|
1009
|
+
byteOffset,
|
|
1010
|
+
utf8Remainder: decoded.remainder,
|
|
1011
|
+
eof: page.eof,
|
|
1012
|
+
exitCode: page.eof ? exit.code : null
|
|
1013
|
+
};
|
|
1014
|
+
if (decoded.text)
|
|
1015
|
+
chunks.push({
|
|
1016
|
+
stream,
|
|
1017
|
+
chunkId: `modal-router:${expected.execId}:${stream}:${old.byteOffset}:${byteOffset}:${page.eof ? 1 : 0}`,
|
|
1018
|
+
text: decoded.text
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
return {
|
|
1022
|
+
command,
|
|
1023
|
+
expected: structuredClone(expected),
|
|
1024
|
+
chunks,
|
|
1025
|
+
exitCode: command.streams.stdout.eof && command.streams.stderr.eof ? exit.code : null,
|
|
1026
|
+
providerExited: exit.code !== null,
|
|
1027
|
+
streamFidelity: expected.pty ? "merged" : "separate"
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
function collectModalRawOutputPage(command, streams, exit) {
|
|
1031
|
+
const expected = structuredClone(command);
|
|
1032
|
+
const captured = {
|
|
1033
|
+
stdout: { bytes: Buffer.from(streams.stdout.bytes), eof: streams.stdout.eof },
|
|
1034
|
+
stderr: { bytes: Buffer.from(streams.stderr.bytes), eof: streams.stderr.eof }
|
|
1035
|
+
};
|
|
1036
|
+
const output = project(expected, captured, exit);
|
|
1037
|
+
return {
|
|
1038
|
+
raw: {
|
|
1039
|
+
protocol: "modal-router-raw-page-v1",
|
|
1040
|
+
expected,
|
|
1041
|
+
command: structuredClone(output.command),
|
|
1042
|
+
streams: captured,
|
|
1043
|
+
exit: { ...exit }
|
|
1044
|
+
},
|
|
1045
|
+
output
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
function reduceModalRawOutputPage(input, current) {
|
|
1049
|
+
const page = RawPage.parse(input);
|
|
1050
|
+
const expected = ModalRouterProviderCommand2.parse(current);
|
|
1051
|
+
if (!isDeepStrictEqual(page.expected, expected))
|
|
1052
|
+
throw new Error("Raw page does not match the current native cursor");
|
|
1053
|
+
for (const stream of ["stdout", "stderr"]) {
|
|
1054
|
+
const old = expected.streams[stream];
|
|
1055
|
+
const raw = page.streams[stream];
|
|
1056
|
+
const remainder = Buffer.from(old.utf8Remainder, "base64");
|
|
1057
|
+
if (remainder.toString("base64") !== old.utf8Remainder || remainder.length > 3 || remainder.length > old.byteOffset || old.eof && remainder.length !== 0)
|
|
1058
|
+
throw new Error("Raw page has an invalid saved UTF-8 remainder");
|
|
1059
|
+
if (old.eof && (!raw.eof || raw.bytes.byteLength !== 0))
|
|
1060
|
+
throw new Error("Raw page reopened or advanced a completed stream");
|
|
1061
|
+
if (old.exitCode !== null && page.exit.code !== old.exitCode)
|
|
1062
|
+
throw new Error("Raw page rewrote captured terminal evidence");
|
|
1063
|
+
}
|
|
1064
|
+
if (page.exit.source === "retained_terminal" && (!expected.streams.stdout.eof || !expected.streams.stderr.eof || expected.streams.stdout.exitCode !== page.exit.code || expected.streams.stderr.exitCode !== page.exit.code))
|
|
1065
|
+
throw new Error("Raw page has no matching retained terminal evidence");
|
|
1066
|
+
const output = project(expected, page.streams, page.exit);
|
|
1067
|
+
if (!isDeepStrictEqual(page.command, output.command))
|
|
1068
|
+
throw new Error("Raw page cursor delta or remainder does not match its bytes");
|
|
1069
|
+
return output;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
155
1072
|
// src/sandbox/host-archive-spool.ts
|
|
156
1073
|
import { createHash as createHash2 } from "crypto";
|
|
157
1074
|
import { constants as constants2 } from "fs";
|
|
@@ -9138,7 +10055,7 @@ import { dirname as dirname3, join as join5, relative as relative3, sep as sep3
|
|
|
9138
10055
|
|
|
9139
10056
|
// ../../node_modules/.bun/@openai+agents-core@0.14.3+933c5e7db4cd33c2/node_modules/@openai/agents-core/dist/sandbox/sandboxes/shared/localSnapshotPaths.mjs
|
|
9140
10057
|
import { homedir, tmpdir as tmpdir3 } from "os";
|
|
9141
|
-
import { posix, win32 } from "path";
|
|
10058
|
+
import { posix as posix2, win32 } from "path";
|
|
9142
10059
|
function isAbsoluteWindowsPath(value) {
|
|
9143
10060
|
const root = win32.parse(value).root;
|
|
9144
10061
|
return win32.isAbsolute(value) && root.length > 1;
|
|
@@ -9150,14 +10067,14 @@ function defaultLocalSnapshotBaseDir() {
|
|
|
9150
10067
|
}
|
|
9151
10068
|
const home = homedir();
|
|
9152
10069
|
if (process.platform === "darwin" && home) {
|
|
9153
|
-
return
|
|
10070
|
+
return posix2.join(home, "Library", "Application Support", "openai-agents-js", "sandbox-snapshots");
|
|
9154
10071
|
}
|
|
9155
10072
|
if (process.platform === "win32") {
|
|
9156
10073
|
const localAppData = process.env.LOCALAPPDATA?.trim();
|
|
9157
10074
|
return win32.join(localAppData && isAbsoluteWindowsPath(localAppData) ? localAppData : home ? win32.join(home, "AppData", "Local") : tmpdir3(), "openai-agents-js", "sandbox-snapshots");
|
|
9158
10075
|
}
|
|
9159
10076
|
const stateHome = process.env.XDG_STATE_HOME?.trim();
|
|
9160
|
-
return
|
|
10077
|
+
return posix2.join(stateHome && posix2.isAbsolute(stateHome) ? stateHome : home ? posix2.join(home, ".local", "state") : tmpdir3(), "openai-agents-js", "sandbox-snapshots");
|
|
9161
10078
|
}
|
|
9162
10079
|
|
|
9163
10080
|
// ../../node_modules/.bun/@openai+agents-core@0.14.3+933c5e7db4cd33c2/node_modules/@openai/agents-core/dist/sandbox/sandboxes/shared/localSnapshots.mjs
|
|
@@ -15452,7 +16369,19 @@ function createActiveProcess(process2) {
|
|
|
15452
16369
|
droppedStderrChars: 0,
|
|
15453
16370
|
done: false,
|
|
15454
16371
|
exitCode: null,
|
|
15455
|
-
donePromise: Promise.resolve()
|
|
16372
|
+
donePromise: Promise.resolve(),
|
|
16373
|
+
failed: false
|
|
16374
|
+
};
|
|
16375
|
+
let notifyFailure;
|
|
16376
|
+
activeProcess.failurePromise = new Promise((resolve7) => {
|
|
16377
|
+
notifyFailure = resolve7;
|
|
16378
|
+
});
|
|
16379
|
+
const errors = [];
|
|
16380
|
+
const recordFailure = (error) => {
|
|
16381
|
+
errors.push(error);
|
|
16382
|
+
activeProcess.failed = true;
|
|
16383
|
+
activeProcess.waitError = errors.length === 1 ? error : new AggregateError([...errors], "Modal process observation failed.");
|
|
16384
|
+
notifyFailure();
|
|
15456
16385
|
};
|
|
15457
16386
|
const stdoutPump = startTextStreamPump(process2.stdout, (chunk) => {
|
|
15458
16387
|
appendActiveProcessOutput2(activeProcess, chunk, "stdout");
|
|
@@ -15460,19 +16389,19 @@ function createActiveProcess(process2) {
|
|
|
15460
16389
|
const stderrPump = startTextStreamPump(process2.stderr, (chunk) => {
|
|
15461
16390
|
appendActiveProcessOutput2(activeProcess, chunk, "stderr");
|
|
15462
16391
|
});
|
|
16392
|
+
const stdoutDone = stdoutPump.promise.catch(recordFailure);
|
|
16393
|
+
const stderrDone = stderrPump.promise.catch(recordFailure);
|
|
15463
16394
|
activeProcess.stopOutputPumps = async () => {
|
|
15464
16395
|
await Promise.allSettled([stdoutPump.cancel(), stderrPump.cancel()]);
|
|
15465
16396
|
};
|
|
15466
16397
|
activeProcess.donePromise = (async () => {
|
|
15467
16398
|
try {
|
|
15468
16399
|
activeProcess.exitCode = await process2.wait();
|
|
15469
|
-
await Promise.allSettled([stdoutPump.promise, stderrPump.promise]);
|
|
15470
16400
|
} catch (error) {
|
|
15471
|
-
|
|
15472
|
-
await Promise.allSettled([stdoutPump.promise, stderrPump.promise]);
|
|
15473
|
-
} finally {
|
|
15474
|
-
activeProcess.done = true;
|
|
16401
|
+
recordFailure(error);
|
|
15475
16402
|
}
|
|
16403
|
+
await Promise.all([stdoutDone, stderrDone]);
|
|
16404
|
+
activeProcess.done = true;
|
|
15476
16405
|
})();
|
|
15477
16406
|
return activeProcess;
|
|
15478
16407
|
}
|
|
@@ -15528,6 +16457,7 @@ async function waitForProcessOrTimeout2(activeProcess, timeoutMs) {
|
|
|
15528
16457
|
try {
|
|
15529
16458
|
await Promise.race([
|
|
15530
16459
|
activeProcess.donePromise,
|
|
16460
|
+
activeProcess.failurePromise,
|
|
15531
16461
|
new Promise((resolve7) => {
|
|
15532
16462
|
timeout = setTimeout(resolve7, timeoutMs);
|
|
15533
16463
|
unrefTimer(timeout);
|
|
@@ -15538,13 +16468,13 @@ async function waitForProcessOrTimeout2(activeProcess, timeoutMs) {
|
|
|
15538
16468
|
clearTimeout(timeout);
|
|
15539
16469
|
}
|
|
15540
16470
|
}
|
|
15541
|
-
if (activeProcess.
|
|
16471
|
+
if (activeProcess.failed) {
|
|
15542
16472
|
await activeProcess.stopOutputPumps?.();
|
|
15543
|
-
throw new SandboxProviderError("ModalSandboxClient failed to wait for process completion.", {
|
|
16473
|
+
throw Object.assign(new SandboxProviderError("ModalSandboxClient failed to wait for process completion.", {
|
|
15544
16474
|
provider: "modal",
|
|
15545
16475
|
operation: "wait process",
|
|
15546
16476
|
cause: modalErrorMessage(activeProcess.waitError)
|
|
15547
|
-
});
|
|
16477
|
+
}), { cause: activeProcess.waitError });
|
|
15548
16478
|
}
|
|
15549
16479
|
}
|
|
15550
16480
|
function modalErrorMessage(error) {
|
|
@@ -15889,661 +16819,213 @@ function writeFilesPrelude(input) {
|
|
|
15889
16819
|
input.sha256Function,
|
|
15890
16820
|
`og_fail() { printf '%s' "$1"; exit "$2"; }`,
|
|
15891
16821
|
`root=$(opengeni_realpath_existing ${shellQuote3(input.root)}) || og_fail __OPENGENI_FS_NOT_FOUND__ 66`,
|
|
15892
|
-
`og_confined() { case "$1" in "$root"|"\${root%/}/"*) return 0 ;; *) return 1 ;; esac; }`,
|
|
15893
|
-
// A directory on the path is never a symbolic link and always resolves
|
|
15894
|
-
// beneath the workspace root. A missing one returns 1 for the caller.
|
|
15895
|
-
[
|
|
15896
|
-
"og_dir() {",
|
|
15897
|
-
`[ ! -L "$2" ] || og_fail "__OPENGENI_FS_SYMLINK__D$1__" 68`,
|
|
15898
|
-
`[ -e "$2" ] || return 1`,
|
|
15899
|
-
`[ -d "$2" ] || og_fail "__OPENGENI_FS_NOT_DIR__D$1__" 69`,
|
|
15900
|
-
`og_t=$(opengeni_realpath_existing "$2") || og_fail "__OPENGENI_FS_NOT_FOUND__D$1__" 66`,
|
|
15901
|
-
`og_confined "$og_t" || og_fail "__OPENGENI_FS_ESCAPE__D$1__" 67`,
|
|
15902
|
-
"}"
|
|
15903
|
-
].join("\n"),
|
|
15904
|
-
// 0: the exact bytes already exist. 1: missing. Anything else fails.
|
|
15905
|
-
[
|
|
15906
|
-
"og_file() {",
|
|
15907
|
-
`if [ -L "$2" ]; then og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65; fi`,
|
|
15908
|
-
`[ -e "$2" ] || return 1`,
|
|
15909
|
-
`[ -f "$2" ] || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
15910
|
-
`og_n=$(wc -c < "$2") || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
15911
|
-
`[ "$((og_n))" = "$3" ] || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
15912
|
-
`og_h=$(opengeni_sha256_file "$2") || og_fail "__OPENGENI_FS_UNVERIFIED__F$1__" 65`,
|
|
15913
|
-
`[ "$og_h" = "$4" ] || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
15914
|
-
"}"
|
|
15915
|
-
].join("\n"),
|
|
15916
|
-
[
|
|
15917
|
-
"og_mk() {",
|
|
15918
|
-
`mkdir -- "$2" 2>/dev/null || og_fail "__OPENGENI_FS_WRITE_FAILED__D$1__" 70`,
|
|
15919
|
-
`printf '__OGF_D__%s__' "$1"`,
|
|
15920
|
-
`og_dir "$1" "$2" || og_fail "__OPENGENI_FS_NOT_FOUND__D$1__" 66`,
|
|
15921
|
-
"}"
|
|
15922
|
-
].join("\n"),
|
|
15923
|
-
// noclobber opens a missing path with O_EXCL, so a file that appeared
|
|
15924
|
-
// since the check (including a dangling symlink) is never replaced. A
|
|
15925
|
-
// failed open exits 1 and leaves the path alone. Once the open succeeded
|
|
15926
|
-
// the file is this call's own, so a failed or short write (a full disk,
|
|
15927
|
-
// for example) removes it; otherwise a repeat would find a truncated file
|
|
15928
|
-
// and report a conflict instead of finishing the write.
|
|
15929
|
-
[
|
|
15930
|
-
"og_put() {",
|
|
15931
|
-
`( set -C; { printf '%s' "$4" | base64 -d || exit 72; } > "$2" ) 2>/dev/null`,
|
|
15932
|
-
"og_s=$?",
|
|
15933
|
-
`[ "$og_s" != 72 ] || { rm -f -- "$2"; og_fail "__OPENGENI_FS_WRITE_FAILED__F$1__" 71; }`,
|
|
15934
|
-
`[ "$og_s" = 0 ] || og_fail "__OPENGENI_FS_WRITE_FAILED__F$1__" 71`,
|
|
15935
|
-
`og_n=$(wc -c < "$2") && [ "$((og_n))" = "$3" ] || { rm -f -- "$2"; og_fail "__OPENGENI_FS_WRITE_FAILED__F$1__" 71; }`,
|
|
15936
|
-
`printf '__OGF_W__%s__' "$1"`,
|
|
15937
|
-
"}"
|
|
15938
|
-
].join("\n")
|
|
15939
|
-
];
|
|
15940
|
-
}
|
|
15941
|
-
function directoryCheckFragment(directory) {
|
|
15942
|
-
return `og_dir ${directory.index} ${shellQuote3(directory.providerPath)} || :`;
|
|
15943
|
-
}
|
|
15944
|
-
function fileCheckFragment(file, mode) {
|
|
15945
|
-
const check = `og_file ${file.index} ${shellQuote3(file.providerPath)} ${file.sizeBytes} ${file.sha256}`;
|
|
15946
|
-
const missing = mode === "check" ? `printf '__OGF_M__%s__' ${file.index}` : `og_m${file.index}=1`;
|
|
15947
|
-
return `if ${check}; then printf '__OGF_S__%s__' ${file.index}; else ${missing}; fi`;
|
|
15948
|
-
}
|
|
15949
|
-
function directoryCreateFragment(directory) {
|
|
15950
|
-
const path = shellQuote3(directory.providerPath);
|
|
15951
|
-
return `og_dir ${directory.index} ${path} || og_mk ${directory.index} ${path}`;
|
|
15952
|
-
}
|
|
15953
|
-
function filePutFragment(file) {
|
|
15954
|
-
if (file.base64 === void 0) throw new Error("write mode requires file content");
|
|
15955
|
-
return `[ -z "\${og_m${file.index}:-}" ] || og_put ${file.index} ${shellQuote3(file.providerPath)} ${file.sizeBytes} ${shellQuote3(file.base64)}`;
|
|
15956
|
-
}
|
|
15957
|
-
function writeFilesScript(input) {
|
|
15958
|
-
const lines = [...input.prelude];
|
|
15959
|
-
for (const directory of input.directories) lines.push(directoryCheckFragment(directory));
|
|
15960
|
-
for (const file of input.files) lines.push(fileCheckFragment(file, input.mode));
|
|
15961
|
-
if (input.mode === "write") {
|
|
15962
|
-
for (const directory of input.directories) lines.push(directoryCreateFragment(directory));
|
|
15963
|
-
for (const file of input.files) lines.push(filePutFragment(file));
|
|
15964
|
-
}
|
|
15965
|
-
lines.push(`printf '%s' ${BATCH_OK}`);
|
|
15966
|
-
return lines.join("\n");
|
|
15967
|
-
}
|
|
15968
|
-
function parseWriteFilesOutput(stdout) {
|
|
15969
|
-
const output = {
|
|
15970
|
-
complete: stdout.includes(BATCH_OK),
|
|
15971
|
-
same: [],
|
|
15972
|
-
missing: [],
|
|
15973
|
-
written: [],
|
|
15974
|
-
createdDirectories: [],
|
|
15975
|
-
failure: null
|
|
15976
|
-
};
|
|
15977
|
-
for (const match of stdout.matchAll(/__OGF_([SMWD])__(\d+)__/g)) {
|
|
15978
|
-
const index = Number(match[2]);
|
|
15979
|
-
if (match[1] === "S") output.same.push(index);
|
|
15980
|
-
else if (match[1] === "M") output.missing.push(index);
|
|
15981
|
-
else if (match[1] === "W") output.written.push(index);
|
|
15982
|
-
else output.createdDirectories.push(index);
|
|
15983
|
-
}
|
|
15984
|
-
const failure = /__OPENGENI_FS_(CONFLICT|UNVERIFIED|SYMLINK|NOT_DIR|NOT_FOUND|ESCAPE|WRITE_FAILED)__(?:([DF])(\d+)__)?/.exec(
|
|
15985
|
-
stdout
|
|
15986
|
-
);
|
|
15987
|
-
if (failure) {
|
|
15988
|
-
output.failure = {
|
|
15989
|
-
code: failure[1],
|
|
15990
|
-
target: failure[2] ? { kind: failure[2] === "D" ? "directory" : "file", index: Number(failure[3]) } : null
|
|
15991
|
-
};
|
|
15992
|
-
}
|
|
15993
|
-
return output;
|
|
15994
|
-
}
|
|
15995
|
-
|
|
15996
|
-
// src/sandbox/exec-banner.ts
|
|
15997
|
-
var typedHandleLossSessions = /* @__PURE__ */ new WeakSet();
|
|
15998
|
-
function markTypedExecHandleLoss(session) {
|
|
15999
|
-
typedHandleLossSessions.add(session);
|
|
16000
|
-
}
|
|
16001
|
-
function hasTypedExecHandleLoss(session, providerSessionId) {
|
|
16002
|
-
if (!session) return false;
|
|
16003
|
-
if (typedHandleLossSessions.has(session)) return true;
|
|
16004
|
-
const routed = session;
|
|
16005
|
-
return providerSessionId !== void 0 && routed.retainedProcessHasTypedHandleLoss?.(providerSessionId) === true;
|
|
16006
|
-
}
|
|
16007
|
-
var EXEC_BANNER_HEADER_MAX_CHARS = 16 * 1024;
|
|
16008
|
-
var OUTPUT_DELIMITER = /\r?\nOutput:\r?\n/u;
|
|
16009
|
-
var SDK_METADATA_LINE = /^(?:Chunk ID:|Wall time:|Original token count:|Output:|Process (?:running with session ID|exited with code))/mu;
|
|
16010
|
-
var RUNNING_LINE = /^Process running with session ID (\d+)$/u;
|
|
16011
|
-
var EXITED_LINE = /^Process exited with code (-?\d+)$/u;
|
|
16012
|
-
var PROCESS_STATUS_PREFIX = /^Process (?:running with session ID|exited with code)/u;
|
|
16013
|
-
function parseExecResponseBanner(raw) {
|
|
16014
|
-
const delimiter = OUTPUT_DELIMITER.exec(raw);
|
|
16015
|
-
if (!delimiter) {
|
|
16016
|
-
return SDK_METADATA_LINE.test(raw) ? { kind: "invalid" } : { kind: "absent" };
|
|
16017
|
-
}
|
|
16018
|
-
if (delimiter.index > EXEC_BANNER_HEADER_MAX_CHARS) return { kind: "invalid" };
|
|
16019
|
-
const header = raw.slice(0, delimiter.index);
|
|
16020
|
-
const status4 = [];
|
|
16021
|
-
for (const line of header.split(/\r?\n/u)) {
|
|
16022
|
-
const running = RUNNING_LINE.exec(line);
|
|
16023
|
-
if (running) {
|
|
16024
|
-
status4.push({ kind: "running", value: running[1] });
|
|
16025
|
-
continue;
|
|
16026
|
-
}
|
|
16027
|
-
const exited = EXITED_LINE.exec(line);
|
|
16028
|
-
if (exited) {
|
|
16029
|
-
status4.push({ kind: "exited", value: exited[1] });
|
|
16030
|
-
continue;
|
|
16031
|
-
}
|
|
16032
|
-
if (PROCESS_STATUS_PREFIX.test(line)) return { kind: "invalid" };
|
|
16033
|
-
}
|
|
16034
|
-
if (status4.length !== 1) return { kind: "invalid" };
|
|
16035
|
-
const terminal = status4[0];
|
|
16036
|
-
const value = Number(terminal.value);
|
|
16037
|
-
if (!Number.isSafeInteger(value)) return { kind: "invalid" };
|
|
16038
|
-
if (terminal.kind === "running") {
|
|
16039
|
-
return value >= 0 ? { kind: "running", sessionId: value } : { kind: "invalid" };
|
|
16040
|
-
}
|
|
16041
|
-
return { kind: "exited", exitCode: value };
|
|
16042
|
-
}
|
|
16043
|
-
function parseExecBannerSessionId(raw) {
|
|
16044
|
-
const banner = parseExecResponseBanner(raw);
|
|
16045
|
-
return banner.kind === "running" ? banner.sessionId : null;
|
|
16046
|
-
}
|
|
16047
|
-
function parseExecBannerExitCode(raw) {
|
|
16048
|
-
const banner = parseExecResponseBanner(raw);
|
|
16049
|
-
return banner.kind === "exited" ? banner.exitCode : null;
|
|
16050
|
-
}
|
|
16051
|
-
function isExecSessionLostBanner(out, execSessionId, source) {
|
|
16052
|
-
if (source && typedHandleLossSessions.has(source)) return false;
|
|
16053
|
-
if (!out || !Number.isSafeInteger(execSessionId) || execSessionId < 0) return false;
|
|
16054
|
-
const delimiter = OUTPUT_DELIMITER.exec(out);
|
|
16055
|
-
if (delimiter && delimiter.index > EXEC_BANNER_HEADER_MAX_CHARS) return false;
|
|
16056
|
-
if (delimiter && parseExecResponseBanner(out).kind !== "exited") return false;
|
|
16057
|
-
const candidate = delimiter ? out.slice(delimiter.index + delimiter[0].length) : out;
|
|
16058
|
-
const match = candidate.match(/^(?:write_stdin failed: )?session not found: (\d+)$/);
|
|
16059
|
-
if (!match || match[0] !== candidate) return false;
|
|
16060
|
-
return match[1] === String(execSessionId);
|
|
16061
|
-
}
|
|
16062
|
-
|
|
16063
|
-
// src/sandbox/op-correlation.ts
|
|
16064
|
-
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
16065
|
-
var storage = new AsyncLocalStorage2();
|
|
16066
|
-
function sanitizeOpIdToken(raw) {
|
|
16067
|
-
return raw.replace(/[^A-Za-z0-9_-]/g, (c) => `_${c.charCodeAt(0).toString(16)}_`);
|
|
16068
|
-
}
|
|
16069
|
-
function runWithToolCallCorrelation(callId, fn, options = {}) {
|
|
16070
|
-
return storage.run(
|
|
16071
|
-
{
|
|
16072
|
-
callId: sanitizeOpIdToken(callId),
|
|
16073
|
-
ordinal: 0,
|
|
16074
|
-
...options.onDurableOpOwnershipTransferStarted ? { onDurableOpOwnershipTransferStarted: options.onDurableOpOwnershipTransferStarted } : {},
|
|
16075
|
-
...options.onDurableOpOwnershipTransferred ? { onDurableOpOwnershipTransferred: options.onDurableOpOwnershipTransferred } : {}
|
|
16076
|
-
},
|
|
16077
|
-
fn
|
|
16078
|
-
);
|
|
16079
|
-
}
|
|
16080
|
-
function nextDurableOpId() {
|
|
16081
|
-
const context = storage.getStore();
|
|
16082
|
-
if (!context) {
|
|
16083
|
-
return null;
|
|
16084
|
-
}
|
|
16085
|
-
const ordinal = context.ordinal;
|
|
16086
|
-
context.ordinal += 1;
|
|
16087
|
-
return `${context.callId}:${ordinal}`;
|
|
16088
|
-
}
|
|
16089
|
-
function notifyDurableOpOwnershipTransferStarted(opId) {
|
|
16090
|
-
storage.getStore()?.onDurableOpOwnershipTransferStarted?.(opId);
|
|
16091
|
-
}
|
|
16092
|
-
function notifyDurableOpOwnershipTransferred(opId) {
|
|
16093
|
-
storage.getStore()?.onDurableOpOwnershipTransferred?.(opId);
|
|
16094
|
-
}
|
|
16095
|
-
|
|
16096
|
-
// src/sandbox/routing/routing-session.ts
|
|
16097
|
-
import { SandboxFilesystemNotFoundError } from "modal";
|
|
16098
|
-
|
|
16099
|
-
// src/sandbox/providers/modal-command-router-wire.ts
|
|
16100
|
-
import { Client, Metadata, credentials, status } from "@grpc/grpc-js";
|
|
16101
|
-
import protobuf from "protobufjs";
|
|
16102
|
-
|
|
16103
|
-
// src/sandbox/providers/modal-command-start-errors.ts
|
|
16104
|
-
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
16105
|
-
import { ModalRouterProviderCommand } from "@opengeni/contracts";
|
|
16106
|
-
var boundaryBrand = Symbol.for("opengeni.modal.command-start.boundary.v1");
|
|
16107
|
-
var invocationBrand = Symbol.for("opengeni.modal.command-start.invocation.v1");
|
|
16108
|
-
var contextBrand = Symbol.for("opengeni.modal.command-start.context.v1");
|
|
16109
|
-
var startSignal = new AsyncLocalStorage3();
|
|
16110
|
-
function withModalCommandStartSignal(signal, operation) {
|
|
16111
|
-
signal.throwIfAborted();
|
|
16112
|
-
return startSignal.run(signal, operation);
|
|
16113
|
-
}
|
|
16114
|
-
function installModalCommandStartContext(modal) {
|
|
16115
|
-
if (Object.getOwnPropertyDescriptor(modal, contextBrand)) return;
|
|
16116
|
-
Object.defineProperty(modal, contextBrand, { value: () => startSignal.getStore() });
|
|
16117
|
-
}
|
|
16118
|
-
function modalCommandStartOwnData(value, key) {
|
|
16119
|
-
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
16120
|
-
return property && "value" in property ? property.value : void 0;
|
|
16121
|
-
}
|
|
16122
|
-
function modalCommandStartHasOwnAccessor(value, key) {
|
|
16123
|
-
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
16124
|
-
return !!property && !("value" in property);
|
|
16125
|
-
}
|
|
16126
|
-
function getModalCommandStartInvocation(error) {
|
|
16127
|
-
const pending = [{ value: error, depth: 0 }];
|
|
16128
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
16129
|
-
let result = null;
|
|
16130
|
-
let inspected = 0;
|
|
16131
|
-
while (pending.length) {
|
|
16132
|
-
if (++inspected > 64) return null;
|
|
16133
|
-
const { value, depth } = pending.shift();
|
|
16134
|
-
if (!value || typeof value !== "object" || seen.has(value)) continue;
|
|
16135
|
-
if (depth > 8) return null;
|
|
16136
|
-
seen.add(value);
|
|
16137
|
-
try {
|
|
16138
|
-
if (["cause", "error", "errors"].some((key) => modalCommandStartHasOwnAccessor(value, key)))
|
|
16139
|
-
return null;
|
|
16140
|
-
if (hasModalCommandStartBoundary(value, "outcome-unknown")) {
|
|
16141
|
-
const descriptor = modalCommandStartOwnData(value, invocationBrand);
|
|
16142
|
-
if (!descriptor || typeof descriptor !== "object" || !Object.isFrozen(descriptor))
|
|
16143
|
-
return null;
|
|
16144
|
-
const sandboxId = modalCommandStartOwnData(descriptor, "sandboxId");
|
|
16145
|
-
const taskId = modalCommandStartOwnData(descriptor, "taskId");
|
|
16146
|
-
const execId = modalCommandStartOwnData(descriptor, "execId");
|
|
16147
|
-
const observe = modalCommandStartOwnData(descriptor, "observe");
|
|
16148
|
-
const ptyProperty = Object.getOwnPropertyDescriptor(descriptor, "pty");
|
|
16149
|
-
if (ptyProperty && (!("value" in ptyProperty) || typeof ptyProperty.value !== "boolean"))
|
|
16150
|
-
return null;
|
|
16151
|
-
if (typeof sandboxId !== "string" || !sandboxId || typeof taskId !== "string" || !taskId || typeof execId !== "string" || !execId || typeof observe !== "function")
|
|
16152
|
-
return null;
|
|
16153
|
-
if (result && result !== descriptor) return null;
|
|
16154
|
-
result = descriptor;
|
|
16155
|
-
}
|
|
16156
|
-
const nested = [
|
|
16157
|
-
modalCommandStartOwnData(value, "cause"),
|
|
16158
|
-
modalCommandStartOwnData(value, "error")
|
|
16159
|
-
].filter((child) => child !== void 0);
|
|
16160
|
-
const errors = modalCommandStartOwnData(value, "errors");
|
|
16161
|
-
if (errors !== void 0) {
|
|
16162
|
-
if (!Array.isArray(errors)) return null;
|
|
16163
|
-
const length = modalCommandStartOwnData(errors, "length");
|
|
16164
|
-
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 1 || length > 32)
|
|
16165
|
-
return null;
|
|
16166
|
-
for (let index = 0; index < length; index++) {
|
|
16167
|
-
const property = Object.getOwnPropertyDescriptor(errors, String(index));
|
|
16168
|
-
if (!property || !("value" in property) || !property.value || typeof property.value !== "object")
|
|
16169
|
-
return null;
|
|
16170
|
-
nested.push(property.value);
|
|
16171
|
-
}
|
|
16172
|
-
}
|
|
16173
|
-
if (depth === 8 && nested.length) return null;
|
|
16174
|
-
for (const child of nested) pending.push({ value: child, depth: depth + 1 });
|
|
16175
|
-
} catch {
|
|
16176
|
-
return null;
|
|
16177
|
-
}
|
|
16178
|
-
}
|
|
16179
|
-
return result;
|
|
16180
|
-
}
|
|
16181
|
-
function modalCommandStartRetainedError(error) {
|
|
16182
|
-
if (error instanceof ProviderCommandStartOutcomeUnknownError) return error;
|
|
16183
|
-
const invocation = getModalCommandStartInvocation(error);
|
|
16184
|
-
if (!invocation) return error;
|
|
16185
|
-
const cursor = () => ({ byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null });
|
|
16186
|
-
const command = ModalRouterProviderCommand.safeParse({
|
|
16187
|
-
kind: "modal-router-v1",
|
|
16188
|
-
sandboxId: invocation.sandboxId,
|
|
16189
|
-
taskId: invocation.taskId,
|
|
16190
|
-
execId: invocation.execId,
|
|
16191
|
-
...invocation.pty === void 0 ? {} : { pty: invocation.pty },
|
|
16192
|
-
streams: { stdout: cursor(), stderr: cursor() }
|
|
16193
|
-
});
|
|
16194
|
-
return command.success ? new ProviderCommandStartOutcomeUnknownError(command.data, error) : error;
|
|
16195
|
-
}
|
|
16196
|
-
function hasModalCommandStartOutcomeUnknownBoundary(error) {
|
|
16197
|
-
const pending = [{ value: error, depth: 0 }];
|
|
16198
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
16199
|
-
for (let inspected = 0; pending.length && inspected < 64; inspected++) {
|
|
16200
|
-
const { value, depth } = pending.shift();
|
|
16201
|
-
if (!value || typeof value !== "object" || seen.has(value)) continue;
|
|
16202
|
-
seen.add(value);
|
|
16203
|
-
if (hasModalCommandStartBoundary(value, "outcome-unknown")) return true;
|
|
16204
|
-
if (depth >= 8) continue;
|
|
16205
|
-
try {
|
|
16206
|
-
for (const key of ["cause", "error"]) {
|
|
16207
|
-
const nested = modalCommandStartOwnData(value, key);
|
|
16208
|
-
if (nested !== void 0) pending.push({ value: nested, depth: depth + 1 });
|
|
16209
|
-
}
|
|
16210
|
-
const errors = modalCommandStartOwnData(value, "errors");
|
|
16211
|
-
if (Array.isArray(errors))
|
|
16212
|
-
for (let index = 0; index < Math.min(errors.length, 32); index++)
|
|
16213
|
-
pending.push({
|
|
16214
|
-
value: modalCommandStartOwnData(errors, String(index)),
|
|
16215
|
-
depth: depth + 1
|
|
16216
|
-
});
|
|
16217
|
-
} catch {
|
|
16218
|
-
}
|
|
16219
|
-
}
|
|
16220
|
-
return false;
|
|
16221
|
-
}
|
|
16222
|
-
function modalCommandStartCleanupIsSafe(error) {
|
|
16223
|
-
const pending = [{ value: error, depth: 0 }];
|
|
16224
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
16225
|
-
let inspected = 0;
|
|
16226
|
-
while (pending.length) {
|
|
16227
|
-
if (++inspected > 64) return false;
|
|
16228
|
-
const { value, depth } = pending.shift();
|
|
16229
|
-
if (!value || typeof value !== "object" && typeof value !== "function") continue;
|
|
16230
|
-
if (seen.has(value)) continue;
|
|
16231
|
-
if (depth > 8) return false;
|
|
16232
|
-
seen.add(value);
|
|
16233
|
-
try {
|
|
16234
|
-
if (value instanceof ProviderCommandStartOutcomeUnknownError || hasModalCommandStartBoundary(value, "outcome-unknown") || [boundaryBrand, "cause", "error", "errors"].some(
|
|
16235
|
-
(key) => modalCommandStartHasOwnAccessor(value, key)
|
|
16236
|
-
))
|
|
16237
|
-
return false;
|
|
16238
|
-
const nested = [
|
|
16239
|
-
modalCommandStartOwnData(value, "cause"),
|
|
16240
|
-
modalCommandStartOwnData(value, "error")
|
|
16241
|
-
].filter((child) => child !== void 0 && child !== null);
|
|
16242
|
-
const errors = modalCommandStartOwnData(value, "errors");
|
|
16243
|
-
if (errors !== void 0) {
|
|
16244
|
-
if (!Array.isArray(errors)) return false;
|
|
16245
|
-
const length = modalCommandStartOwnData(errors, "length");
|
|
16246
|
-
if (typeof length !== "number" || !Number.isSafeInteger(length) || length > 32)
|
|
16247
|
-
return false;
|
|
16248
|
-
for (let index = 0; index < length; index++) {
|
|
16249
|
-
const property = Object.getOwnPropertyDescriptor(errors, String(index));
|
|
16250
|
-
if (!property || !("value" in property) || !property.value || typeof property.value !== "object" && typeof property.value !== "function")
|
|
16251
|
-
return false;
|
|
16252
|
-
nested.push(property.value);
|
|
16253
|
-
}
|
|
16254
|
-
}
|
|
16255
|
-
if (depth === 8 && nested.length) return false;
|
|
16256
|
-
for (const child of nested) pending.push({ value: child, depth: depth + 1 });
|
|
16257
|
-
} catch {
|
|
16258
|
-
return false;
|
|
16259
|
-
}
|
|
16260
|
-
}
|
|
16261
|
-
return true;
|
|
16262
|
-
}
|
|
16263
|
-
function installModalCommandStartRetention(session) {
|
|
16264
|
-
for (const name of [
|
|
16265
|
-
"execCommand",
|
|
16266
|
-
"applyManifest",
|
|
16267
|
-
"materializeEntry",
|
|
16268
|
-
"hydrateWorkspace",
|
|
16269
|
-
"persistWorkspace",
|
|
16270
|
-
"runDirectCommand",
|
|
16271
|
-
"runAsCommandRunner"
|
|
16272
|
-
]) {
|
|
16273
|
-
const operation = Reflect.get(session, name);
|
|
16274
|
-
if (typeof operation !== "function") continue;
|
|
16275
|
-
Reflect.set(session, name, async function(...args) {
|
|
16276
|
-
try {
|
|
16277
|
-
return await operation.apply(session, args);
|
|
16278
|
-
} catch (error) {
|
|
16279
|
-
throw modalCommandStartRetainedError(error);
|
|
16280
|
-
}
|
|
16281
|
-
});
|
|
16282
|
-
}
|
|
16283
|
-
}
|
|
16284
|
-
function hasModalCommandStartBoundary(error, kind) {
|
|
16285
|
-
if (!error || typeof error !== "object") return false;
|
|
16286
|
-
try {
|
|
16287
|
-
const property = Object.getOwnPropertyDescriptor(error, boundaryBrand);
|
|
16288
|
-
return property?.value === kind && property.writable === false && property.configurable === false;
|
|
16289
|
-
} catch {
|
|
16290
|
-
return false;
|
|
16291
|
-
}
|
|
16822
|
+
`og_confined() { case "$1" in "$root"|"\${root%/}/"*) return 0 ;; *) return 1 ;; esac; }`,
|
|
16823
|
+
// A directory on the path is never a symbolic link and always resolves
|
|
16824
|
+
// beneath the workspace root. A missing one returns 1 for the caller.
|
|
16825
|
+
[
|
|
16826
|
+
"og_dir() {",
|
|
16827
|
+
`[ ! -L "$2" ] || og_fail "__OPENGENI_FS_SYMLINK__D$1__" 68`,
|
|
16828
|
+
`[ -e "$2" ] || return 1`,
|
|
16829
|
+
`[ -d "$2" ] || og_fail "__OPENGENI_FS_NOT_DIR__D$1__" 69`,
|
|
16830
|
+
`og_t=$(opengeni_realpath_existing "$2") || og_fail "__OPENGENI_FS_NOT_FOUND__D$1__" 66`,
|
|
16831
|
+
`og_confined "$og_t" || og_fail "__OPENGENI_FS_ESCAPE__D$1__" 67`,
|
|
16832
|
+
"}"
|
|
16833
|
+
].join("\n"),
|
|
16834
|
+
// 0: the exact bytes already exist. 1: missing. Anything else fails.
|
|
16835
|
+
[
|
|
16836
|
+
"og_file() {",
|
|
16837
|
+
`if [ -L "$2" ]; then og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65; fi`,
|
|
16838
|
+
`[ -e "$2" ] || return 1`,
|
|
16839
|
+
`[ -f "$2" ] || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
16840
|
+
`og_n=$(wc -c < "$2") || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
16841
|
+
`[ "$((og_n))" = "$3" ] || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
16842
|
+
`og_h=$(opengeni_sha256_file "$2") || og_fail "__OPENGENI_FS_UNVERIFIED__F$1__" 65`,
|
|
16843
|
+
`[ "$og_h" = "$4" ] || og_fail "__OPENGENI_FS_CONFLICT__F$1__" 65`,
|
|
16844
|
+
"}"
|
|
16845
|
+
].join("\n"),
|
|
16846
|
+
[
|
|
16847
|
+
"og_mk() {",
|
|
16848
|
+
`mkdir -- "$2" 2>/dev/null || og_fail "__OPENGENI_FS_WRITE_FAILED__D$1__" 70`,
|
|
16849
|
+
`printf '__OGF_D__%s__' "$1"`,
|
|
16850
|
+
`og_dir "$1" "$2" || og_fail "__OPENGENI_FS_NOT_FOUND__D$1__" 66`,
|
|
16851
|
+
"}"
|
|
16852
|
+
].join("\n"),
|
|
16853
|
+
// noclobber opens a missing path with O_EXCL, so a file that appeared
|
|
16854
|
+
// since the check (including a dangling symlink) is never replaced. A
|
|
16855
|
+
// failed open exits 1 and leaves the path alone. Once the open succeeded
|
|
16856
|
+
// the file is this call's own, so a failed or short write (a full disk,
|
|
16857
|
+
// for example) removes it; otherwise a repeat would find a truncated file
|
|
16858
|
+
// and report a conflict instead of finishing the write.
|
|
16859
|
+
[
|
|
16860
|
+
"og_put() {",
|
|
16861
|
+
`( set -C; { printf '%s' "$4" | base64 -d || exit 72; } > "$2" ) 2>/dev/null`,
|
|
16862
|
+
"og_s=$?",
|
|
16863
|
+
`[ "$og_s" != 72 ] || { rm -f -- "$2"; og_fail "__OPENGENI_FS_WRITE_FAILED__F$1__" 71; }`,
|
|
16864
|
+
`[ "$og_s" = 0 ] || og_fail "__OPENGENI_FS_WRITE_FAILED__F$1__" 71`,
|
|
16865
|
+
`og_n=$(wc -c < "$2") && [ "$((og_n))" = "$3" ] || { rm -f -- "$2"; og_fail "__OPENGENI_FS_WRITE_FAILED__F$1__" 71; }`,
|
|
16866
|
+
`printf '__OGF_W__%s__' "$1"`,
|
|
16867
|
+
"}"
|
|
16868
|
+
].join("\n")
|
|
16869
|
+
];
|
|
16292
16870
|
}
|
|
16293
|
-
|
|
16294
|
-
|
|
16295
|
-
super("Modal command Start outcome unknown; do not replay this invocation", { cause });
|
|
16296
|
-
this.taskId = taskId;
|
|
16297
|
-
this.execId = execId;
|
|
16298
|
-
this.name = "CommandStartOutcomeUnknownError";
|
|
16299
|
-
Object.defineProperty(this, boundaryBrand, { value: "outcome-unknown" });
|
|
16300
|
-
}
|
|
16301
|
-
};
|
|
16302
|
-
|
|
16303
|
-
// src/sandbox/providers/modal-command-router-wire.ts
|
|
16304
|
-
var modalRouterWire = protobuf.parse(`syntax = "proto3";
|
|
16305
|
-
message Identity { string task_id = 1; string exec_id = 2; }
|
|
16306
|
-
message Pty {
|
|
16307
|
-
bool enabled = 1; uint32 winsz_rows = 2; uint32 winsz_cols = 3;
|
|
16308
|
-
string env_term = 4; string env_colorterm = 5; string env_term_program = 6;
|
|
16309
|
-
int32 pty_type = 7; bool no_terminate_on_idle_stdin = 8;
|
|
16871
|
+
function directoryCheckFragment(directory) {
|
|
16872
|
+
return `og_dir ${directory.index} ${shellQuote3(directory.providerPath)} || :`;
|
|
16310
16873
|
}
|
|
16311
|
-
|
|
16312
|
-
|
|
16313
|
-
|
|
16314
|
-
|
|
16315
|
-
repeated string secret_ids = 8; optional Pty pty_info = 9;
|
|
16316
|
-
bool runtime_debug = 10; string container_id = 11; map<string,string> env = 12;
|
|
16874
|
+
function fileCheckFragment(file, mode) {
|
|
16875
|
+
const check = `og_file ${file.index} ${shellQuote3(file.providerPath)} ${file.sizeBytes} ${file.sha256}`;
|
|
16876
|
+
const missing = mode === "check" ? `printf '__OGF_M__%s__' ${file.index}` : `og_m${file.index}=1`;
|
|
16877
|
+
return `if ${check}; then printf '__OGF_S__%s__' ${file.index}; else ${missing}; fi`;
|
|
16317
16878
|
}
|
|
16318
|
-
|
|
16319
|
-
|
|
16879
|
+
function directoryCreateFragment(directory) {
|
|
16880
|
+
const path = shellQuote3(directory.providerPath);
|
|
16881
|
+
return `og_dir ${directory.index} ${path} || og_mk ${directory.index} ${path}`;
|
|
16320
16882
|
}
|
|
16321
|
-
|
|
16322
|
-
|
|
16323
|
-
|
|
16324
|
-
string task_id = 1; string exec_id = 2; uint64 offset = 3; bytes data = 4; bool eof = 5;
|
|
16883
|
+
function filePutFragment(file) {
|
|
16884
|
+
if (file.base64 === void 0) throw new Error("write mode requires file content");
|
|
16885
|
+
return `[ -z "\${og_m${file.index}:-}" ] || og_put ${file.index} ${shellQuote3(file.providerPath)} ${file.sizeBytes} ${shellQuote3(file.base64)}`;
|
|
16325
16886
|
}
|
|
16326
|
-
|
|
16327
|
-
|
|
16328
|
-
|
|
16329
|
-
|
|
16330
|
-
|
|
16331
|
-
|
|
16332
|
-
|
|
16333
|
-
super(cause);
|
|
16334
|
-
this.code = code;
|
|
16335
|
-
this.name = "ModalCommandStartRejectedError";
|
|
16336
|
-
}
|
|
16337
|
-
};
|
|
16338
|
-
var ModalCommandStartPreDispatchUnavailableError = class _ModalCommandStartPreDispatchUnavailableError extends Error {
|
|
16339
|
-
constructor(cause) {
|
|
16340
|
-
super("Modal command router was not ready before Start dispatch", { cause });
|
|
16341
|
-
this.name = "ModalCommandStartPreDispatchUnavailableError";
|
|
16342
|
-
}
|
|
16343
|
-
/** The supplied operation must contain only read-only preparation, never
|
|
16344
|
-
* Start itself. Its transport failure therefore proves non-dispatch. */
|
|
16345
|
-
static async beforeDispatch(operation, signal) {
|
|
16346
|
-
signal?.throwIfAborted();
|
|
16347
|
-
try {
|
|
16348
|
-
return await operation();
|
|
16349
|
-
} catch (error) {
|
|
16350
|
-
signal?.throwIfAborted();
|
|
16351
|
-
const code = error?.code;
|
|
16352
|
-
if (error instanceof Error && (code === status.UNAVAILABLE || code === status.DEADLINE_EXCEEDED))
|
|
16353
|
-
throw new _ModalCommandStartPreDispatchUnavailableError(error);
|
|
16354
|
-
throw error;
|
|
16355
|
-
}
|
|
16356
|
-
}
|
|
16357
|
-
static async ensureReady(client, signal) {
|
|
16358
|
-
signal?.throwIfAborted();
|
|
16359
|
-
await new Promise((resolve7, reject) => {
|
|
16360
|
-
let settled = false;
|
|
16361
|
-
const finish = (error) => {
|
|
16362
|
-
if (settled) return;
|
|
16363
|
-
settled = true;
|
|
16364
|
-
signal?.removeEventListener("abort", abort);
|
|
16365
|
-
if (signal?.aborted) reject(signal.reason);
|
|
16366
|
-
else if (error) reject(new _ModalCommandStartPreDispatchUnavailableError(error));
|
|
16367
|
-
else resolve7();
|
|
16368
|
-
};
|
|
16369
|
-
const abort = () => finish();
|
|
16370
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
16371
|
-
client.waitForReady(Date.now() + 5e3, finish);
|
|
16372
|
-
if (signal?.aborted) abort();
|
|
16373
|
-
});
|
|
16374
|
-
}
|
|
16375
|
-
};
|
|
16376
|
-
var ModalCommandStartNotDispatchedError = class extends Error {
|
|
16377
|
-
constructor(cause) {
|
|
16378
|
-
super(cause instanceof Error ? cause.message : "Modal command Start was never dispatched", {
|
|
16379
|
-
cause
|
|
16380
|
-
});
|
|
16381
|
-
this.name = "ModalCommandStartNotDispatchedError";
|
|
16887
|
+
function writeFilesScript(input) {
|
|
16888
|
+
const lines = [...input.prelude];
|
|
16889
|
+
for (const directory of input.directories) lines.push(directoryCheckFragment(directory));
|
|
16890
|
+
for (const file of input.files) lines.push(fileCheckFragment(file, input.mode));
|
|
16891
|
+
if (input.mode === "write") {
|
|
16892
|
+
for (const directory of input.directories) lines.push(directoryCreateFragment(directory));
|
|
16893
|
+
for (const file of input.files) lines.push(filePutFragment(file));
|
|
16382
16894
|
}
|
|
16383
|
-
};
|
|
16384
|
-
|
|
16385
|
-
const codec = modalRouterWire.lookupType(type);
|
|
16386
|
-
return Buffer.from(codec.encode(codec.fromObject(value)).finish());
|
|
16895
|
+
lines.push(`printf '%s' ${BATCH_OK}`);
|
|
16896
|
+
return lines.join("\n");
|
|
16387
16897
|
}
|
|
16388
|
-
|
|
16389
|
-
|
|
16390
|
-
|
|
16391
|
-
|
|
16392
|
-
|
|
16393
|
-
|
|
16394
|
-
|
|
16395
|
-
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
// The HTTP/2 default 64 KiB window caps one read at 64 KiB per round
|
|
16404
|
-
// trip. Two pages lets stdout and stderr each fill a page in one trip
|
|
16405
|
-
// while bounding bytes discarded when a full read cancels its stream.
|
|
16406
|
-
"grpc-node.flow_control_window": 2 * MODAL_ROUTER_READ_PAGE_BYTES
|
|
16407
|
-
}
|
|
16408
|
-
);
|
|
16409
|
-
this.metadata = new Metadata();
|
|
16410
|
-
this.metadata.set("authorization", `Bearer ${access.jwt}`);
|
|
16898
|
+
function parseWriteFilesOutput(stdout) {
|
|
16899
|
+
const output = {
|
|
16900
|
+
complete: stdout.includes(BATCH_OK),
|
|
16901
|
+
same: [],
|
|
16902
|
+
missing: [],
|
|
16903
|
+
written: [],
|
|
16904
|
+
createdDirectories: [],
|
|
16905
|
+
failure: null
|
|
16906
|
+
};
|
|
16907
|
+
for (const match of stdout.matchAll(/__OGF_([SMWD])__(\d+)__/g)) {
|
|
16908
|
+
const index = Number(match[2]);
|
|
16909
|
+
if (match[1] === "S") output.same.push(index);
|
|
16910
|
+
else if (match[1] === "M") output.missing.push(index);
|
|
16911
|
+
else if (match[1] === "W") output.written.push(index);
|
|
16912
|
+
else output.createdDirectories.push(index);
|
|
16411
16913
|
}
|
|
16412
|
-
|
|
16413
|
-
|
|
16414
|
-
|
|
16914
|
+
const failure = /__OPENGENI_FS_(CONFLICT|UNVERIFIED|SYMLINK|NOT_DIR|NOT_FOUND|ESCAPE|WRITE_FAILED)__(?:([DF])(\d+)__)?/.exec(
|
|
16915
|
+
stdout
|
|
16916
|
+
);
|
|
16917
|
+
if (failure) {
|
|
16918
|
+
output.failure = {
|
|
16919
|
+
code: failure[1],
|
|
16920
|
+
target: failure[2] ? { kind: failure[2] === "D" ? "directory" : "file", index: Number(failure[3]) } : null
|
|
16921
|
+
};
|
|
16415
16922
|
}
|
|
16416
|
-
|
|
16417
|
-
|
|
16418
|
-
|
|
16419
|
-
|
|
16420
|
-
|
|
16421
|
-
|
|
16422
|
-
|
|
16423
|
-
|
|
16424
|
-
|
|
16425
|
-
|
|
16426
|
-
|
|
16427
|
-
|
|
16428
|
-
|
|
16429
|
-
|
|
16430
|
-
|
|
16431
|
-
|
|
16432
|
-
|
|
16433
|
-
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16437
|
-
|
|
16438
|
-
|
|
16923
|
+
return output;
|
|
16924
|
+
}
|
|
16925
|
+
|
|
16926
|
+
// src/sandbox/exec-banner.ts
|
|
16927
|
+
var typedHandleLossSessions = /* @__PURE__ */ new WeakSet();
|
|
16928
|
+
function markTypedExecHandleLoss(session) {
|
|
16929
|
+
typedHandleLossSessions.add(session);
|
|
16930
|
+
}
|
|
16931
|
+
function hasTypedExecHandleLoss(session, providerSessionId) {
|
|
16932
|
+
if (!session) return false;
|
|
16933
|
+
if (typedHandleLossSessions.has(session)) return true;
|
|
16934
|
+
const routed = session;
|
|
16935
|
+
return providerSessionId !== void 0 && routed.retainedProcessHasTypedHandleLoss?.(providerSessionId) === true;
|
|
16936
|
+
}
|
|
16937
|
+
var EXEC_BANNER_HEADER_MAX_CHARS = 16 * 1024;
|
|
16938
|
+
var OUTPUT_DELIMITER = /\r?\nOutput:\r?\n/u;
|
|
16939
|
+
var SDK_METADATA_LINE = /^(?:Chunk ID:|Wall time:|Original token count:|Output:|Process (?:running with session ID|exited with code))/mu;
|
|
16940
|
+
var RUNNING_LINE = /^Process running with session ID (\d+)$/u;
|
|
16941
|
+
var EXITED_LINE = /^Process exited with code (-?\d+)$/u;
|
|
16942
|
+
var PROCESS_STATUS_PREFIX = /^Process (?:running with session ID|exited with code)/u;
|
|
16943
|
+
function parseExecResponseBanner(raw) {
|
|
16944
|
+
const delimiter = OUTPUT_DELIMITER.exec(raw);
|
|
16945
|
+
if (!delimiter) {
|
|
16946
|
+
return SDK_METADATA_LINE.test(raw) ? { kind: "invalid" } : { kind: "absent" };
|
|
16439
16947
|
}
|
|
16440
|
-
|
|
16441
|
-
|
|
16442
|
-
|
|
16443
|
-
|
|
16444
|
-
|
|
16445
|
-
|
|
16446
|
-
|
|
16447
|
-
|
|
16448
|
-
throw new ModalCommandStartNotDispatchedError(
|
|
16449
|
-
new Error("Modal command router is closed", { cause: error })
|
|
16450
|
-
);
|
|
16451
|
-
if (error instanceof ModalCommandStartPreDispatchUnavailableError) throw error;
|
|
16452
|
-
throw new ModalCommandStartNotDispatchedError(error);
|
|
16948
|
+
if (delimiter.index > EXEC_BANNER_HEADER_MAX_CHARS) return { kind: "invalid" };
|
|
16949
|
+
const header = raw.slice(0, delimiter.index);
|
|
16950
|
+
const status4 = [];
|
|
16951
|
+
for (const line of header.split(/\r?\n/u)) {
|
|
16952
|
+
const running = RUNNING_LINE.exec(line);
|
|
16953
|
+
if (running) {
|
|
16954
|
+
status4.push({ kind: "running", value: running[1] });
|
|
16955
|
+
continue;
|
|
16453
16956
|
}
|
|
16454
|
-
|
|
16455
|
-
|
|
16456
|
-
|
|
16457
|
-
|
|
16458
|
-
"Empty",
|
|
16459
|
-
{
|
|
16460
|
-
...request,
|
|
16461
|
-
stdoutConfig: 1,
|
|
16462
|
-
stderrConfig: 1
|
|
16463
|
-
},
|
|
16464
|
-
signal
|
|
16465
|
-
);
|
|
16466
|
-
} catch (error) {
|
|
16467
|
-
const code = error?.code;
|
|
16468
|
-
if (typeof code === "number" && [
|
|
16469
|
-
status.INVALID_ARGUMENT,
|
|
16470
|
-
status.NOT_FOUND,
|
|
16471
|
-
status.PERMISSION_DENIED,
|
|
16472
|
-
status.UNAUTHENTICATED,
|
|
16473
|
-
status.UNIMPLEMENTED
|
|
16474
|
-
].includes(code))
|
|
16475
|
-
throw new ModalCommandStartRejectedError(code, error);
|
|
16476
|
-
throw new ModalCommandStartOutcomeUnknownError(request.taskId, request.execId, error);
|
|
16957
|
+
const exited = EXITED_LINE.exec(line);
|
|
16958
|
+
if (exited) {
|
|
16959
|
+
status4.push({ kind: "exited", value: exited[1] });
|
|
16960
|
+
continue;
|
|
16477
16961
|
}
|
|
16962
|
+
if (PROCESS_STATUS_PREFIX.test(line)) return { kind: "invalid" };
|
|
16478
16963
|
}
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
"Empty",
|
|
16486
|
-
{ ...identity, offset, data, eof: false },
|
|
16487
|
-
signal
|
|
16488
|
-
);
|
|
16964
|
+
if (status4.length !== 1) return { kind: "invalid" };
|
|
16965
|
+
const terminal = status4[0];
|
|
16966
|
+
const value = Number(terminal.value);
|
|
16967
|
+
if (!Number.isSafeInteger(value)) return { kind: "invalid" };
|
|
16968
|
+
if (terminal.kind === "running") {
|
|
16969
|
+
return value >= 0 ? { kind: "running", sessionId: value } : { kind: "invalid" };
|
|
16489
16970
|
}
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
|
|
16971
|
+
return { kind: "exited", exitCode: value };
|
|
16972
|
+
}
|
|
16973
|
+
function parseExecBannerSessionId(raw) {
|
|
16974
|
+
const banner = parseExecResponseBanner(raw);
|
|
16975
|
+
return banner.kind === "running" ? banner.sessionId : null;
|
|
16976
|
+
}
|
|
16977
|
+
function parseExecBannerExitCode(raw) {
|
|
16978
|
+
const banner = parseExecResponseBanner(raw);
|
|
16979
|
+
return banner.kind === "exited" ? banner.exitCode : null;
|
|
16980
|
+
}
|
|
16981
|
+
function isExecSessionLostBanner(out, execSessionId, source) {
|
|
16982
|
+
if (source && typedHandleLossSessions.has(source)) return false;
|
|
16983
|
+
if (!out || !Number.isSafeInteger(execSessionId) || execSessionId < 0) return false;
|
|
16984
|
+
const delimiter = OUTPUT_DELIMITER.exec(out);
|
|
16985
|
+
if (delimiter && delimiter.index > EXEC_BANNER_HEADER_MAX_CHARS) return false;
|
|
16986
|
+
if (delimiter && parseExecResponseBanner(out).kind !== "exited") return false;
|
|
16987
|
+
const candidate = delimiter ? out.slice(delimiter.index + delimiter[0].length) : out;
|
|
16988
|
+
const match = candidate.match(/^(?:write_stdin failed: )?session not found: (\d+)$/);
|
|
16989
|
+
if (!match || match[0] !== candidate) return false;
|
|
16990
|
+
return match[1] === String(execSessionId);
|
|
16991
|
+
}
|
|
16992
|
+
|
|
16993
|
+
// src/sandbox/op-correlation.ts
|
|
16994
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
16995
|
+
var storage = new AsyncLocalStorage3();
|
|
16996
|
+
function sanitizeOpIdToken(raw) {
|
|
16997
|
+
return raw.replace(/[^A-Za-z0-9_-]/g, (c) => `_${c.charCodeAt(0).toString(16)}_`);
|
|
16998
|
+
}
|
|
16999
|
+
function runWithToolCallCorrelation(callId, fn, options = {}) {
|
|
17000
|
+
return storage.run(
|
|
17001
|
+
{
|
|
17002
|
+
callId: sanitizeOpIdToken(callId),
|
|
17003
|
+
ordinal: 0,
|
|
17004
|
+
...options.onDurableOpOwnershipTransferStarted ? { onDurableOpOwnershipTransferStarted: options.onDurableOpOwnershipTransferStarted } : {},
|
|
17005
|
+
...options.onDurableOpOwnershipTransferred ? { onDurableOpOwnershipTransferred: options.onDurableOpOwnershipTransferred } : {}
|
|
17006
|
+
},
|
|
17007
|
+
fn
|
|
17008
|
+
);
|
|
17009
|
+
}
|
|
17010
|
+
function nextDurableOpId() {
|
|
17011
|
+
const context = storage.getStore();
|
|
17012
|
+
if (!context) {
|
|
16495
17013
|
return null;
|
|
16496
17014
|
}
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16507
|
-
prefix + "TaskExecStdioRead",
|
|
16508
|
-
(value) => encode("Read", value),
|
|
16509
|
-
(bytes) => modalRouterWire.lookupType("Data").decode(bytes),
|
|
16510
|
-
{ ...identity, offset, fileDescriptor: stream === "stdout" ? 0 : 1 },
|
|
16511
|
-
this.metadata,
|
|
16512
|
-
{ deadline: Date.now() + Math.max(1, waitMs) }
|
|
16513
|
-
);
|
|
16514
|
-
const abort = () => call.cancel();
|
|
16515
|
-
const finish = (eof, error) => {
|
|
16516
|
-
signal?.removeEventListener("abort", abort);
|
|
16517
|
-
if (signal?.aborted) reject(signal.reason);
|
|
16518
|
-
else if (error) reject(error);
|
|
16519
|
-
else resolve7({ bytes: Buffer.concat(chunks, length), eof });
|
|
16520
|
-
};
|
|
16521
|
-
call.on("data", (value) => {
|
|
16522
|
-
if (limited) return;
|
|
16523
|
-
const part = Buffer.from(value.data).subarray(0, MODAL_ROUTER_READ_PAGE_BYTES - length);
|
|
16524
|
-
if (part.length) {
|
|
16525
|
-
chunks.push(part);
|
|
16526
|
-
length += part.length;
|
|
16527
|
-
}
|
|
16528
|
-
if (length === MODAL_ROUTER_READ_PAGE_BYTES) {
|
|
16529
|
-
limited = true;
|
|
16530
|
-
call.cancel();
|
|
16531
|
-
}
|
|
16532
|
-
});
|
|
16533
|
-
call.once("error", (error) => {
|
|
16534
|
-
if (limited && error.code === status.CANCELLED || error.code === status.DEADLINE_EXCEEDED)
|
|
16535
|
-
finish(false);
|
|
16536
|
-
else finish(false, error);
|
|
16537
|
-
});
|
|
16538
|
-
call.once("end", () => finish(!limited));
|
|
16539
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
16540
|
-
if (signal?.aborted) abort();
|
|
16541
|
-
});
|
|
16542
|
-
}
|
|
16543
|
-
};
|
|
17015
|
+
const ordinal = context.ordinal;
|
|
17016
|
+
context.ordinal += 1;
|
|
17017
|
+
return `${context.callId}:${ordinal}`;
|
|
17018
|
+
}
|
|
17019
|
+
function notifyDurableOpOwnershipTransferStarted(opId) {
|
|
17020
|
+
storage.getStore()?.onDurableOpOwnershipTransferStarted?.(opId);
|
|
17021
|
+
}
|
|
17022
|
+
function notifyDurableOpOwnershipTransferred(opId) {
|
|
17023
|
+
storage.getStore()?.onDurableOpOwnershipTransferred?.(opId);
|
|
17024
|
+
}
|
|
16544
17025
|
|
|
16545
17026
|
// src/sandbox/routing/routing-session.ts
|
|
16546
|
-
import {
|
|
17027
|
+
import { SandboxFilesystemNotFoundError } from "modal";
|
|
17028
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
16547
17029
|
|
|
16548
17030
|
// src/sandbox/materialization-verification-error.ts
|
|
16549
17031
|
var EXPLANATIONS = {
|
|
@@ -17615,6 +18097,11 @@ var RoutingSandboxSession = class {
|
|
|
17615
18097
|
() => write.call(record.backend.session, args)
|
|
17616
18098
|
);
|
|
17617
18099
|
} catch (error) {
|
|
18100
|
+
let inputUnknown = false;
|
|
18101
|
+
try {
|
|
18102
|
+
inputUnknown = error instanceof ProviderCommandInputOutcomeUnknownError;
|
|
18103
|
+
} catch {
|
|
18104
|
+
}
|
|
17618
18105
|
if (this.deps.afterProcessMutation) {
|
|
17619
18106
|
const pending = {
|
|
17620
18107
|
op,
|
|
@@ -17629,11 +18116,21 @@ var RoutingSandboxSession = class {
|
|
|
17629
18116
|
record.pendingMutationSettlement = pending;
|
|
17630
18117
|
throw new RoutingMutationOutcomeUnknownError(
|
|
17631
18118
|
op,
|
|
17632
|
-
|
|
17633
|
-
|
|
18119
|
+
inputUnknown ? "Retained-process stdin acknowledgement and durable settlement unavailable; input may have been accepted. Do not resend stdin." : "Retained-process stdin rejected at the provider but lost durable settlement; it was not replayed",
|
|
18120
|
+
inputUnknown ? {
|
|
18121
|
+
cause: new AggregateError([error, settlementError]),
|
|
18122
|
+
retainedProcess: record.process
|
|
18123
|
+
} : { cause: settlementError }
|
|
17634
18124
|
);
|
|
17635
18125
|
}
|
|
17636
18126
|
}
|
|
18127
|
+
if (inputUnknown) {
|
|
18128
|
+
throw new RoutingMutationOutcomeUnknownError(
|
|
18129
|
+
op,
|
|
18130
|
+
"Provider stdin acknowledgement unavailable; input may have been accepted and was not resent. Do not resend stdin.",
|
|
18131
|
+
{ cause: error, retainedProcess: record.process }
|
|
18132
|
+
);
|
|
18133
|
+
}
|
|
17637
18134
|
throw error;
|
|
17638
18135
|
}
|
|
17639
18136
|
if (this.deps.afterProcessMutation) {
|
|
@@ -17993,7 +18490,7 @@ var RoutingSandboxSession = class {
|
|
|
17993
18490
|
{ retainedProcess: process2 }
|
|
17994
18491
|
);
|
|
17995
18492
|
const persisted = await this.deps.providerCommandPersistence(process2).load();
|
|
17996
|
-
if (!persisted || !
|
|
18493
|
+
if (!persisted || !isDeepStrictEqual2(persisted, command))
|
|
17997
18494
|
throw new Error(
|
|
17998
18495
|
"Supervised launch reservation did not retain the exact invocation"
|
|
17999
18496
|
);
|
|
@@ -18362,7 +18859,13 @@ var RoutingSandboxSession = class {
|
|
|
18362
18859
|
async writeStdin(args) {
|
|
18363
18860
|
const providerSessionId = providerSessionIdFromArgs(args);
|
|
18364
18861
|
if (providerSessionId !== null && this.retainedProcesses.has(providerSessionId)) {
|
|
18365
|
-
|
|
18862
|
+
try {
|
|
18863
|
+
return await this.dispatchProcessMutation(args);
|
|
18864
|
+
} catch (error) {
|
|
18865
|
+
if (isRoutingMutationOutcomeUnknownError(error))
|
|
18866
|
+
return renderRoutingMutationOutcomeUnknownToolResult(error);
|
|
18867
|
+
throw error;
|
|
18868
|
+
}
|
|
18366
18869
|
}
|
|
18367
18870
|
return this.dispatch("writeStdin", true, async (s) => {
|
|
18368
18871
|
if (!s.writeStdin) {
|
|
@@ -18383,6 +18886,18 @@ var RoutingSandboxSession = class {
|
|
|
18383
18886
|
hasRetainedProcess(providerSessionId) {
|
|
18384
18887
|
return positiveProviderSessionId(providerSessionId) !== null && this.retainedProcesses.has(providerSessionId);
|
|
18385
18888
|
}
|
|
18889
|
+
/** A reaper may have settled the command while a local capture/control receipt
|
|
18890
|
+
* remained pending. Cleanup may consume that same durable proof without
|
|
18891
|
+
* replaying a provider operation or accepting pending output into the model. */
|
|
18892
|
+
async reconcileRetainedProcess(providerSessionId) {
|
|
18893
|
+
const record = this.retainedProcesses.get(providerSessionId);
|
|
18894
|
+
if (!record || !this.deps.isProcessSettled) return false;
|
|
18895
|
+
if (!await this.deps.isProcessSettled({ backend: record.backend, process: record.process }))
|
|
18896
|
+
return false;
|
|
18897
|
+
if (this.retainedProcesses.get(providerSessionId) !== record) return false;
|
|
18898
|
+
this.retainedProcesses.delete(providerSessionId);
|
|
18899
|
+
return true;
|
|
18900
|
+
}
|
|
18386
18901
|
/** Local, Docker, and OpenSandbox process ids address an in-memory table on one worker
|
|
18387
18902
|
* session object. They are not valid durable locators for the independently
|
|
18388
18903
|
* scheduled reaper, so their yielded handles stay turn-owned until terminal
|
|
@@ -18583,40 +19098,15 @@ var RoutingSandboxSession = class {
|
|
|
18583
19098
|
async writePlacementPrivate(args) {
|
|
18584
19099
|
const input = placementPrivateWrite(args);
|
|
18585
19100
|
return this.dispatch("writePlacementPrivate", false, async (session, backend) => {
|
|
18586
|
-
|
|
18587
|
-
if (session.writeFile) return await session.writeFile(input);
|
|
18588
|
-
return await streamPlacementPrivateFile(session, input, backend.kind);
|
|
19101
|
+
return await writePlacementPrivateOnBackend(session, input, backend.kind);
|
|
18589
19102
|
});
|
|
18590
19103
|
}
|
|
18591
19104
|
/** Delete only an OpenGeni placement-private staging file. This narrow
|
|
18592
19105
|
* control operation cannot be repurposed into a generic mutation bypass. */
|
|
18593
19106
|
async deletePlacementPrivate(path, runAs) {
|
|
18594
19107
|
const privatePath = placementPrivatePath(path);
|
|
18595
|
-
await this.dispatch("deletePlacementPrivate", false, async (session) => {
|
|
18596
|
-
|
|
18597
|
-
await session.deletePlacementPrivate(privatePath, runAs);
|
|
18598
|
-
return;
|
|
18599
|
-
}
|
|
18600
|
-
const args = {
|
|
18601
|
-
cmd: `rm -f ${shellSingleQuote(privatePath)}`,
|
|
18602
|
-
...runAs ? { runAs } : {}
|
|
18603
|
-
};
|
|
18604
|
-
if (session.exec) {
|
|
18605
|
-
const result = await session.exec(args);
|
|
18606
|
-
if (result && typeof result === "object" && typeof result.exitCode === "number" && result.exitCode !== 0) {
|
|
18607
|
-
throw new Error("placement-private cleanup failed");
|
|
18608
|
-
}
|
|
18609
|
-
return;
|
|
18610
|
-
}
|
|
18611
|
-
if (session.execCommand) {
|
|
18612
|
-
const result = await session.execCommand(args);
|
|
18613
|
-
const exitCode = parseExecBannerExitCode(result);
|
|
18614
|
-
if (exitCode !== null && exitCode !== 0) {
|
|
18615
|
-
throw new Error("placement-private cleanup failed");
|
|
18616
|
-
}
|
|
18617
|
-
return;
|
|
18618
|
-
}
|
|
18619
|
-
throw new RoutingUnsupportedError("deletePlacementPrivate", this.cached?.kind ?? "unknown");
|
|
19108
|
+
await this.dispatch("deletePlacementPrivate", false, async (session, backend) => {
|
|
19109
|
+
await deletePlacementPrivateOnBackend(session, privatePath, runAs, backend.kind);
|
|
18620
19110
|
});
|
|
18621
19111
|
}
|
|
18622
19112
|
/** Keep private download authority and its consuming import on one exact
|
|
@@ -18625,7 +19115,7 @@ var RoutingSandboxSession = class {
|
|
|
18625
19115
|
async importWorkspaceFileOnResolvedBackend(input) {
|
|
18626
19116
|
return await this.dispatch("importWorkspaceFile", true, async (session, backend) => {
|
|
18627
19117
|
const channel = new SandboxChannelAService({
|
|
18628
|
-
session,
|
|
19118
|
+
session: withPlacementPrivateControl(session, backend.kind),
|
|
18629
19119
|
workspaceRoot: input.workspaceRoot,
|
|
18630
19120
|
...backend.kind === "selfhosted" ? { providerPathMode: "workspace-relative" } : {},
|
|
18631
19121
|
revision: input.revision,
|
|
@@ -18641,7 +19131,7 @@ var RoutingSandboxSession = class {
|
|
|
18641
19131
|
async importWorkspaceFilesOnResolvedBackend(input) {
|
|
18642
19132
|
return await this.dispatch("importWorkspaceFiles", true, async (session, backend) => {
|
|
18643
19133
|
const channel = new SandboxChannelAService({
|
|
18644
|
-
session,
|
|
19134
|
+
session: withPlacementPrivateControl(session, backend.kind),
|
|
18645
19135
|
workspaceRoot: input.workspaceRoot,
|
|
18646
19136
|
...backend.kind === "selfhosted" ? { providerPathMode: "workspace-relative" } : {},
|
|
18647
19137
|
revision: input.revision,
|
|
@@ -18875,8 +19365,59 @@ function placementPrivateWrite(value) {
|
|
|
18875
19365
|
...typeof input.runAs === "string" ? { runAs: input.runAs } : {}
|
|
18876
19366
|
};
|
|
18877
19367
|
}
|
|
19368
|
+
function withPlacementPrivateControl(session, backendKind) {
|
|
19369
|
+
return new Proxy(session, {
|
|
19370
|
+
get(target, property) {
|
|
19371
|
+
if (property === "writePlacementPrivate") {
|
|
19372
|
+
return async (args) => await writePlacementPrivateOnBackend(target, placementPrivateWrite(args), backendKind);
|
|
19373
|
+
}
|
|
19374
|
+
if (property === "deletePlacementPrivate") {
|
|
19375
|
+
return async (path, runAs) => await deletePlacementPrivateOnBackend(
|
|
19376
|
+
target,
|
|
19377
|
+
placementPrivatePath(path),
|
|
19378
|
+
runAs,
|
|
19379
|
+
backendKind
|
|
19380
|
+
);
|
|
19381
|
+
}
|
|
19382
|
+
const value = Reflect.get(target, property, target);
|
|
19383
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
19384
|
+
}
|
|
19385
|
+
});
|
|
19386
|
+
}
|
|
19387
|
+
async function writePlacementPrivateOnBackend(session, input, backendKind) {
|
|
19388
|
+
if (session.writePlacementPrivate) return await session.writePlacementPrivate(input);
|
|
19389
|
+
if (session.writeFile) return await session.writeFile(input);
|
|
19390
|
+
return await streamPlacementPrivateFile(session, input, backendKind);
|
|
19391
|
+
}
|
|
19392
|
+
async function deletePlacementPrivateOnBackend(session, privatePath, runAs, backendKind) {
|
|
19393
|
+
if (session.deletePlacementPrivate) {
|
|
19394
|
+
await session.deletePlacementPrivate(privatePath, runAs);
|
|
19395
|
+
return;
|
|
19396
|
+
}
|
|
19397
|
+
const args = {
|
|
19398
|
+
cmd: `rm -f ${shellSingleQuote(privatePath)}`,
|
|
19399
|
+
...runAs ? { runAs } : {}
|
|
19400
|
+
};
|
|
19401
|
+
if (session.exec) {
|
|
19402
|
+
const result = await session.exec(args);
|
|
19403
|
+
if (result && typeof result === "object" && typeof result.exitCode === "number" && result.exitCode !== 0) {
|
|
19404
|
+
throw new Error("placement-private cleanup failed");
|
|
19405
|
+
}
|
|
19406
|
+
return;
|
|
19407
|
+
}
|
|
19408
|
+
if (session.execCommand) {
|
|
19409
|
+
const result = await session.execCommand(args);
|
|
19410
|
+
const exitCode = parseExecBannerExitCode(result);
|
|
19411
|
+
if (exitCode !== null && exitCode !== 0) {
|
|
19412
|
+
throw new Error("placement-private cleanup failed");
|
|
19413
|
+
}
|
|
19414
|
+
return;
|
|
19415
|
+
}
|
|
19416
|
+
throw new RoutingUnsupportedError("deletePlacementPrivate", backendKind);
|
|
19417
|
+
}
|
|
18878
19418
|
async function streamPlacementPrivateFile(session, input, backendKind) {
|
|
18879
|
-
|
|
19419
|
+
const exec = session.exec?.bind(session) ?? session.execCommand?.bind(session);
|
|
19420
|
+
if (!exec || !session.writeStdin) {
|
|
18880
19421
|
throw new RoutingUnsupportedError("writePlacementPrivate", backendKind);
|
|
18881
19422
|
}
|
|
18882
19423
|
const bytes = typeof input.content === "string" ? Buffer.from(input.content) : input.content;
|
|
@@ -18887,7 +19428,7 @@ async function streamPlacementPrivateFile(session, input, backendKind) {
|
|
|
18887
19428
|
...input.createParents ? [`install -d -m 0700 -- ${shellSingleQuote(parent)}`] : []
|
|
18888
19429
|
];
|
|
18889
19430
|
if (bytes.byteLength === 0) {
|
|
18890
|
-
const result = await
|
|
19431
|
+
const result = await exec({
|
|
18891
19432
|
cmd: [
|
|
18892
19433
|
...prelude,
|
|
18893
19434
|
`: > ${shellSingleQuote(input.path)}`,
|
|
@@ -18914,7 +19455,7 @@ async function streamPlacementPrivateFile(session, input, backendKind) {
|
|
|
18914
19455
|
`chmod 0600 -- ${shellSingleQuote(input.path)}`,
|
|
18915
19456
|
`printf %s ${shellSingleQuote(marker)}`
|
|
18916
19457
|
].join("; ");
|
|
18917
|
-
const started = await
|
|
19458
|
+
const started = await exec({
|
|
18918
19459
|
cmd: command,
|
|
18919
19460
|
...input.runAs ? { runAs: input.runAs } : {},
|
|
18920
19461
|
yieldTimeMs: 250,
|
|
@@ -19179,8 +19720,14 @@ function cancellableShellCommand(command, markerPath) {
|
|
|
19179
19720
|
'case "$__opengeni_outer_pid:$__opengeni_outer_pgid" in *[!0-9:]*|*:|:*) exit 125 ;; esac',
|
|
19180
19721
|
'if [ "$__opengeni_outer_pid" != "$__opengeni_outer_pgid" ]; then',
|
|
19181
19722
|
' __opengeni_setsid="$(command -v setsid 2>/dev/null)"',
|
|
19182
|
-
' [ -n "$__opengeni_setsid" ]
|
|
19183
|
-
`
|
|
19723
|
+
' if [ -n "$__opengeni_setsid" ]; then',
|
|
19724
|
+
` exec "$__opengeni_setsid" /bin/sh -c ${singleQuote(groupLeaderCommand)}`,
|
|
19725
|
+
" fi",
|
|
19726
|
+
// macOS has setsid(2), but no setsid executable. The parent is proven
|
|
19727
|
+
// not to be a group leader, so the same process can safely start a session.
|
|
19728
|
+
' __opengeni_python="$(command -v python3 2>/dev/null)"',
|
|
19729
|
+
' [ -n "$__opengeni_python" ] || exit 125',
|
|
19730
|
+
` exec "$__opengeni_python" -c ${singleQuote('import os,sys; os.setsid(); os.execv("/bin/sh", ["/bin/sh", "-c", sys.argv[1]])')} ${singleQuote(groupLeaderCommand)}`,
|
|
19184
19731
|
"fi",
|
|
19185
19732
|
groupLeaderCommand
|
|
19186
19733
|
].join("\n");
|
|
@@ -19282,6 +19829,12 @@ function retainedProcessSession(session, providerSessionId) {
|
|
|
19282
19829
|
return session?.hasRetainedProcess?.(providerSessionId) === true ? session : null;
|
|
19283
19830
|
}
|
|
19284
19831
|
function renderDirectToolFault(error, retainedProcessSessionId) {
|
|
19832
|
+
if (error instanceof ProviderCommandInputOutcomeUnknownError) {
|
|
19833
|
+
return `Command input acknowledgement unavailable${retainedProcessSessionId === void 0 ? "" : ` for session ID ${retainedProcessSessionId}`}. The input may have been accepted; its outcome is unknown and it was not resent. Do not resend stdin. Inspect the existing command with write_stdin using empty chars.`;
|
|
19834
|
+
}
|
|
19835
|
+
if (isProviderCommandObservationUnavailableError(error)) {
|
|
19836
|
+
return `Command observation unavailable${retainedProcessSessionId === void 0 ? "" : ` for session ID ${retainedProcessSessionId}`}. Outcome unknown; the original invocation remains retained. Do not replay the command or resend stdin; observe the existing command.`;
|
|
19837
|
+
}
|
|
19285
19838
|
try {
|
|
19286
19839
|
const terminal = error;
|
|
19287
19840
|
if (retainedProcessSessionId !== void 0 && Number.isSafeInteger(retainedProcessSessionId) && terminal.name === "SandboxRetainedProcessTerminalError" && terminal.code === "process_fenced") {
|
|
@@ -19353,6 +19906,7 @@ function wrapComputer(computer, track) {
|
|
|
19353
19906
|
}
|
|
19354
19907
|
var TurnToolCancellationControllerImpl = class {
|
|
19355
19908
|
cancelled = false;
|
|
19909
|
+
observationCancellation = new AbortController();
|
|
19356
19910
|
reason;
|
|
19357
19911
|
inFlight = /* @__PURE__ */ new Set();
|
|
19358
19912
|
shellSessions = /* @__PURE__ */ new Map();
|
|
@@ -19375,6 +19929,7 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19375
19929
|
if (!this.cancelled) {
|
|
19376
19930
|
this.cancelled = true;
|
|
19377
19931
|
this.reason = reason;
|
|
19932
|
+
this.observationCancellation.abort(cancellationError(reason));
|
|
19378
19933
|
this.signal?.removeEventListener("abort", this.onAbort);
|
|
19379
19934
|
}
|
|
19380
19935
|
void this.ensureDrain().catch(() => void 0);
|
|
@@ -19422,6 +19977,7 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19422
19977
|
}
|
|
19423
19978
|
const directArgs = {
|
|
19424
19979
|
sessionId: parsed.session_id,
|
|
19980
|
+
signal: this.observationCancellation.signal,
|
|
19425
19981
|
...typeof parsed.chars === "string" ? { chars: parsed.chars } : {},
|
|
19426
19982
|
...typeof parsed.yield_time_ms === "number" ? { yieldTimeMs: parsed.yield_time_ms } : {},
|
|
19427
19983
|
...typeof parsed.max_output_tokens === "number" ? { maxOutputTokens: parsed.max_output_tokens } : {}
|
|
@@ -19808,6 +20364,7 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19808
20364
|
const directProcessSession = sessionId === null ? null : retainedProcessSession(cancellationSession, sessionId);
|
|
19809
20365
|
const typedHandleLoss = sessionId !== null && (hasTypedExecHandleLoss(cancellationSession, sessionId) || this.shellSessions.get(sessionId)?.typedHandleLoss === true);
|
|
19810
20366
|
let output;
|
|
20367
|
+
let initialObservationFailure;
|
|
19811
20368
|
if (sessionId !== null && directProcessSession?.writeStdinForProcessMutation) {
|
|
19812
20369
|
try {
|
|
19813
20370
|
output = await directProcessSession.writeStdinForProcessMutation({
|
|
@@ -19817,7 +20374,10 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19817
20374
|
...typeof parsed?.max_output_tokens === "number" ? { maxOutputTokens: parsed.max_output_tokens } : {}
|
|
19818
20375
|
});
|
|
19819
20376
|
} catch (error) {
|
|
19820
|
-
|
|
20377
|
+
if (!(error instanceof ProviderCommandObservationUnavailableError))
|
|
20378
|
+
return renderDirectToolFault(error, sessionId);
|
|
20379
|
+
initialObservationFailure = error;
|
|
20380
|
+
output = "";
|
|
19821
20381
|
}
|
|
19822
20382
|
} else {
|
|
19823
20383
|
output = await tool.invoke(runContext, cappedInput, details);
|
|
@@ -19863,6 +20423,7 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19863
20423
|
return state && typeof output === "string" ? await this.awaitModelFacingShellResult({
|
|
19864
20424
|
state,
|
|
19865
20425
|
initialOutput: output,
|
|
20426
|
+
...initialObservationFailure ? { initialObservationFailure } : {},
|
|
19866
20427
|
startedAt,
|
|
19867
20428
|
waitMs: modelWaitMs(parsed?.yield_time_ms),
|
|
19868
20429
|
maxOutputTokens: typeof parsed?.max_output_tokens === "number" ? parsed.max_output_tokens : 2e4
|
|
@@ -19887,11 +20448,13 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19887
20448
|
this.shellSessions.delete(state.sessionId);
|
|
19888
20449
|
return input.initialOutput;
|
|
19889
20450
|
}
|
|
19890
|
-
if (parseExecBannerSessionId(input.initialOutput) !== state.sessionId) {
|
|
20451
|
+
if (!input.initialObservationFailure && parseExecBannerSessionId(input.initialOutput) !== state.sessionId) {
|
|
19891
20452
|
return input.initialOutput;
|
|
19892
20453
|
}
|
|
19893
20454
|
let output = appendBoundedOutput3("", execOutput(input.initialOutput), maxOutputTokens);
|
|
20455
|
+
let observationFailure = input.initialObservationFailure ?? null;
|
|
19894
20456
|
for (; ; ) {
|
|
20457
|
+
if (observationFailure?.readRetryAllowed === false) break;
|
|
19895
20458
|
if (performance.now() - startedAt >= waitMs) break;
|
|
19896
20459
|
if (this.cancelled) throw cancellationError(this.reason);
|
|
19897
20460
|
if (!state.writeInvoke && !state.processSession?.writeStdinForProcessRead && !state.processSession?.writeStdinForProcessControl) {
|
|
@@ -19903,21 +20466,33 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19903
20466
|
if (remainingMs <= 0) break;
|
|
19904
20467
|
const yieldTimeMs = Math.min(TURN_PROVIDER_YIELD_SLICE_MS, Math.ceil(remainingMs));
|
|
19905
20468
|
const read = state.processSession?.writeStdinForProcessRead ?? state.processSession?.writeStdinForProcessControl;
|
|
19906
|
-
|
|
19907
|
-
|
|
19908
|
-
|
|
19909
|
-
|
|
19910
|
-
maxOutputTokens
|
|
19911
|
-
}) : await state.writeInvoke(
|
|
19912
|
-
state.runContext,
|
|
19913
|
-
JSON.stringify({
|
|
19914
|
-
session_id: state.sessionId,
|
|
20469
|
+
let next;
|
|
20470
|
+
try {
|
|
20471
|
+
next = read ? await read.call(state.processSession, {
|
|
20472
|
+
sessionId: state.sessionId,
|
|
19915
20473
|
chars: "",
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
|
|
19919
|
-
|
|
19920
|
-
|
|
20474
|
+
yieldTimeMs,
|
|
20475
|
+
maxOutputTokens,
|
|
20476
|
+
signal: this.observationCancellation.signal
|
|
20477
|
+
}) : await state.writeInvoke(
|
|
20478
|
+
state.runContext,
|
|
20479
|
+
JSON.stringify({
|
|
20480
|
+
session_id: state.sessionId,
|
|
20481
|
+
chars: "",
|
|
20482
|
+
yield_time_ms: yieldTimeMs,
|
|
20483
|
+
max_output_tokens: maxOutputTokens
|
|
20484
|
+
}),
|
|
20485
|
+
void 0
|
|
20486
|
+
);
|
|
20487
|
+
} catch (error) {
|
|
20488
|
+
if (this.cancelled) throw cancellationError(this.reason);
|
|
20489
|
+
if (!(error instanceof ProviderCommandObservationUnavailableError)) throw error;
|
|
20490
|
+
observationFailure = error;
|
|
20491
|
+
if (!error.readRetryAllowed) break;
|
|
20492
|
+
await delay(Math.min(SHELL_POLL_MS, Math.max(0, waitMs - (performance.now() - startedAt))));
|
|
20493
|
+
continue;
|
|
20494
|
+
}
|
|
20495
|
+
observationFailure = null;
|
|
19921
20496
|
if (this.cancelled) throw cancellationError(this.reason);
|
|
19922
20497
|
if (typeof next !== "string")
|
|
19923
20498
|
throw new Error("Retained command read returned no provider status");
|
|
@@ -19937,6 +20512,13 @@ var TurnToolCancellationControllerImpl = class {
|
|
|
19937
20512
|
}
|
|
19938
20513
|
await delay(Math.min(SHELL_POLL_MS, Math.max(0, remainingMs)));
|
|
19939
20514
|
}
|
|
20515
|
+
if (observationFailure) {
|
|
20516
|
+
const commandId = state.processSession?.retainedProcessIdentity?.(state.sessionId)?.id;
|
|
20517
|
+
return `${renderDirectToolFault(observationFailure, state.sessionId)}${commandId ? `
|
|
20518
|
+
Command ID: ${commandId}` : ""}
|
|
20519
|
+
Output:
|
|
20520
|
+
${output}`;
|
|
20521
|
+
}
|
|
19940
20522
|
if (!canAdoptInBackground) {
|
|
19941
20523
|
return `${runningCommandBanner(state.sessionId, output)}
|
|
19942
20524
|
This process is turn-scoped; it will stop when this turn ends or is interrupted.
|
|
@@ -20017,7 +20599,13 @@ This process is turn-scoped; it will stop when this turn ends or is interrupted.
|
|
|
20017
20599
|
return promise;
|
|
20018
20600
|
}
|
|
20019
20601
|
ensureDrain() {
|
|
20020
|
-
this.drainPromise
|
|
20602
|
+
if (!this.drainPromise) {
|
|
20603
|
+
const drain = this.drain();
|
|
20604
|
+
this.drainPromise = drain;
|
|
20605
|
+
void drain.catch(() => {
|
|
20606
|
+
if (this.drainPromise === drain) this.drainPromise = null;
|
|
20607
|
+
});
|
|
20608
|
+
}
|
|
20021
20609
|
return this.drainPromise;
|
|
20022
20610
|
}
|
|
20023
20611
|
async drain() {
|
|
@@ -20160,8 +20748,43 @@ This process is turn-scoped; it will stop when this turn ends or is interrupted.
|
|
|
20160
20748
|
});
|
|
20161
20749
|
return state.cancellation;
|
|
20162
20750
|
}
|
|
20751
|
+
async reconcileSettledShellSession(state) {
|
|
20752
|
+
try {
|
|
20753
|
+
if (await state.processSession?.reconcileRetainedProcess?.(state.sessionId)) {
|
|
20754
|
+
this.shellSessions.delete(state.sessionId);
|
|
20755
|
+
return true;
|
|
20756
|
+
}
|
|
20757
|
+
} catch {
|
|
20758
|
+
}
|
|
20759
|
+
return false;
|
|
20760
|
+
}
|
|
20761
|
+
async awaitShellControl(state, operation) {
|
|
20762
|
+
if (!state.processSession?.reconcileRetainedProcess)
|
|
20763
|
+
return { reconciled: false, value: await operation };
|
|
20764
|
+
const observed = operation.then(
|
|
20765
|
+
(value) => ({ kind: "resolved", value }),
|
|
20766
|
+
(error) => ({ kind: "rejected", error })
|
|
20767
|
+
);
|
|
20768
|
+
while (true) {
|
|
20769
|
+
const result = await Promise.race([
|
|
20770
|
+
observed,
|
|
20771
|
+
delay(SHELL_POLL_MS).then(() => ({ kind: "pending" }))
|
|
20772
|
+
]);
|
|
20773
|
+
if (result.kind === "resolved") return { reconciled: false, value: result.value };
|
|
20774
|
+
if (result.kind === "rejected") throw result.error;
|
|
20775
|
+
if (await this.reconcileSettledShellSession(state)) return { reconciled: true };
|
|
20776
|
+
}
|
|
20777
|
+
}
|
|
20163
20778
|
async cancelShellSessionOnce(state) {
|
|
20164
|
-
if (await
|
|
20779
|
+
if (await this.reconcileSettledShellSession(state)) return;
|
|
20780
|
+
const nativeCancellation = await this.awaitShellControl(
|
|
20781
|
+
state,
|
|
20782
|
+
Promise.resolve(
|
|
20783
|
+
state.processSession?.cancelSupervisedCommand?.(state.sessionId, "explicit_stop")
|
|
20784
|
+
)
|
|
20785
|
+
);
|
|
20786
|
+
if (nativeCancellation.reconciled) return;
|
|
20787
|
+
if (nativeCancellation.value) {
|
|
20165
20788
|
while (state.processSession?.hasRetainedProcess?.(state.sessionId) === true) {
|
|
20166
20789
|
if (await this.rawWrite(state, "", SHELL_POLL_MS)) {
|
|
20167
20790
|
await this.forgetShellSessionAfterExactSettlement(state);
|
|
@@ -20183,12 +20806,17 @@ This process is turn-scoped; it will stop when this turn ends or is interrupted.
|
|
|
20183
20806
|
}
|
|
20184
20807
|
if (state.token && state.processSession?.execCommandForProcessControl && state.processSession.writeStdinForProcessControl) {
|
|
20185
20808
|
while (state.processSession.hasRetainedProcess?.(state.sessionId) === true) {
|
|
20809
|
+
if (await this.reconcileSettledShellSession(state)) return;
|
|
20186
20810
|
try {
|
|
20187
|
-
const
|
|
20188
|
-
state
|
|
20189
|
-
|
|
20811
|
+
const control = await this.awaitShellControl(
|
|
20812
|
+
state,
|
|
20813
|
+
state.processSession.execCommandForProcessControl(
|
|
20814
|
+
state.sessionId,
|
|
20815
|
+
shellHelperArgs(retainedShellCancellationCommand(state))
|
|
20816
|
+
)
|
|
20190
20817
|
);
|
|
20191
|
-
|
|
20818
|
+
if (control.reconciled) return;
|
|
20819
|
+
const exitCode = parseExecBannerExitCode(control.value);
|
|
20192
20820
|
if (exitCode === 0 || exitCode === RETAINED_SHELL_MARKER_PENDING_EXIT_CODE) {
|
|
20193
20821
|
await this.forgetShellSessionAfterExactSettlement(state);
|
|
20194
20822
|
return;
|
|
@@ -20251,23 +20879,29 @@ This process is turn-scoped; it will stop when this turn ends or is interrupted.
|
|
|
20251
20879
|
this.shellSessions.delete(state.sessionId);
|
|
20252
20880
|
}
|
|
20253
20881
|
async rawWrite(state, chars, yieldTimeMs) {
|
|
20882
|
+
if (await this.reconcileSettledShellSession(state)) return true;
|
|
20254
20883
|
if (!state.writeInvoke && !state.processSession?.writeStdinForProcessControl) return false;
|
|
20255
20884
|
try {
|
|
20256
|
-
const
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
|
|
20260
|
-
maxOutputTokens: 128
|
|
20261
|
-
}) : await state.writeInvoke(
|
|
20262
|
-
state.runContext,
|
|
20263
|
-
JSON.stringify({
|
|
20264
|
-
session_id: state.sessionId,
|
|
20885
|
+
const control = await this.awaitShellControl(
|
|
20886
|
+
state,
|
|
20887
|
+
state.processSession?.writeStdinForProcessControl ? state.processSession.writeStdinForProcessControl({
|
|
20888
|
+
sessionId: state.sessionId,
|
|
20265
20889
|
chars,
|
|
20266
|
-
|
|
20267
|
-
|
|
20268
|
-
})
|
|
20269
|
-
|
|
20890
|
+
yieldTimeMs,
|
|
20891
|
+
maxOutputTokens: 128
|
|
20892
|
+
}) : state.writeInvoke(
|
|
20893
|
+
state.runContext,
|
|
20894
|
+
JSON.stringify({
|
|
20895
|
+
session_id: state.sessionId,
|
|
20896
|
+
chars,
|
|
20897
|
+
yield_time_ms: yieldTimeMs,
|
|
20898
|
+
max_output_tokens: 128
|
|
20899
|
+
}),
|
|
20900
|
+
void 0
|
|
20901
|
+
)
|
|
20270
20902
|
);
|
|
20903
|
+
if (control.reconciled) return true;
|
|
20904
|
+
const output = control.value;
|
|
20271
20905
|
if (typeof output !== "string") return false;
|
|
20272
20906
|
if (!state.typedHandleLoss && isExecSessionLostBanner(output, state.sessionId)) return true;
|
|
20273
20907
|
if (parseExecBannerSessionId(output) === state.sessionId) return false;
|
|
@@ -23471,9 +24105,180 @@ function parseUnifiedPatch(patch) {
|
|
|
23471
24105
|
|
|
23472
24106
|
// src/sandbox/providers/modal-command-session.ts
|
|
23473
24107
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
23474
|
-
import { isDeepStrictEqual as
|
|
24108
|
+
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
24109
|
+
|
|
24110
|
+
// src/sandbox/provider-errors.ts
|
|
24111
|
+
var GRPC_TRANSIENT = /* @__PURE__ */ new Set([1, 2, 4, 13, 14]);
|
|
24112
|
+
var TRANSIENT_CODES = /* @__PURE__ */ new Set([
|
|
24113
|
+
"1",
|
|
24114
|
+
"2",
|
|
24115
|
+
"4",
|
|
24116
|
+
"13",
|
|
24117
|
+
"14",
|
|
24118
|
+
"CANCELLED",
|
|
24119
|
+
"UNKNOWN",
|
|
24120
|
+
"DEADLINE_EXCEEDED",
|
|
24121
|
+
"INTERNAL",
|
|
24122
|
+
"UNAVAILABLE",
|
|
24123
|
+
"ECONNRESET",
|
|
24124
|
+
"ECONNREFUSED",
|
|
24125
|
+
"ETIMEDOUT",
|
|
24126
|
+
"EAI_AGAIN",
|
|
24127
|
+
"ENOTFOUND"
|
|
24128
|
+
]);
|
|
24129
|
+
var NOT_FOUND_CODES = /* @__PURE__ */ new Set(["404", "NOT_FOUND", "RESOURCE_NOT_FOUND", "SANDBOX_NOT_FOUND"]);
|
|
24130
|
+
var SAFE_CODE = /^[A-Z0-9._:-]{1,64}$/;
|
|
24131
|
+
var UNREADABLE_ERROR_SIGNAL = Symbol("unreadable-error-signal");
|
|
24132
|
+
function safeRead(record, key) {
|
|
24133
|
+
try {
|
|
24134
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
24135
|
+
return descriptor ? "value" in descriptor ? descriptor.value : UNREADABLE_ERROR_SIGNAL : void 0;
|
|
24136
|
+
} catch {
|
|
24137
|
+
return UNREADABLE_ERROR_SIGNAL;
|
|
24138
|
+
}
|
|
24139
|
+
}
|
|
24140
|
+
function collectSignals(value) {
|
|
24141
|
+
const out = { numbers: [], codes: [], messages: [], incomplete: false };
|
|
24142
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24143
|
+
const read = (record, key) => {
|
|
24144
|
+
const signal = safeRead(record, key);
|
|
24145
|
+
if (signal !== UNREADABLE_ERROR_SIGNAL) return signal;
|
|
24146
|
+
out.incomplete = true;
|
|
24147
|
+
return void 0;
|
|
24148
|
+
};
|
|
24149
|
+
const visit = (current, depth) => {
|
|
24150
|
+
if (current === null || current === void 0) return;
|
|
24151
|
+
if (depth > 6 || seen.size >= 64) {
|
|
24152
|
+
out.incomplete = true;
|
|
24153
|
+
return;
|
|
24154
|
+
}
|
|
24155
|
+
if (typeof current === "string") {
|
|
24156
|
+
if (current.length <= 512) out.messages.push(current);
|
|
24157
|
+
return;
|
|
24158
|
+
}
|
|
24159
|
+
if (typeof current !== "object" || seen.has(current)) return;
|
|
24160
|
+
seen.add(current);
|
|
24161
|
+
for (const key of [
|
|
24162
|
+
"status",
|
|
24163
|
+
"statusCode",
|
|
24164
|
+
"httpStatus",
|
|
24165
|
+
"httpStatusCode",
|
|
24166
|
+
"responseStatus",
|
|
24167
|
+
"errorCode",
|
|
24168
|
+
"code"
|
|
24169
|
+
]) {
|
|
24170
|
+
const signal = read(current, key);
|
|
24171
|
+
if (typeof signal === "number" && Number.isFinite(signal)) out.numbers.push(signal);
|
|
24172
|
+
if (typeof signal === "string") {
|
|
24173
|
+
const code = signal.trim().toUpperCase();
|
|
24174
|
+
if (SAFE_CODE.test(code)) out.codes.push(code);
|
|
24175
|
+
}
|
|
24176
|
+
}
|
|
24177
|
+
for (const key of ["name", "message", "details", "cause"]) {
|
|
24178
|
+
const signal = read(current, key);
|
|
24179
|
+
if (typeof signal === "string" && signal.length <= 512) out.messages.push(signal);
|
|
24180
|
+
else visit(signal, depth + 1);
|
|
24181
|
+
}
|
|
24182
|
+
visit(read(current, "response"), depth + 1);
|
|
24183
|
+
visit(read(current, "error"), depth + 1);
|
|
24184
|
+
const errors = read(current, "errors");
|
|
24185
|
+
if (errors !== void 0) {
|
|
24186
|
+
if (!Array.isArray(errors) || !errors.length || errors.length > 16) out.incomplete = true;
|
|
24187
|
+
else
|
|
24188
|
+
for (let index = 0; index < errors.length; index++) {
|
|
24189
|
+
const nested = read(errors, String(index));
|
|
24190
|
+
if (!nested || typeof nested !== "object") out.incomplete = true;
|
|
24191
|
+
visit(nested, depth + 1);
|
|
24192
|
+
}
|
|
24193
|
+
}
|
|
24194
|
+
};
|
|
24195
|
+
visit(value, 0);
|
|
24196
|
+
return out;
|
|
24197
|
+
}
|
|
24198
|
+
function safeDiagnostic(signals) {
|
|
24199
|
+
const code = signals.codes.find(Boolean);
|
|
24200
|
+
const numeric = signals.numbers.find((value) => Number.isFinite(value));
|
|
24201
|
+
return [code ? `code=${code}` : "", numeric !== void 0 ? `status=${numeric}` : ""].filter(Boolean).join(" ");
|
|
24202
|
+
}
|
|
24203
|
+
function hasTransientSignal(signals) {
|
|
24204
|
+
return signals.codes.some((code) => TRANSIENT_CODES.has(code)) || signals.numbers.some((status4) => GRPC_TRANSIENT.has(status4));
|
|
24205
|
+
}
|
|
24206
|
+
function hasModalTerminalSandboxMessage(signals) {
|
|
24207
|
+
return signals.messages.some(
|
|
24208
|
+
(message) => /^Modal sandbox [A-Za-z0-9_-]+ is no longer running\.$/.test(message) || /^Modal sandbox [A-Za-z0-9_-]+ not found \(has been terminated\)$/.test(message)
|
|
24209
|
+
);
|
|
24210
|
+
}
|
|
24211
|
+
function hasUnixLocalTerminalWorkspaceMessage(signals) {
|
|
24212
|
+
return signals.messages.includes(
|
|
24213
|
+
"UnixLocal sandbox workspace is unavailable and no local snapshot could be restored."
|
|
24214
|
+
);
|
|
24215
|
+
}
|
|
24216
|
+
function hasDockerTerminalWorkspaceMessage(signals) {
|
|
24217
|
+
return signals.messages.includes(
|
|
24218
|
+
"Docker sandbox resources are unavailable and no local snapshot could be restored."
|
|
24219
|
+
);
|
|
24220
|
+
}
|
|
24221
|
+
function hasCloudflareTerminalSandboxMessage(signals) {
|
|
24222
|
+
return signals.messages.some(
|
|
24223
|
+
(message) => /^Cloudflare sandbox [A-Za-z0-9._:-]+ is no longer running\.$/.test(message)
|
|
24224
|
+
);
|
|
24225
|
+
}
|
|
24226
|
+
function classifyProviderSandboxFailure(backendId, error) {
|
|
24227
|
+
if (backendId === "selfhosted" || !error) {
|
|
24228
|
+
return { kind: "other", diagnostic: "selfhosted-or-empty" };
|
|
24229
|
+
}
|
|
24230
|
+
const signals = collectSignals(error);
|
|
24231
|
+
const diagnostic = safeDiagnostic(signals) || "unclassified_provider_failure";
|
|
24232
|
+
if (hasTransientSignal(signals)) {
|
|
24233
|
+
return { kind: "transient_transport", diagnostic };
|
|
24234
|
+
}
|
|
24235
|
+
if (signals.incomplete) return { kind: "other", diagnostic };
|
|
24236
|
+
if (signals.numbers.some((status4) => status4 === 404) || signals.codes.some((code) => NOT_FOUND_CODES.has(code))) {
|
|
24237
|
+
return { kind: "not_found", diagnostic };
|
|
24238
|
+
}
|
|
24239
|
+
if (backendId === "modal" && hasModalTerminalSandboxMessage(signals)) {
|
|
24240
|
+
return {
|
|
24241
|
+
kind: "not_found",
|
|
24242
|
+
diagnostic: diagnostic === "unclassified_provider_failure" ? "modal_terminal_message" : `${diagnostic} modal_terminal_message`
|
|
24243
|
+
};
|
|
24244
|
+
}
|
|
24245
|
+
if (backendId === "cloudflare" && hasCloudflareTerminalSandboxMessage(signals)) {
|
|
24246
|
+
return {
|
|
24247
|
+
kind: "not_found",
|
|
24248
|
+
diagnostic: diagnostic === "unclassified_provider_failure" ? "cloudflare_terminal_message" : `${diagnostic} cloudflare_terminal_message`
|
|
24249
|
+
};
|
|
24250
|
+
}
|
|
24251
|
+
if ((backendId === "local" || backendId === "unix_local") && hasUnixLocalTerminalWorkspaceMessage(signals)) {
|
|
24252
|
+
return {
|
|
24253
|
+
kind: "not_found",
|
|
24254
|
+
diagnostic: diagnostic === "unclassified_provider_failure" ? "unix_local_workspace_missing" : `${diagnostic} unix_local_workspace_missing`
|
|
24255
|
+
};
|
|
24256
|
+
}
|
|
24257
|
+
if (backendId === "docker" && hasDockerTerminalWorkspaceMessage(signals)) {
|
|
24258
|
+
return {
|
|
24259
|
+
kind: "not_found",
|
|
24260
|
+
diagnostic: diagnostic === "unclassified_provider_failure" ? "docker_resources_missing" : `${diagnostic} docker_resources_missing`
|
|
24261
|
+
};
|
|
24262
|
+
}
|
|
24263
|
+
return { kind: "other", diagnostic };
|
|
24264
|
+
}
|
|
24265
|
+
function isProviderSandboxNotFoundError2(backendId, error) {
|
|
24266
|
+
return classifyProviderSandboxFailure(backendId, error).kind === "not_found";
|
|
24267
|
+
}
|
|
24268
|
+
function isProviderSandboxGoneDuringRoutedOperation(backendId, error) {
|
|
24269
|
+
if (backendId === "selfhosted" || !error) return false;
|
|
24270
|
+
const signals = collectSignals(error);
|
|
24271
|
+
if (hasTransientSignal(signals) || signals.incomplete) return false;
|
|
24272
|
+
if (signals.codes.includes("SANDBOX_NOT_FOUND")) return true;
|
|
24273
|
+
return backendId === "modal" && hasModalTerminalSandboxMessage(signals);
|
|
24274
|
+
}
|
|
24275
|
+
function isProviderSandboxTransientError(backendId, error) {
|
|
24276
|
+
return classifyProviderSandboxFailure(backendId, error).kind === "transient_transport";
|
|
24277
|
+
}
|
|
23475
24278
|
|
|
23476
24279
|
// src/sandbox/providers/modal-materialization-verification.ts
|
|
24280
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
24281
|
+
import { setTimeout as delay2 } from "timers/promises";
|
|
23477
24282
|
var MARKER = "__OPENGENI_MATERIALIZED_PATH_VISIBLE__";
|
|
23478
24283
|
var OUTPUT_LIMIT = 16 * 1024;
|
|
23479
24284
|
async function verifyModalMaterializedPath(control, path, workdir, pending, observationTimeoutMs = 3e4) {
|
|
@@ -23482,6 +24287,7 @@ async function verifyModalMaterializedPath(control, path, workdir, pending, obse
|
|
|
23482
24287
|
const cancellation = new AbortController();
|
|
23483
24288
|
const deadlineReason = new Error("Materialization visibility observation deadline exceeded");
|
|
23484
24289
|
let providerCommand;
|
|
24290
|
+
let startUnknown;
|
|
23485
24291
|
let stdout = "";
|
|
23486
24292
|
let stderr = "";
|
|
23487
24293
|
const diagnostic = (reason, exitCode = null) => ({
|
|
@@ -23506,13 +24312,46 @@ async function verifyModalMaterializedPath(control, path, workdir, pending, obse
|
|
|
23506
24312
|
timer.unref();
|
|
23507
24313
|
pending.add(cancellation);
|
|
23508
24314
|
try {
|
|
23509
|
-
|
|
23510
|
-
|
|
23511
|
-
|
|
23512
|
-
|
|
24315
|
+
try {
|
|
24316
|
+
providerCommand = await control.start(
|
|
24317
|
+
{ cmd: command, workdir, shell: "sh", login: false, tty: false },
|
|
24318
|
+
cancellation.signal
|
|
24319
|
+
);
|
|
24320
|
+
} catch (error) {
|
|
24321
|
+
if (!(error instanceof ProviderCommandStartOutcomeUnknownError)) throw error;
|
|
24322
|
+
providerCommand = structuredClone(error.command);
|
|
24323
|
+
startUnknown = error;
|
|
24324
|
+
}
|
|
23513
24325
|
for (; ; ) {
|
|
23514
24326
|
cancellation.signal.throwIfAborted();
|
|
23515
|
-
|
|
24327
|
+
let page;
|
|
24328
|
+
try {
|
|
24329
|
+
page = await control.readProbe(providerCommand, 1e3, cancellation);
|
|
24330
|
+
} catch (error) {
|
|
24331
|
+
cancellation.signal.throwIfAborted();
|
|
24332
|
+
if (!(error instanceof ProviderCommandObservationUnavailableError) || !error.readRetryAllowed) {
|
|
24333
|
+
if (!startUnknown) throw error;
|
|
24334
|
+
throw new ProviderCommandObservationUnavailableError(
|
|
24335
|
+
structuredClone(providerCommand),
|
|
24336
|
+
new AggregateError(
|
|
24337
|
+
[startUnknown, error],
|
|
24338
|
+
"Original visibility Start and observation remain uncertain"
|
|
24339
|
+
),
|
|
24340
|
+
false
|
|
24341
|
+
);
|
|
24342
|
+
}
|
|
24343
|
+
if (!isDeepStrictEqual3(error.command, providerCommand))
|
|
24344
|
+
throw new SandboxMaterializationVerificationError(diagnostic("invalid_response"), {
|
|
24345
|
+
cause: error
|
|
24346
|
+
});
|
|
24347
|
+
try {
|
|
24348
|
+
await delay2(100, void 0, { signal: cancellation.signal });
|
|
24349
|
+
} catch (interrupted) {
|
|
24350
|
+
cancellation.signal.throwIfAborted();
|
|
24351
|
+
throw interrupted;
|
|
24352
|
+
}
|
|
24353
|
+
continue;
|
|
24354
|
+
}
|
|
23516
24355
|
cancellation.signal.throwIfAborted();
|
|
23517
24356
|
if (page.command.sandboxId !== providerCommand.sandboxId || page.command.taskId !== providerCommand.taskId || page.command.execId !== providerCommand.execId) {
|
|
23518
24357
|
throw new SandboxMaterializationVerificationError(diagnostic("invalid_response"));
|
|
@@ -23544,7 +24383,15 @@ async function verifyModalMaterializedPath(control, path, workdir, pending, obse
|
|
|
23544
24383
|
...diagnostic("command_pending"),
|
|
23545
24384
|
causeMessage: "Observation deadline exceeded; provider process completion is unconfirmed"
|
|
23546
24385
|
},
|
|
23547
|
-
{
|
|
24386
|
+
{
|
|
24387
|
+
cause: providerCommand ? new ProviderCommandObservationUnavailableError(
|
|
24388
|
+
providerCommand,
|
|
24389
|
+
startUnknown ? new AggregateError(
|
|
24390
|
+
[startUnknown, error],
|
|
24391
|
+
"Original visibility Start and observation deadline remain uncertain"
|
|
24392
|
+
) : error
|
|
24393
|
+
) : error
|
|
24394
|
+
}
|
|
23548
24395
|
);
|
|
23549
24396
|
}
|
|
23550
24397
|
if (!(error instanceof SandboxMaterializationVerificationError)) {
|
|
@@ -23563,7 +24410,7 @@ async function verifyModalMaterializedPath(control, path, workdir, pending, obse
|
|
|
23563
24410
|
|
|
23564
24411
|
// src/sandbox/providers/modal-command-session.ts
|
|
23565
24412
|
function sameExecution(a, b) {
|
|
23566
|
-
return a.kind === b.kind && a.sandboxId === b.sandboxId && a.taskId === b.taskId && a.execId === b.execId &&
|
|
24413
|
+
return a.kind === b.kind && a.sandboxId === b.sandboxId && a.taskId === b.taskId && a.execId === b.execId && isDeepStrictEqual4(
|
|
23567
24414
|
"supervision" in a ? a.supervision : void 0,
|
|
23568
24415
|
"supervision" in b ? b.supervision : void 0
|
|
23569
24416
|
) && Boolean(a.pty) === Boolean(b.pty);
|
|
@@ -23782,7 +24629,7 @@ function installModalCommandSession(session, control) {
|
|
|
23782
24629
|
session.captureCommandOutput = async (result) => {
|
|
23783
24630
|
const receipt = receipts.get(result);
|
|
23784
24631
|
if (!receipt || receipt.page.command.kind !== "modal-router-v1") return false;
|
|
23785
|
-
if (
|
|
24632
|
+
if (!receipt.page.expected && receipt.page.exitCode === null && receipt.page.chunks.length === 0) {
|
|
23786
24633
|
receipts.delete(result);
|
|
23787
24634
|
return true;
|
|
23788
24635
|
}
|
|
@@ -23840,9 +24687,23 @@ function installModalCommandSession(session, control) {
|
|
|
23840
24687
|
if (!retained || !sameExecution(entry.command, retained))
|
|
23841
24688
|
throw new Error("Original Modal command identity is unavailable");
|
|
23842
24689
|
const index = await entry.persistence.reserveInput(Buffer.byteLength(args.chars));
|
|
23843
|
-
|
|
24690
|
+
try {
|
|
24691
|
+
await control.write(retained, args.chars, index);
|
|
24692
|
+
} catch (error) {
|
|
24693
|
+
if (retained.kind === "modal-router-v1" && // Contain supported transport graphs, including mixed failures. This
|
|
24694
|
+
// grants no read/write retry permission; the locator and byte range
|
|
24695
|
+
// come only from the retained command and its one input reservation.
|
|
24696
|
+
classifyProviderSandboxFailure("modal", error).kind === "transient_transport")
|
|
24697
|
+
throw new ProviderCommandInputOutcomeUnknownError(
|
|
24698
|
+
retained,
|
|
24699
|
+
index,
|
|
24700
|
+
Buffer.byteLength(args.chars),
|
|
24701
|
+
error
|
|
24702
|
+
);
|
|
24703
|
+
throw error;
|
|
24704
|
+
}
|
|
23844
24705
|
}
|
|
23845
|
-
return read(args.sessionId, entry, args.yieldTimeMs ?? 250, args.maxOutputTokens);
|
|
24706
|
+
return read(args.sessionId, entry, args.yieldTimeMs ?? 250, args.maxOutputTokens, args.signal);
|
|
23846
24707
|
};
|
|
23847
24708
|
}
|
|
23848
24709
|
|
|
@@ -23850,274 +24711,88 @@ function installModalCommandSession(session, control) {
|
|
|
23850
24711
|
import { randomUUID as randomUUID6, randomBytes } from "crypto";
|
|
23851
24712
|
import { posix as posix3 } from "path";
|
|
23852
24713
|
import { status as status3 } from "@grpc/grpc-js";
|
|
23853
|
-
import { setTimeout as
|
|
24714
|
+
import { setTimeout as delay3 } from "timers/promises";
|
|
23854
24715
|
import {
|
|
23855
24716
|
SandboxProviderCommand,
|
|
23856
|
-
CommandSupervisionReceipt
|
|
24717
|
+
CommandSupervisionReceipt,
|
|
24718
|
+
ModalRouterProviderCommand as ModalRouterProviderCommand3
|
|
23857
24719
|
} from "@opengeni/contracts";
|
|
23858
24720
|
|
|
23859
|
-
// src/sandbox/providers/modal-
|
|
23860
|
-
|
|
23861
|
-
|
|
23862
|
-
|
|
23863
|
-
|
|
23864
|
-
|
|
23865
|
-
|
|
23866
|
-
|
|
23867
|
-
};
|
|
23868
|
-
var ModalClientBase = ModalClient;
|
|
23869
|
-
var ModalCommandClient = class extends ModalClientBase {
|
|
23870
|
-
retryMiddleware() {
|
|
23871
|
-
return modalCommandAbortMiddleware;
|
|
23872
|
-
}
|
|
23873
|
-
};
|
|
23874
|
-
var controlClients = /* @__PURE__ */ new WeakMap();
|
|
23875
|
-
function commandControlPlane(client) {
|
|
23876
|
-
if (!client.profile) return client.cpClient;
|
|
23877
|
-
if (typeof Reflect.get(ModalClient.prototype, "retryMiddleware") !== "function")
|
|
23878
|
-
throw new Error("Verified Modal command cancellation contract is unavailable");
|
|
23879
|
-
let controlled = controlClients.get(client);
|
|
23880
|
-
if (!controlled) {
|
|
23881
|
-
const profile = client.profile;
|
|
23882
|
-
if (!profile.tokenId || !profile.tokenSecret)
|
|
23883
|
-
throw new Error("Modal command control requires its original authenticated profile");
|
|
23884
|
-
controlled = new ModalCommandClient({
|
|
23885
|
-
tokenId: profile.tokenId,
|
|
23886
|
-
tokenSecret: profile.tokenSecret,
|
|
23887
|
-
endpoint: profile.serverUrl,
|
|
23888
|
-
environment: profile.environment ?? "",
|
|
23889
|
-
...profile.maxThrottleWaitSecs !== void 0 ? { maxThrottleWaitSecs: profile.maxThrottleWaitSecs } : {},
|
|
23890
|
-
...client.logger ? { logger: client.logger } : {}
|
|
23891
|
-
});
|
|
23892
|
-
controlClients.set(client, controlled);
|
|
23893
|
-
}
|
|
23894
|
-
return controlled.cpClient;
|
|
23895
|
-
}
|
|
23896
|
-
function decodePage(prior, input, terminal) {
|
|
23897
|
-
const bytes = Buffer.concat([Buffer.from(prior, "base64"), ...input]);
|
|
23898
|
-
let boundary = bytes.length;
|
|
23899
|
-
if (!terminal) {
|
|
23900
|
-
for (let start = Math.max(0, bytes.length - 3); start < bytes.length; start++) {
|
|
23901
|
-
const first = bytes[start];
|
|
23902
|
-
const width = first >= 194 && first <= 223 ? 2 : first >= 224 && first <= 239 ? 3 : first >= 240 && first <= 244 ? 4 : 0;
|
|
23903
|
-
if (!width || bytes.length - start >= width) continue;
|
|
23904
|
-
const suffix = bytes.subarray(start + 1);
|
|
23905
|
-
if (!suffix.every((byte) => byte >= 128 && byte <= 191)) continue;
|
|
23906
|
-
const second = suffix[0];
|
|
23907
|
-
if (second !== void 0 && (first === 224 && second < 160 || first === 237 && second > 159 || first === 240 && second < 144 || first === 244 && second > 143))
|
|
23908
|
-
continue;
|
|
23909
|
-
boundary = start;
|
|
23910
|
-
break;
|
|
23911
|
-
}
|
|
23912
|
-
}
|
|
23913
|
-
return {
|
|
23914
|
-
text: bytes.subarray(0, boundary).toString("utf8"),
|
|
23915
|
-
remainder: bytes.subarray(boundary).toString("base64")
|
|
24721
|
+
// src/sandbox/providers/modal-command-observation-errors.ts
|
|
24722
|
+
function isModalCommandObservationTransportError(error) {
|
|
24723
|
+
const seen = /* @__PURE__ */ new Map();
|
|
24724
|
+
let nodes = 0;
|
|
24725
|
+
const own = (value, key) => {
|
|
24726
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
24727
|
+
if (descriptor && !("value" in descriptor)) throw new Error("Unreadable provider error graph");
|
|
24728
|
+
return descriptor && "value" in descriptor ? descriptor.value : void 0;
|
|
23916
24729
|
};
|
|
23917
|
-
|
|
23918
|
-
|
|
23919
|
-
|
|
23920
|
-
|
|
23921
|
-
|
|
23922
|
-
|
|
23923
|
-
|
|
23924
|
-
|
|
23925
|
-
static forSandbox(client, sandboxId, root, environment = {}) {
|
|
23926
|
-
if (client.version() !== "0.9.0")
|
|
23927
|
-
throw new Error("Modal command control requires the verified 0.9.0 SDK contract");
|
|
23928
|
-
return new _ModalCommandControl(commandControlPlane(client), sandboxId, root, environment);
|
|
23929
|
-
}
|
|
23930
|
-
get sandboxId() {
|
|
23931
|
-
return typeof this.sandboxIdentity === "function" ? this.sandboxIdentity() : this.sandboxIdentity;
|
|
23932
|
-
}
|
|
23933
|
-
async start(args, signal) {
|
|
23934
|
-
signal?.throwIfAborted();
|
|
23935
|
-
const workdir = posix2.resolve(this.root, args.workdir ?? this.root);
|
|
23936
|
-
if (workdir !== this.root && !workdir.startsWith(`${this.root.replace(/\/$/u, "")}/`))
|
|
23937
|
-
throw new Error("Command workdir is outside the sandbox workspace");
|
|
23938
|
-
const sandboxId = this.sandboxId;
|
|
23939
|
-
const task = await ModalCommandStartPreDispatchUnavailableError.beforeDispatch(
|
|
23940
|
-
() => this.client.sandboxGetTaskId({ sandboxId }, signal ? { signal } : void 0),
|
|
23941
|
-
signal
|
|
23942
|
-
);
|
|
23943
|
-
if (!task.taskId || task.taskResult) throw new Error("Modal command task is unavailable");
|
|
23944
|
-
if (sandboxId !== this.sandboxId)
|
|
23945
|
-
throw new Error("Modal sandbox changed during command preparation");
|
|
23946
|
-
const login = args.shell ? args.login ?? true : false;
|
|
23947
|
-
let command = [args.shell ?? "/bin/sh", login ? "-lc" : "-c", args.cmd];
|
|
23948
|
-
if (args.runAs) {
|
|
23949
|
-
const user = shellQuote(args.runAs);
|
|
23950
|
-
const invocation = command.map(shellQuote).join(" ");
|
|
23951
|
-
const script = `if [ "$(id -u)" = ${user} ] || [ "$(id -un 2>/dev/null)" = ${user} ]; then exec ${invocation}; elif [ "$(id -u)" = 0 ]; then exec su -s /bin/sh ${user} -c ${shellQuote(`exec ${invocation}`)}; else exec sudo -n -u ${user} -- ${invocation}; fi`;
|
|
23952
|
-
command = ["/bin/sh", "-c", script];
|
|
23953
|
-
}
|
|
23954
|
-
const environment = typeof this.environment === "function" ? this.environment() : this.environment;
|
|
23955
|
-
if (Object.keys(environment).length) {
|
|
23956
|
-
command = [
|
|
23957
|
-
"/usr/bin/env",
|
|
23958
|
-
"--",
|
|
23959
|
-
...Object.entries(environment).map(([key, value]) => `${key}=${value}`),
|
|
23960
|
-
...command
|
|
23961
|
-
];
|
|
23962
|
-
}
|
|
23963
|
-
const result = await this.client.containerExec(
|
|
23964
|
-
{
|
|
23965
|
-
taskId: task.taskId,
|
|
23966
|
-
command,
|
|
23967
|
-
terminateContainerOnExit: false,
|
|
23968
|
-
runtimeDebug: false,
|
|
23969
|
-
stdoutOutput: 2,
|
|
23970
|
-
stderrOutput: 2,
|
|
23971
|
-
timeoutSecs: 0,
|
|
23972
|
-
workdir,
|
|
23973
|
-
secretIds: [],
|
|
23974
|
-
...args.tty ? {
|
|
23975
|
-
ptyInfo: {
|
|
23976
|
-
enabled: true,
|
|
23977
|
-
winszRows: 24,
|
|
23978
|
-
winszCols: 80,
|
|
23979
|
-
envTerm: "xterm",
|
|
23980
|
-
envColorterm: "",
|
|
23981
|
-
envTermProgram: "",
|
|
23982
|
-
ptyType: 1,
|
|
23983
|
-
noTerminateOnIdleStdin: true
|
|
23984
|
-
}
|
|
23985
|
-
} : {}
|
|
23986
|
-
},
|
|
23987
|
-
{ retries: 0, ...signal ? { signal } : {} }
|
|
23988
|
-
).catch((error) => {
|
|
23989
|
-
const code = error?.code;
|
|
23990
|
-
if (typeof code === "number" && [
|
|
23991
|
-
status2.INVALID_ARGUMENT,
|
|
23992
|
-
status2.NOT_FOUND,
|
|
23993
|
-
status2.PERMISSION_DENIED,
|
|
23994
|
-
status2.UNAUTHENTICATED,
|
|
23995
|
-
status2.UNIMPLEMENTED
|
|
23996
|
-
].includes(code))
|
|
23997
|
-
throw new ProviderCommandStartRejectedError(error);
|
|
23998
|
-
throw new ModalCommandStartOutcomeUnknownError(task.taskId, "", error);
|
|
23999
|
-
});
|
|
24000
|
-
if (!result.execId)
|
|
24001
|
-
throw new ModalCommandStartOutcomeUnknownError(
|
|
24002
|
-
task.taskId,
|
|
24003
|
-
"",
|
|
24004
|
-
new Error("Modal command start returned no execution identity")
|
|
24730
|
+
const visit = (value, depth) => {
|
|
24731
|
+
if (!value || typeof value !== "object" || depth > 6 || ++nodes > 32) return false;
|
|
24732
|
+
if (seen.has(value)) return seen.get(value);
|
|
24733
|
+
seen.set(value, false);
|
|
24734
|
+
try {
|
|
24735
|
+
const code = own(value, "code");
|
|
24736
|
+
const nested = [own(value, "cause"), own(value, "error")].filter(
|
|
24737
|
+
(item) => item !== void 0
|
|
24005
24738
|
);
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
24009
|
-
|
|
24010
|
-
execId: result.execId,
|
|
24011
|
-
...args.tty ? { pty: true } : {},
|
|
24012
|
-
streams: {
|
|
24013
|
-
stdout: { batchIndex: 0, utf8Remainder: "", exitCode: null },
|
|
24014
|
-
stderr: { batchIndex: 0, utf8Remainder: "", exitCode: null }
|
|
24739
|
+
const errors = own(value, "errors");
|
|
24740
|
+
if (errors !== void 0) {
|
|
24741
|
+
if (!Array.isArray(errors) || !errors.length || errors.length > 16) return false;
|
|
24742
|
+
for (let index = 0; index < errors.length; index++) nested.push(own(errors, String(index)));
|
|
24015
24743
|
}
|
|
24016
|
-
|
|
24017
|
-
|
|
24018
|
-
|
|
24019
|
-
|
|
24020
|
-
|
|
24021
|
-
|
|
24022
|
-
|
|
24023
|
-
|
|
24024
|
-
|
|
24025
|
-
|
|
24026
|
-
|
|
24027
|
-
|
|
24028
|
-
|
|
24029
|
-
|
|
24030
|
-
|
|
24031
|
-
|
|
24032
|
-
|
|
24033
|
-
|
|
24034
|
-
|
|
24035
|
-
|
|
24036
|
-
|
|
24037
|
-
|
|
24038
|
-
|
|
24039
|
-
|
|
24040
|
-
|
|
24041
|
-
|
|
24042
|
-
|
|
24043
|
-
|
|
24044
|
-
execId: command.execId,
|
|
24045
|
-
timeout: Math.max(0, yieldTimeMs) / 1e3,
|
|
24046
|
-
lastBatchIndex: cursor.batchIndex,
|
|
24047
|
-
fileDescriptor: descriptor,
|
|
24048
|
-
getRawBytes: true
|
|
24049
|
-
},
|
|
24050
|
-
signal ? { signal } : void 0
|
|
24051
|
-
)) {
|
|
24052
|
-
if (batch.batchIndex <= cursor.batchIndex) continue;
|
|
24053
|
-
if (!Number.isSafeInteger(batch.batchIndex))
|
|
24054
|
-
throw new Error("Invalid Modal output cursor");
|
|
24055
|
-
const terminal = batch.exitCode !== void 0;
|
|
24056
|
-
if (terminal && !Number.isSafeInteger(batch.exitCode))
|
|
24057
|
-
throw new Error("Invalid Modal exit status");
|
|
24058
|
-
const decoded = decodePage(
|
|
24059
|
-
cursor.utf8Remainder,
|
|
24060
|
-
batch.items.filter((item) => item.fileDescriptor === descriptor).map((item) => item.messageBytes),
|
|
24061
|
-
terminal
|
|
24062
|
-
);
|
|
24063
|
-
next.streams[stream] = {
|
|
24064
|
-
batchIndex: batch.batchIndex,
|
|
24065
|
-
utf8Remainder: decoded.remainder,
|
|
24066
|
-
exitCode: terminal ? batch.exitCode : null
|
|
24067
|
-
};
|
|
24068
|
-
return {
|
|
24069
|
-
stream,
|
|
24070
|
-
chunkId: `modal:${command.execId}:${stream}:${cursor.batchIndex}:${batch.batchIndex}`,
|
|
24071
|
-
text: decoded.text
|
|
24072
|
-
};
|
|
24744
|
+
if (code !== void 0) {
|
|
24745
|
+
const normalized = typeof code === "string" ? code.trim().toUpperCase() : code;
|
|
24746
|
+
if (![
|
|
24747
|
+
1,
|
|
24748
|
+
2,
|
|
24749
|
+
4,
|
|
24750
|
+
13,
|
|
24751
|
+
14,
|
|
24752
|
+
"1",
|
|
24753
|
+
"2",
|
|
24754
|
+
"4",
|
|
24755
|
+
"13",
|
|
24756
|
+
"14",
|
|
24757
|
+
"CANCELLED",
|
|
24758
|
+
"UNKNOWN",
|
|
24759
|
+
"DEADLINE_EXCEEDED",
|
|
24760
|
+
"INTERNAL",
|
|
24761
|
+
"UNAVAILABLE",
|
|
24762
|
+
"ECONNRESET",
|
|
24763
|
+
"ECONNREFUSED",
|
|
24764
|
+
"ETIMEDOUT",
|
|
24765
|
+
"EAI_AGAIN",
|
|
24766
|
+
"ENOTFOUND"
|
|
24767
|
+
].includes(normalized))
|
|
24768
|
+
return false;
|
|
24769
|
+
const result2 = nested.length === 0 || nested.every((item) => visit(item, depth + 1));
|
|
24770
|
+
seen.set(value, result2);
|
|
24771
|
+
return result2;
|
|
24073
24772
|
}
|
|
24074
|
-
|
|
24075
|
-
|
|
24076
|
-
|
|
24077
|
-
|
|
24078
|
-
|
|
24079
|
-
|
|
24080
|
-
|
|
24081
|
-
|
|
24082
|
-
|
|
24083
|
-
if (failure) throw failure.error;
|
|
24084
|
-
return results.map((result) => {
|
|
24085
|
-
if (result.status === "rejected") throw result.reason;
|
|
24086
|
-
return result.value;
|
|
24087
|
-
});
|
|
24088
|
-
}) : await Promise.all(reads);
|
|
24089
|
-
const stdoutExit = next.streams.stdout.exitCode;
|
|
24090
|
-
const stderrExit = next.streams.stderr.exitCode;
|
|
24091
|
-
if (stdoutExit !== null && stderrExit !== null && stdoutExit !== stderrExit)
|
|
24092
|
-
throw new Error("Modal output streams disagree about command exit status");
|
|
24093
|
-
return {
|
|
24094
|
-
command: next,
|
|
24095
|
-
streamFidelity: command.pty ? "merged" : "separate",
|
|
24096
|
-
chunks: pages.filter((page) => page !== null),
|
|
24097
|
-
exitCode: stdoutExit !== null && stderrExit !== null ? stdoutExit : null
|
|
24098
|
-
};
|
|
24099
|
-
}
|
|
24100
|
-
async write(command, chars, messageIndex) {
|
|
24101
|
-
this.assertIdentity(command);
|
|
24102
|
-
if (!chars) return;
|
|
24103
|
-
if (!Number.isSafeInteger(messageIndex) || messageIndex < 1)
|
|
24104
|
-
throw new Error("Modal stdin requires a protected monotonic message index");
|
|
24105
|
-
await this.client.containerExecPutInput(
|
|
24106
|
-
{
|
|
24107
|
-
execId: command.execId,
|
|
24108
|
-
input: { message: Buffer.from(chars), messageIndex, eof: false }
|
|
24109
|
-
},
|
|
24110
|
-
{ retries: 0 }
|
|
24111
|
-
);
|
|
24112
|
-
}
|
|
24113
|
-
assertIdentity(command) {
|
|
24114
|
-
ModalLegacyProviderCommand.parse(command);
|
|
24115
|
-
if (command.kind !== "modal-control-v1" || command.sandboxId !== this.sandboxId || !command.taskId || !command.execId)
|
|
24116
|
-
throw new Error("Modal command locator does not match the original sandbox");
|
|
24117
|
-
}
|
|
24118
|
-
};
|
|
24773
|
+
const result = nested.length > 0 && nested.every((item) => visit(item, depth + 1));
|
|
24774
|
+
seen.set(value, result);
|
|
24775
|
+
return result;
|
|
24776
|
+
} catch {
|
|
24777
|
+
return false;
|
|
24778
|
+
}
|
|
24779
|
+
};
|
|
24780
|
+
return visit(error, 0);
|
|
24781
|
+
}
|
|
24119
24782
|
|
|
24120
24783
|
// src/sandbox/providers/modal-command-control.ts
|
|
24784
|
+
function awaitRouterAccess(pending, signal) {
|
|
24785
|
+
if (!signal) return pending;
|
|
24786
|
+
signal.throwIfAborted();
|
|
24787
|
+
return new Promise((resolve7, reject) => {
|
|
24788
|
+
const abort = () => {
|
|
24789
|
+
signal.removeEventListener("abort", abort);
|
|
24790
|
+
reject(signal.reason);
|
|
24791
|
+
};
|
|
24792
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
24793
|
+
void pending.then(resolve7, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
24794
|
+
});
|
|
24795
|
+
}
|
|
24121
24796
|
var ModalCommandControl2 = class _ModalCommandControl {
|
|
24122
24797
|
constructor(client, sandboxIdentity, root, environment) {
|
|
24123
24798
|
this.sandboxIdentity = sandboxIdentity;
|
|
@@ -24127,6 +24802,8 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24127
24802
|
this.legacy = ModalCommandControl.forSandbox(client, sandboxIdentity, root, environment);
|
|
24128
24803
|
}
|
|
24129
24804
|
routers = /* @__PURE__ */ new Map();
|
|
24805
|
+
routerLookups = /* @__PURE__ */ new Map();
|
|
24806
|
+
controlHelpers = /* @__PURE__ */ new Map();
|
|
24130
24807
|
client;
|
|
24131
24808
|
legacy;
|
|
24132
24809
|
closed = false;
|
|
@@ -24144,10 +24821,15 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24144
24821
|
let pending = this.routers.get(taskId);
|
|
24145
24822
|
const reused = Boolean(pending);
|
|
24146
24823
|
if (!pending) {
|
|
24824
|
+
const lookup2 = {
|
|
24825
|
+
controller: new AbortController(),
|
|
24826
|
+
waiters: 0,
|
|
24827
|
+
settled: false
|
|
24828
|
+
};
|
|
24147
24829
|
pending = (async () => {
|
|
24148
|
-
const access = await
|
|
24149
|
-
{ taskId },
|
|
24150
|
-
signal
|
|
24830
|
+
const access = await awaitRouterAccess(
|
|
24831
|
+
this.client.taskGetCommandRouterAccess({ taskId }, { signal: lookup2.controller.signal }),
|
|
24832
|
+
lookup2.controller.signal
|
|
24151
24833
|
);
|
|
24152
24834
|
let refreshAt = Date.now() + 6e4;
|
|
24153
24835
|
try {
|
|
@@ -24161,15 +24843,33 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24161
24843
|
return { router: new ModalCommandRouterWire(access), users: 0, refreshAt };
|
|
24162
24844
|
})();
|
|
24163
24845
|
this.routers.set(taskId, pending);
|
|
24164
|
-
|
|
24846
|
+
this.routerLookups.set(pending, lookup2);
|
|
24847
|
+
const settled = () => {
|
|
24848
|
+
lookup2.settled = true;
|
|
24849
|
+
this.routerLookups.delete(pending);
|
|
24850
|
+
};
|
|
24851
|
+
void pending.then(settled, () => {
|
|
24852
|
+
settled();
|
|
24165
24853
|
if (this.routers.get(taskId) === pending) this.routers.delete(taskId);
|
|
24166
24854
|
});
|
|
24167
24855
|
}
|
|
24168
|
-
const
|
|
24856
|
+
const lookup = this.routerLookups.get(pending);
|
|
24857
|
+
if (lookup) lookup.waiters++;
|
|
24858
|
+
let entry;
|
|
24859
|
+
try {
|
|
24860
|
+
entry = await awaitRouterAccess(pending, signal);
|
|
24861
|
+
} finally {
|
|
24862
|
+
if (lookup && --lookup.waiters === 0 && !lookup.settled) {
|
|
24863
|
+
if (this.routers.get(taskId) === pending) this.routers.delete(taskId);
|
|
24864
|
+
lookup.controller.abort(new Error("Modal router access has no remaining waiters"));
|
|
24865
|
+
}
|
|
24866
|
+
}
|
|
24169
24867
|
if (reused && !entry.users && Date.now() > entry.refreshAt) {
|
|
24170
|
-
|
|
24171
|
-
|
|
24172
|
-
|
|
24868
|
+
if (this.routers.get(taskId) === pending) {
|
|
24869
|
+
this.routers.delete(taskId);
|
|
24870
|
+
clearTimeout(entry.idle);
|
|
24871
|
+
entry.router.close();
|
|
24872
|
+
}
|
|
24173
24873
|
return await this.withRouter(taskId, signal, run2);
|
|
24174
24874
|
}
|
|
24175
24875
|
clearTimeout(entry.idle);
|
|
@@ -24192,6 +24892,8 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24192
24892
|
}
|
|
24193
24893
|
async close() {
|
|
24194
24894
|
this.closed = true;
|
|
24895
|
+
for (const lookup of this.routerLookups.values())
|
|
24896
|
+
lookup.controller.abort(new Error("Modal command control is closed"));
|
|
24195
24897
|
const entries = await Promise.allSettled(this.routers.values());
|
|
24196
24898
|
this.routers.clear();
|
|
24197
24899
|
for (const entry of entries)
|
|
@@ -24240,19 +24942,7 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24240
24942
|
nonce: randomBytes(32).toString("hex"),
|
|
24241
24943
|
controlPath: `/tmp/opengeni-supervision/${invocationId}.sock`
|
|
24242
24944
|
} : void 0;
|
|
24243
|
-
let commandArgs =
|
|
24244
|
-
args.shell ?? "/bin/sh",
|
|
24245
|
-
args.shell && (args.login ?? true) ? "-lc" : "-c",
|
|
24246
|
-
args.cmd
|
|
24247
|
-
];
|
|
24248
|
-
if (args.runAs) {
|
|
24249
|
-
const user = shellQuote(args.runAs), invocation = commandArgs.map(shellQuote).join(" ");
|
|
24250
|
-
commandArgs = [
|
|
24251
|
-
"/bin/sh",
|
|
24252
|
-
"-c",
|
|
24253
|
-
`if [ "$(id -u)" = ${user} ] || [ "$(id -un 2>/dev/null)" = ${user} ]; then exec ${invocation}; elif [ "$(id -u)" = 0 ]; then exec su -s /bin/sh ${user} -c ${shellQuote(`exec ${invocation}`)}; else exec sudo -n -u ${user} -- ${invocation}; fi`
|
|
24254
|
-
];
|
|
24255
|
-
}
|
|
24945
|
+
let commandArgs = modalCommandArgv(args);
|
|
24256
24946
|
const env = typeof this.environment === "function" ? this.environment() : this.environment;
|
|
24257
24947
|
if (supervision)
|
|
24258
24948
|
commandArgs = [
|
|
@@ -24325,28 +25015,50 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24325
25015
|
if (!task.taskId || task.taskResult) throw new Error("Modal command task is unavailable");
|
|
24326
25016
|
await this.withStartRouter(task.taskId, signal, async (router) => {
|
|
24327
25017
|
const identity = { taskId: task.taskId, execId: randomUUID6() };
|
|
24328
|
-
|
|
24329
|
-
{
|
|
25018
|
+
const observation = {
|
|
25019
|
+
command: {
|
|
25020
|
+
kind: "modal-router-v1",
|
|
25021
|
+
sandboxId,
|
|
24330
25022
|
...identity,
|
|
24331
|
-
|
|
24332
|
-
|
|
24333
|
-
|
|
25023
|
+
streams: {
|
|
25024
|
+
stdout: { byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null },
|
|
25025
|
+
stderr: { byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null }
|
|
25026
|
+
}
|
|
24334
25027
|
},
|
|
24335
|
-
|
|
24336
|
-
|
|
24337
|
-
let
|
|
24338
|
-
|
|
24339
|
-
|
|
24340
|
-
|
|
24341
|
-
|
|
24342
|
-
|
|
24343
|
-
|
|
24344
|
-
|
|
24345
|
-
|
|
24346
|
-
|
|
24347
|
-
|
|
24348
|
-
|
|
25028
|
+
output: ""
|
|
25029
|
+
};
|
|
25030
|
+
let startUnknown;
|
|
25031
|
+
try {
|
|
25032
|
+
await router.start(
|
|
25033
|
+
{
|
|
25034
|
+
...identity,
|
|
25035
|
+
commandArgs: ["/usr/local/bin/opengeni-command-supervisor", "capabilities"],
|
|
25036
|
+
workdir: "/tmp",
|
|
25037
|
+
env: {}
|
|
25038
|
+
},
|
|
25039
|
+
signal
|
|
25040
|
+
);
|
|
25041
|
+
} catch (error) {
|
|
25042
|
+
if (!(error instanceof ModalCommandStartOutcomeUnknownError)) throw error;
|
|
25043
|
+
if (error.taskId !== identity.taskId || error.execId !== identity.execId) throw error;
|
|
25044
|
+
startUnknown = error;
|
|
25045
|
+
}
|
|
25046
|
+
let result;
|
|
25047
|
+
try {
|
|
25048
|
+
result = await this.readControlOutput(identity, 128, signal, observation);
|
|
25049
|
+
} catch (error) {
|
|
25050
|
+
if (!startUnknown) throw error;
|
|
25051
|
+
throw new ProviderCommandObservationUnavailableError(
|
|
25052
|
+
structuredClone(observation.command),
|
|
25053
|
+
new AggregateError(
|
|
25054
|
+
[startUnknown, error],
|
|
25055
|
+
"Original capability Start and observation remain uncertain"
|
|
25056
|
+
),
|
|
25057
|
+
error instanceof ProviderCommandObservationUnavailableError && error.readRetryAllowed
|
|
25058
|
+
);
|
|
24349
25059
|
}
|
|
25060
|
+
signal.throwIfAborted();
|
|
25061
|
+
const { output, exit } = result;
|
|
24350
25062
|
if (exit !== 0 || output !== "native-subreaper-v1")
|
|
24351
25063
|
throw new Error(
|
|
24352
25064
|
"Exact Modal instance lacks compatible native supervision; command not admitted"
|
|
@@ -24373,7 +25085,7 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24373
25085
|
const transientObservation = (error) => [status3.UNAVAILABLE, status3.DEADLINE_EXCEEDED].includes(
|
|
24374
25086
|
error?.code ?? -1
|
|
24375
25087
|
);
|
|
24376
|
-
const pause = () =>
|
|
25088
|
+
const pause = () => delay3(100, void 0, { signal });
|
|
24377
25089
|
return await this.withStartRouter(task.taskId, signal, async (router) => {
|
|
24378
25090
|
for (; ; ) {
|
|
24379
25091
|
signal.throwIfAborted();
|
|
@@ -24426,45 +25138,92 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24426
25138
|
const descriptor = command.supervision;
|
|
24427
25139
|
if (!descriptor || command.sandboxId !== this.sandboxId)
|
|
24428
25140
|
throw new Error("Supervised command identity is unavailable");
|
|
24429
|
-
const
|
|
24430
|
-
|
|
24431
|
-
|
|
24432
|
-
|
|
24433
|
-
|
|
24434
|
-
|
|
24435
|
-
|
|
24436
|
-
|
|
24437
|
-
|
|
24438
|
-
|
|
24439
|
-
|
|
24440
|
-
|
|
24441
|
-
|
|
24442
|
-
|
|
24443
|
-
|
|
24444
|
-
|
|
24445
|
-
|
|
24446
|
-
|
|
24447
|
-
|
|
24448
|
-
|
|
24449
|
-
|
|
24450
|
-
|
|
24451
|
-
|
|
24452
|
-
|
|
24453
|
-
|
|
24454
|
-
|
|
24455
|
-
|
|
24456
|
-
|
|
24457
|
-
|
|
24458
|
-
|
|
24459
|
-
|
|
24460
|
-
|
|
24461
|
-
|
|
24462
|
-
|
|
24463
|
-
|
|
24464
|
-
|
|
25141
|
+
const key = JSON.stringify([
|
|
25142
|
+
command.sandboxId,
|
|
25143
|
+
command.taskId,
|
|
25144
|
+
command.execId,
|
|
25145
|
+
descriptor.invocationId,
|
|
25146
|
+
descriptor.nonce,
|
|
25147
|
+
descriptor.controlPath,
|
|
25148
|
+
action,
|
|
25149
|
+
receiptId ?? null
|
|
25150
|
+
]);
|
|
25151
|
+
let helper = this.controlHelpers.get(key);
|
|
25152
|
+
if (!helper) {
|
|
25153
|
+
helper = {
|
|
25154
|
+
startPending: true,
|
|
25155
|
+
output: "",
|
|
25156
|
+
command: {
|
|
25157
|
+
kind: "modal-router-v1",
|
|
25158
|
+
sandboxId: command.sandboxId,
|
|
25159
|
+
taskId: command.taskId,
|
|
25160
|
+
execId: randomUUID6(),
|
|
25161
|
+
streams: {
|
|
25162
|
+
stdout: { byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null },
|
|
25163
|
+
stderr: { byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null }
|
|
25164
|
+
}
|
|
25165
|
+
}
|
|
25166
|
+
};
|
|
25167
|
+
this.controlHelpers.set(key, helper);
|
|
25168
|
+
}
|
|
25169
|
+
const observation = helper;
|
|
25170
|
+
const run2 = async () => {
|
|
25171
|
+
const signal = AbortSignal.timeout(5e3);
|
|
25172
|
+
if (observation.startPending) {
|
|
25173
|
+
try {
|
|
25174
|
+
await this.withStartRouter(command.taskId, signal, async (router) => {
|
|
25175
|
+
observation.startPending = false;
|
|
25176
|
+
await router.start(
|
|
25177
|
+
{
|
|
25178
|
+
taskId: observation.command.taskId,
|
|
25179
|
+
execId: observation.command.execId,
|
|
25180
|
+
commandArgs: [
|
|
25181
|
+
"/usr/local/bin/opengeni-command-supervisor",
|
|
25182
|
+
"control",
|
|
25183
|
+
"--invocation",
|
|
25184
|
+
descriptor.invocationId,
|
|
25185
|
+
"--nonce",
|
|
25186
|
+
descriptor.nonce,
|
|
25187
|
+
"--socket",
|
|
25188
|
+
descriptor.controlPath,
|
|
25189
|
+
"--action",
|
|
25190
|
+
action,
|
|
25191
|
+
...receiptId ? ["--receipt", receiptId] : []
|
|
25192
|
+
],
|
|
25193
|
+
workdir: "/tmp",
|
|
25194
|
+
env: {}
|
|
25195
|
+
},
|
|
25196
|
+
signal
|
|
25197
|
+
);
|
|
25198
|
+
});
|
|
25199
|
+
} catch (error) {
|
|
25200
|
+
if (observation.startPending || error instanceof ModalCommandStartNotDispatchedError || error instanceof ModalCommandStartRejectedError || error instanceof ModalCommandStartPreDispatchUnavailableError) {
|
|
25201
|
+
this.controlHelpers.delete(key);
|
|
25202
|
+
throw error;
|
|
25203
|
+
}
|
|
25204
|
+
observation.startUnknown = error;
|
|
25205
|
+
throw error;
|
|
25206
|
+
}
|
|
25207
|
+
}
|
|
25208
|
+
let response;
|
|
25209
|
+
try {
|
|
25210
|
+
response = await this.readControlOutput(observation.command, 4096, signal, observation);
|
|
25211
|
+
} catch (error) {
|
|
25212
|
+
if (observation.startUnknown !== void 0 && error instanceof ProviderCommandObservationUnavailableError)
|
|
25213
|
+
throw new ProviderCommandObservationUnavailableError(
|
|
25214
|
+
error.command,
|
|
25215
|
+
new AggregateError(
|
|
25216
|
+
[observation.startUnknown, error],
|
|
25217
|
+
"Original helper Start and observation remain uncertain"
|
|
25218
|
+
),
|
|
25219
|
+
error.readRetryAllowed
|
|
25220
|
+
);
|
|
25221
|
+
throw error;
|
|
24465
25222
|
}
|
|
25223
|
+
const { output, exit } = response;
|
|
25224
|
+
this.controlHelpers.delete(key);
|
|
24466
25225
|
if (exit !== 0) throw new Error("Supervisor control is unavailable");
|
|
24467
|
-
const result = JSON.parse(
|
|
25226
|
+
const result = JSON.parse(output);
|
|
24468
25227
|
if (!result || !["idle", "running", "quiescent"].includes(result.state))
|
|
24469
25228
|
throw new Error("Invalid supervisor control response");
|
|
24470
25229
|
if (result.receipt !== void 0) {
|
|
@@ -24475,27 +25234,169 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24475
25234
|
if (result.state === "quiescent" !== Boolean(result.receipt))
|
|
24476
25235
|
throw new Error("Supervisor quiescence response lacks its receipt");
|
|
24477
25236
|
return result;
|
|
24478
|
-
}
|
|
25237
|
+
};
|
|
25238
|
+
observation.inFlight ??= run2().finally(() => {
|
|
25239
|
+
delete observation.inFlight;
|
|
25240
|
+
});
|
|
25241
|
+
return await observation.inFlight;
|
|
25242
|
+
}
|
|
25243
|
+
/** These fixed helpers already started once. Observe only their original
|
|
25244
|
+
* invocation within the caller's existing five-second budget. */
|
|
25245
|
+
async readControlOutput(identity, limit, signal, observation) {
|
|
25246
|
+
const state = observation ?? {
|
|
25247
|
+
command: {
|
|
25248
|
+
kind: "modal-router-v1",
|
|
25249
|
+
sandboxId: this.sandboxId,
|
|
25250
|
+
...identity,
|
|
25251
|
+
streams: {
|
|
25252
|
+
stdout: { byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null },
|
|
25253
|
+
stderr: { byteOffset: 0, utf8Remainder: "", eof: false, exitCode: null }
|
|
25254
|
+
}
|
|
25255
|
+
},
|
|
25256
|
+
output: ""
|
|
25257
|
+
};
|
|
25258
|
+
for (; ; ) {
|
|
25259
|
+
try {
|
|
25260
|
+
signal.throwIfAborted();
|
|
25261
|
+
const page = await this.read(state.command, 250, signal);
|
|
25262
|
+
state.command = page.command;
|
|
25263
|
+
if (state.command.streams.stdout.byteOffset + state.command.streams.stderr.byteOffset > limit)
|
|
25264
|
+
throw new Error("Supervisor control response exceeds its bound");
|
|
25265
|
+
state.output += page.chunks.filter((chunk) => chunk.stream === "stdout").map((chunk) => chunk.text).join("");
|
|
25266
|
+
if (page.exitCode !== null) return { output: state.output, exit: page.exitCode };
|
|
25267
|
+
} catch (error) {
|
|
25268
|
+
if (signal.aborted)
|
|
25269
|
+
throw new ProviderCommandObservationUnavailableError(
|
|
25270
|
+
structuredClone(state.command),
|
|
25271
|
+
error
|
|
25272
|
+
);
|
|
25273
|
+
if (!(error instanceof ProviderCommandObservationUnavailableError) || !error.readRetryAllowed)
|
|
25274
|
+
throw error;
|
|
25275
|
+
}
|
|
25276
|
+
try {
|
|
25277
|
+
await delay3(100, void 0, { signal });
|
|
25278
|
+
} catch (error) {
|
|
25279
|
+
throw new ProviderCommandObservationUnavailableError(structuredClone(state.command), error);
|
|
25280
|
+
}
|
|
25281
|
+
}
|
|
24479
25282
|
}
|
|
24480
25283
|
async read(command, waitMs, signal) {
|
|
24481
25284
|
SandboxProviderCommand.parse(command);
|
|
24482
25285
|
if (command.sandboxId !== this.sandboxId)
|
|
24483
25286
|
throw new Error("Modal command does not belong to this sandbox");
|
|
24484
25287
|
if (command.kind === "modal-control-v1") return await this.legacy.read(command, waitMs, signal);
|
|
24485
|
-
|
|
25288
|
+
return (await this.readNative(command, waitMs, signal)).output;
|
|
25289
|
+
}
|
|
25290
|
+
/** Native capture plumbing only. Raw bytes are acquired by the same joined
|
|
25291
|
+
* read/poll path as read(); no legacy locator or new command is admitted. */
|
|
25292
|
+
async readRaw(command, waitMs, signal) {
|
|
25293
|
+
return (await this.readNative(command, waitMs, signal)).raw;
|
|
25294
|
+
}
|
|
25295
|
+
async readNative(input, waitMs, signal) {
|
|
25296
|
+
const command = structuredClone(ModalRouterProviderCommand3.parse(input));
|
|
25297
|
+
if (command.sandboxId !== this.sandboxId)
|
|
25298
|
+
throw new Error("Modal command does not belong to this sandbox");
|
|
25299
|
+
if (!Number.isFinite(waitMs) || waitMs < 0 || waitMs > 5e4)
|
|
25300
|
+
throw new Error("Invalid Modal output read bounds");
|
|
25301
|
+
signal?.throwIfAborted();
|
|
25302
|
+
const stdout = command.streams.stdout;
|
|
25303
|
+
const stderr = command.streams.stderr;
|
|
25304
|
+
if (stdout.eof && stderr.eof && stdout.utf8Remainder === "" && stderr.utf8Remainder === "" && stdout.exitCode !== null && stdout.exitCode === stderr.exitCode) {
|
|
25305
|
+
return collectModalRawOutputPage(
|
|
25306
|
+
command,
|
|
25307
|
+
{
|
|
25308
|
+
stdout: { bytes: Buffer.alloc(0), eof: true },
|
|
25309
|
+
stderr: { bytes: Buffer.alloc(0), eof: true }
|
|
25310
|
+
},
|
|
25311
|
+
{ source: "retained_terminal", code: stdout.exitCode }
|
|
25312
|
+
);
|
|
25313
|
+
}
|
|
25314
|
+
const budget = new AbortController();
|
|
25315
|
+
const abort = () => budget.abort(signal?.reason);
|
|
25316
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
25317
|
+
if (signal?.aborted) abort();
|
|
25318
|
+
const deadline = performance.now() + Math.max(1, waitMs);
|
|
25319
|
+
const timeout = setTimeout(
|
|
25320
|
+
() => budget.abort(new Error("Modal command read budget exhausted")),
|
|
25321
|
+
Math.max(1, waitMs) + 5e3
|
|
25322
|
+
);
|
|
25323
|
+
let lastError;
|
|
25324
|
+
try {
|
|
25325
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
25326
|
+
signal?.throwIfAborted();
|
|
25327
|
+
if (attempt > 0 && performance.now() >= deadline) break;
|
|
25328
|
+
try {
|
|
25329
|
+
return await this.readRouterPage(
|
|
25330
|
+
command,
|
|
25331
|
+
Math.min(Math.max(1, waitMs), Math.max(1, deadline - performance.now())),
|
|
25332
|
+
budget.signal,
|
|
25333
|
+
deadline
|
|
25334
|
+
);
|
|
25335
|
+
} catch (error) {
|
|
25336
|
+
signal?.throwIfAborted();
|
|
25337
|
+
if (!budget.signal.aborted && !isModalCommandObservationTransportError(error)) {
|
|
25338
|
+
if (classifyProviderSandboxFailure("modal", error).kind === "transient_transport")
|
|
25339
|
+
throw new ProviderCommandObservationUnavailableError(
|
|
25340
|
+
structuredClone(command),
|
|
25341
|
+
error,
|
|
25342
|
+
false
|
|
25343
|
+
);
|
|
25344
|
+
throw error;
|
|
25345
|
+
}
|
|
25346
|
+
lastError = error;
|
|
25347
|
+
if (budget.signal.aborted || performance.now() >= deadline || attempt === 4) break;
|
|
25348
|
+
try {
|
|
25349
|
+
await delay3(Math.min(100, Math.max(1, deadline - performance.now())), void 0, {
|
|
25350
|
+
signal: budget.signal
|
|
25351
|
+
});
|
|
25352
|
+
} catch {
|
|
25353
|
+
signal?.throwIfAborted();
|
|
25354
|
+
break;
|
|
25355
|
+
}
|
|
25356
|
+
}
|
|
25357
|
+
}
|
|
25358
|
+
throw new ProviderCommandObservationUnavailableError(structuredClone(command), lastError);
|
|
25359
|
+
} finally {
|
|
25360
|
+
clearTimeout(timeout);
|
|
25361
|
+
signal?.removeEventListener("abort", abort);
|
|
25362
|
+
}
|
|
25363
|
+
}
|
|
25364
|
+
async readRouterPage(command, waitMs, signal, deadline) {
|
|
24486
25365
|
const cancellation = new AbortController();
|
|
24487
|
-
const
|
|
25366
|
+
const lookupCancellation = new AbortController();
|
|
25367
|
+
const abort = () => {
|
|
25368
|
+
cancellation.abort(signal.reason);
|
|
25369
|
+
lookupCancellation.abort(signal.reason);
|
|
25370
|
+
};
|
|
24488
25371
|
signal?.addEventListener("abort", abort, { once: true });
|
|
24489
25372
|
if (signal?.aborted) abort();
|
|
25373
|
+
const lookupTimeout = setTimeout(
|
|
25374
|
+
() => lookupCancellation.abort(
|
|
25375
|
+
new ProviderCommandObservationUnavailableError(
|
|
25376
|
+
structuredClone(command),
|
|
25377
|
+
new Error("Modal command read access budget exhausted")
|
|
25378
|
+
)
|
|
25379
|
+
),
|
|
25380
|
+
Math.max(1, deadline - performance.now())
|
|
25381
|
+
);
|
|
24490
25382
|
try {
|
|
24491
|
-
return await this.withRouter(command.taskId,
|
|
25383
|
+
return await this.withRouter(command.taskId, lookupCancellation.signal, async (router) => {
|
|
25384
|
+
clearTimeout(lookupTimeout);
|
|
25385
|
+
lookupCancellation.signal.throwIfAborted();
|
|
25386
|
+
signal.throwIfAborted();
|
|
25387
|
+
if (performance.now() >= deadline)
|
|
25388
|
+
throw new ProviderCommandObservationUnavailableError(
|
|
25389
|
+
structuredClone(command),
|
|
25390
|
+
new Error("Modal command read budget exhausted")
|
|
25391
|
+
);
|
|
25392
|
+
const remainingWait = Math.max(1, Math.min(waitMs, deadline - performance.now()));
|
|
24492
25393
|
const operations = [
|
|
24493
25394
|
...["stdout", "stderr"].map(
|
|
24494
25395
|
async (stream) => command.streams[stream].eof ? { bytes: Buffer.alloc(0), eof: true } : await router.read(
|
|
24495
25396
|
command,
|
|
24496
25397
|
stream,
|
|
24497
25398
|
command.streams[stream].byteOffset,
|
|
24498
|
-
|
|
25399
|
+
remainingWait,
|
|
24499
25400
|
cancellation.signal
|
|
24500
25401
|
)
|
|
24501
25402
|
),
|
|
@@ -24510,42 +25411,18 @@ var ModalCommandControl2 = class _ModalCommandControl {
|
|
|
24510
25411
|
)
|
|
24511
25412
|
);
|
|
24512
25413
|
const failed = results.find((result) => result.status === "rejected");
|
|
24513
|
-
if (failed?.status === "rejected") throw failed.reason;
|
|
25414
|
+
if (failed?.status === "rejected") throw cancellation.signal.reason ?? failed.reason;
|
|
24514
25415
|
const stdout = results[0].value;
|
|
24515
25416
|
const stderr = results[1].value;
|
|
24516
25417
|
const exit = results[2].value;
|
|
24517
|
-
|
|
24518
|
-
|
|
24519
|
-
|
|
24520
|
-
|
|
24521
|
-
|
|
24522
|
-
const old = command.streams[stream];
|
|
24523
|
-
const decoded = decodePage(old.utf8Remainder, [page.bytes], page.eof);
|
|
24524
|
-
const byteOffset = old.byteOffset + page.bytes.length;
|
|
24525
|
-
if (!Number.isSafeInteger(byteOffset)) throw new Error("Modal output offset exhausted");
|
|
24526
|
-
next.streams[stream] = {
|
|
24527
|
-
byteOffset,
|
|
24528
|
-
utf8Remainder: decoded.remainder,
|
|
24529
|
-
eof: page.eof,
|
|
24530
|
-
exitCode: page.eof ? exit : null
|
|
24531
|
-
};
|
|
24532
|
-
if (decoded.text)
|
|
24533
|
-
chunks.push({
|
|
24534
|
-
stream,
|
|
24535
|
-
chunkId: `modal-router:${command.execId}:${stream}:${old.byteOffset}:${byteOffset}:${page.eof ? 1 : 0}`,
|
|
24536
|
-
text: decoded.text
|
|
24537
|
-
});
|
|
24538
|
-
}
|
|
24539
|
-
return {
|
|
24540
|
-
command: next,
|
|
24541
|
-
expected: structuredClone(command),
|
|
24542
|
-
chunks,
|
|
24543
|
-
exitCode: next.streams.stdout.eof && next.streams.stderr.eof ? exit : null,
|
|
24544
|
-
providerExited: exit !== null,
|
|
24545
|
-
streamFidelity: command.pty ? "merged" : "separate"
|
|
24546
|
-
};
|
|
25418
|
+
return collectModalRawOutputPage(
|
|
25419
|
+
command,
|
|
25420
|
+
{ stdout, stderr },
|
|
25421
|
+
{ source: "router_poll", code: exit }
|
|
25422
|
+
);
|
|
24547
25423
|
});
|
|
24548
25424
|
} finally {
|
|
25425
|
+
clearTimeout(lookupTimeout);
|
|
24549
25426
|
signal?.removeEventListener("abort", abort);
|
|
24550
25427
|
}
|
|
24551
25428
|
}
|
|
@@ -26241,7 +27118,7 @@ function commandForArgs(args) {
|
|
|
26241
27118
|
if (!requestedShell) return args.cmd;
|
|
26242
27119
|
return `${shellQuote(requestedShell)}${args.login === false ? "" : " -l"} -c ${shellQuote(args.cmd)}`;
|
|
26243
27120
|
}
|
|
26244
|
-
function
|
|
27121
|
+
function delay4(ms) {
|
|
26245
27122
|
return new Promise((resolve7) => setTimeout(resolve7, Math.max(0, ms)));
|
|
26246
27123
|
}
|
|
26247
27124
|
function consumeProcessOutput(process2) {
|
|
@@ -26600,7 +27477,7 @@ var OpenSandboxSession = class {
|
|
|
26600
27477
|
}
|
|
26601
27478
|
} catch {
|
|
26602
27479
|
}
|
|
26603
|
-
await
|
|
27480
|
+
await delay4(DEFAULT_WRITE_STDIN_YIELD_TIME_MS3);
|
|
26604
27481
|
}
|
|
26605
27482
|
}
|
|
26606
27483
|
async execToCompletion(args) {
|
|
@@ -26641,7 +27518,7 @@ var OpenSandboxSession = class {
|
|
|
26641
27518
|
const yieldTimeMs = requestedYieldMs >= DEFAULT_EXEC_YIELD_TIME_MS3 ? requestedYieldMs + COMMAND_API_SETTLE_GRACE_MS : requestedYieldMs;
|
|
26642
27519
|
const outcome = await Promise.race([
|
|
26643
27520
|
process2.completed.then((value) => ({ done: true, value })),
|
|
26644
|
-
|
|
27521
|
+
delay4(yieldTimeMs).then(() => ({ done: false }))
|
|
26645
27522
|
]);
|
|
26646
27523
|
const consumed = consumeProcessOutput(process2);
|
|
26647
27524
|
const output = truncateOutput(consumed.output, args.maxOutputTokens);
|
|
@@ -26753,7 +27630,7 @@ var OpenSandboxSession = class {
|
|
|
26753
27630
|
}
|
|
26754
27631
|
const outcome = await Promise.race([
|
|
26755
27632
|
process2.completed.then((value) => ({ done: true, value })),
|
|
26756
|
-
|
|
27633
|
+
delay4(args.yieldTimeMs ?? DEFAULT_WRITE_STDIN_YIELD_TIME_MS3).then(() => ({
|
|
26757
27634
|
done: false
|
|
26758
27635
|
}))
|
|
26759
27636
|
]);
|
|
@@ -33536,147 +34413,6 @@ function negotiateCapabilities(ctx) {
|
|
|
33536
34413
|
};
|
|
33537
34414
|
}
|
|
33538
34415
|
|
|
33539
|
-
// src/sandbox/provider-errors.ts
|
|
33540
|
-
var GRPC_TRANSIENT = /* @__PURE__ */ new Set([1, 2, 4, 13, 14]);
|
|
33541
|
-
var TRANSIENT_CODES = /* @__PURE__ */ new Set([
|
|
33542
|
-
"CANCELLED",
|
|
33543
|
-
"UNKNOWN",
|
|
33544
|
-
"DEADLINE_EXCEEDED",
|
|
33545
|
-
"INTERNAL",
|
|
33546
|
-
"UNAVAILABLE",
|
|
33547
|
-
"ECONNRESET",
|
|
33548
|
-
"ECONNREFUSED",
|
|
33549
|
-
"ETIMEDOUT",
|
|
33550
|
-
"EAI_AGAIN",
|
|
33551
|
-
"ENOTFOUND"
|
|
33552
|
-
]);
|
|
33553
|
-
var NOT_FOUND_CODES = /* @__PURE__ */ new Set(["404", "NOT_FOUND", "RESOURCE_NOT_FOUND", "SANDBOX_NOT_FOUND"]);
|
|
33554
|
-
var SAFE_CODE = /^[A-Z0-9._:-]{1,64}$/;
|
|
33555
|
-
function safeRead(record, key) {
|
|
33556
|
-
try {
|
|
33557
|
-
return Reflect.get(record, key);
|
|
33558
|
-
} catch {
|
|
33559
|
-
return void 0;
|
|
33560
|
-
}
|
|
33561
|
-
}
|
|
33562
|
-
function collectSignals(value) {
|
|
33563
|
-
const out = { numbers: [], codes: [], messages: [] };
|
|
33564
|
-
const seen = /* @__PURE__ */ new Set();
|
|
33565
|
-
const visit = (current, depth) => {
|
|
33566
|
-
if (depth > 3 || current === null || current === void 0) return;
|
|
33567
|
-
if (typeof current === "string") {
|
|
33568
|
-
if (current.length <= 512) out.messages.push(current);
|
|
33569
|
-
return;
|
|
33570
|
-
}
|
|
33571
|
-
if (typeof current !== "object" || seen.has(current)) return;
|
|
33572
|
-
seen.add(current);
|
|
33573
|
-
for (const key of [
|
|
33574
|
-
"status",
|
|
33575
|
-
"statusCode",
|
|
33576
|
-
"httpStatus",
|
|
33577
|
-
"httpStatusCode",
|
|
33578
|
-
"responseStatus",
|
|
33579
|
-
"errorCode",
|
|
33580
|
-
"code"
|
|
33581
|
-
]) {
|
|
33582
|
-
const signal = safeRead(current, key);
|
|
33583
|
-
if (typeof signal === "number" && Number.isFinite(signal)) out.numbers.push(signal);
|
|
33584
|
-
if (typeof signal === "string") {
|
|
33585
|
-
const code = signal.trim().toUpperCase();
|
|
33586
|
-
if (SAFE_CODE.test(code)) out.codes.push(code);
|
|
33587
|
-
}
|
|
33588
|
-
}
|
|
33589
|
-
for (const key of ["name", "message", "details", "cause"]) {
|
|
33590
|
-
const signal = safeRead(current, key);
|
|
33591
|
-
if (typeof signal === "string" && signal.length <= 512) out.messages.push(signal);
|
|
33592
|
-
else visit(signal, depth + 1);
|
|
33593
|
-
}
|
|
33594
|
-
visit(safeRead(current, "response"), depth + 1);
|
|
33595
|
-
visit(safeRead(current, "error"), depth + 1);
|
|
33596
|
-
};
|
|
33597
|
-
visit(value, 0);
|
|
33598
|
-
return out;
|
|
33599
|
-
}
|
|
33600
|
-
function safeDiagnostic(signals) {
|
|
33601
|
-
const code = signals.codes.find(Boolean);
|
|
33602
|
-
const numeric = signals.numbers.find((value) => Number.isFinite(value));
|
|
33603
|
-
return [code ? `code=${code}` : "", numeric !== void 0 ? `status=${numeric}` : ""].filter(Boolean).join(" ");
|
|
33604
|
-
}
|
|
33605
|
-
function hasTransientSignal(signals) {
|
|
33606
|
-
return signals.codes.some((code) => TRANSIENT_CODES.has(code)) || signals.numbers.some((status4) => GRPC_TRANSIENT.has(status4));
|
|
33607
|
-
}
|
|
33608
|
-
function hasModalTerminalSandboxMessage(signals) {
|
|
33609
|
-
return signals.messages.some(
|
|
33610
|
-
(message) => /^Modal sandbox [A-Za-z0-9_-]+ is no longer running\.$/.test(message) || /^Modal sandbox [A-Za-z0-9_-]+ not found \(has been terminated\)$/.test(message)
|
|
33611
|
-
);
|
|
33612
|
-
}
|
|
33613
|
-
function hasUnixLocalTerminalWorkspaceMessage(signals) {
|
|
33614
|
-
return signals.messages.includes(
|
|
33615
|
-
"UnixLocal sandbox workspace is unavailable and no local snapshot could be restored."
|
|
33616
|
-
);
|
|
33617
|
-
}
|
|
33618
|
-
function hasDockerTerminalWorkspaceMessage(signals) {
|
|
33619
|
-
return signals.messages.includes(
|
|
33620
|
-
"Docker sandbox resources are unavailable and no local snapshot could be restored."
|
|
33621
|
-
);
|
|
33622
|
-
}
|
|
33623
|
-
function hasCloudflareTerminalSandboxMessage(signals) {
|
|
33624
|
-
return signals.messages.some(
|
|
33625
|
-
(message) => /^Cloudflare sandbox [A-Za-z0-9._:-]+ is no longer running\.$/.test(message)
|
|
33626
|
-
);
|
|
33627
|
-
}
|
|
33628
|
-
function classifyProviderSandboxFailure(backendId, error) {
|
|
33629
|
-
if (backendId === "selfhosted" || !error) {
|
|
33630
|
-
return { kind: "other", diagnostic: "selfhosted-or-empty" };
|
|
33631
|
-
}
|
|
33632
|
-
const signals = collectSignals(error);
|
|
33633
|
-
const diagnostic = safeDiagnostic(signals) || "unclassified_provider_failure";
|
|
33634
|
-
if (hasTransientSignal(signals)) {
|
|
33635
|
-
return { kind: "transient_transport", diagnostic };
|
|
33636
|
-
}
|
|
33637
|
-
if (signals.numbers.some((status4) => status4 === 404) || signals.codes.some((code) => NOT_FOUND_CODES.has(code))) {
|
|
33638
|
-
return { kind: "not_found", diagnostic };
|
|
33639
|
-
}
|
|
33640
|
-
if (backendId === "modal" && hasModalTerminalSandboxMessage(signals)) {
|
|
33641
|
-
return {
|
|
33642
|
-
kind: "not_found",
|
|
33643
|
-
diagnostic: diagnostic === "unclassified_provider_failure" ? "modal_terminal_message" : `${diagnostic} modal_terminal_message`
|
|
33644
|
-
};
|
|
33645
|
-
}
|
|
33646
|
-
if (backendId === "cloudflare" && hasCloudflareTerminalSandboxMessage(signals)) {
|
|
33647
|
-
return {
|
|
33648
|
-
kind: "not_found",
|
|
33649
|
-
diagnostic: diagnostic === "unclassified_provider_failure" ? "cloudflare_terminal_message" : `${diagnostic} cloudflare_terminal_message`
|
|
33650
|
-
};
|
|
33651
|
-
}
|
|
33652
|
-
if ((backendId === "local" || backendId === "unix_local") && hasUnixLocalTerminalWorkspaceMessage(signals)) {
|
|
33653
|
-
return {
|
|
33654
|
-
kind: "not_found",
|
|
33655
|
-
diagnostic: diagnostic === "unclassified_provider_failure" ? "unix_local_workspace_missing" : `${diagnostic} unix_local_workspace_missing`
|
|
33656
|
-
};
|
|
33657
|
-
}
|
|
33658
|
-
if (backendId === "docker" && hasDockerTerminalWorkspaceMessage(signals)) {
|
|
33659
|
-
return {
|
|
33660
|
-
kind: "not_found",
|
|
33661
|
-
diagnostic: diagnostic === "unclassified_provider_failure" ? "docker_resources_missing" : `${diagnostic} docker_resources_missing`
|
|
33662
|
-
};
|
|
33663
|
-
}
|
|
33664
|
-
return { kind: "other", diagnostic };
|
|
33665
|
-
}
|
|
33666
|
-
function isProviderSandboxNotFoundError2(backendId, error) {
|
|
33667
|
-
return classifyProviderSandboxFailure(backendId, error).kind === "not_found";
|
|
33668
|
-
}
|
|
33669
|
-
function isProviderSandboxGoneDuringRoutedOperation(backendId, error) {
|
|
33670
|
-
if (backendId === "selfhosted" || !error) return false;
|
|
33671
|
-
const signals = collectSignals(error);
|
|
33672
|
-
if (hasTransientSignal(signals)) return false;
|
|
33673
|
-
if (signals.codes.includes("SANDBOX_NOT_FOUND")) return true;
|
|
33674
|
-
return backendId === "modal" && hasModalTerminalSandboxMessage(signals);
|
|
33675
|
-
}
|
|
33676
|
-
function isProviderSandboxTransientError(backendId, error) {
|
|
33677
|
-
return classifyProviderSandboxFailure(backendId, error).kind === "transient_transport";
|
|
33678
|
-
}
|
|
33679
|
-
|
|
33680
34416
|
// src/protocol-json.ts
|
|
33681
34417
|
var MAX_PROTOCOL_JSON_DEPTH = 512;
|
|
33682
34418
|
var UnsupportedProtocolJsonValueError = class extends TypeError {
|
|
@@ -37172,7 +37908,7 @@ var MAX_CREDENTIAL_FILES = 64;
|
|
|
37172
37908
|
var MAX_CREDENTIAL_FILE_BYTES = 1024 * 1024;
|
|
37173
37909
|
var MAX_TOTAL_MATERIAL_BYTES = 4 * 1024 * 1024;
|
|
37174
37910
|
var MAX_AUTH_NEEDED_NOTICES = 32;
|
|
37175
|
-
var WRITE_CHUNK_BYTES =
|
|
37911
|
+
var WRITE_CHUNK_BYTES = 1536;
|
|
37176
37912
|
var COMMAND_OK_MARKER = "__OPENGENI_RUN_CREDENTIAL_COMMAND_OK__";
|
|
37177
37913
|
var AUTH_NEEDED_REASONS = /* @__PURE__ */ new Set([
|
|
37178
37914
|
"missing_connection",
|
|
@@ -37536,23 +38272,43 @@ env -u BASH_ENV bash --noprofile --norc -c ${shellQuote8(marked)}`,
|
|
|
37536
38272
|
throw new Error("run credential materialization command failed");
|
|
37537
38273
|
}
|
|
37538
38274
|
}
|
|
37539
|
-
async function writeCredentialFile(session,
|
|
37540
|
-
await runCredentialCommand(
|
|
38275
|
+
async function writeCredentialFile(session, directory, relativePath, content, commandRunner) {
|
|
38276
|
+
await runCredentialCommand(
|
|
38277
|
+
session,
|
|
38278
|
+
credentialFileCommand(directory, relativePath, ': > "$_opengeni_credential_path"'),
|
|
38279
|
+
commandRunner
|
|
38280
|
+
);
|
|
37541
38281
|
const encoded = base64(content);
|
|
37542
38282
|
for (let offset = 0; offset < encoded.length; offset += WRITE_CHUNK_BYTES) {
|
|
37543
38283
|
const chunk = encoded.slice(offset, offset + WRITE_CHUNK_BYTES);
|
|
37544
38284
|
await runCredentialCommand(
|
|
37545
38285
|
session,
|
|
37546
|
-
|
|
38286
|
+
credentialFileCommand(
|
|
38287
|
+
directory,
|
|
38288
|
+
relativePath,
|
|
38289
|
+
`printf %s ${shellQuote8(chunk)} | ${portableBase64DecodeCommand()} >> "$_opengeni_credential_path"`
|
|
38290
|
+
),
|
|
37547
38291
|
commandRunner
|
|
37548
38292
|
);
|
|
37549
38293
|
}
|
|
37550
38294
|
await runCredentialCommand(
|
|
37551
38295
|
session,
|
|
37552
|
-
|
|
38296
|
+
credentialFileCommand(
|
|
38297
|
+
directory,
|
|
38298
|
+
relativePath,
|
|
38299
|
+
`[ "$(wc -c < "$_opengeni_credential_path" | tr -d '[:space:]')" = ${shellQuote8(String(byteLength(content)))} ]`
|
|
38300
|
+
),
|
|
37553
38301
|
commandRunner
|
|
37554
38302
|
);
|
|
37555
38303
|
}
|
|
38304
|
+
function credentialFileCommand(directory, relativePath, command) {
|
|
38305
|
+
const escapedPath = [...Buffer.from(relativePath, "utf8")].map((byte) => `\\x${byte.toString(16).padStart(2, "0")}`).join("");
|
|
38306
|
+
return [
|
|
38307
|
+
`printf -v _opengeni_credential_path %b ${shellQuote8(escapedPath)}`,
|
|
38308
|
+
`_opengeni_credential_path=${shellQuote8(directory)}/"$_opengeni_credential_path"`,
|
|
38309
|
+
command
|
|
38310
|
+
].join("\n");
|
|
38311
|
+
}
|
|
37556
38312
|
async function materializeRunCredentials(session, material, options) {
|
|
37557
38313
|
const root = runCredentialRoot(options.sessionId);
|
|
37558
38314
|
const attemptId = assertPathIdentity(options.attemptId, "attemptId");
|
|
@@ -37591,7 +38347,8 @@ async function materializeRunCredentials(session, material, options) {
|
|
|
37591
38347
|
];
|
|
37592
38348
|
await writeCredentialFile(
|
|
37593
38349
|
session,
|
|
37594
|
-
|
|
38350
|
+
stage,
|
|
38351
|
+
"env",
|
|
37595
38352
|
environmentLines.length > 0 ? `${environmentLines.join("\n")}
|
|
37596
38353
|
` : "",
|
|
37597
38354
|
options.commandRunner
|
|
@@ -37602,33 +38359,45 @@ async function materializeRunCredentials(session, material, options) {
|
|
|
37602
38359
|
options.commandRunner
|
|
37603
38360
|
);
|
|
37604
38361
|
for (const file of material.files) {
|
|
37605
|
-
const
|
|
37606
|
-
|
|
37607
|
-
|
|
37608
|
-
|
|
38362
|
+
const directory = `${stage}/files`;
|
|
38363
|
+
await runCredentialCommand(
|
|
38364
|
+
session,
|
|
38365
|
+
credentialFileCommand(directory, file.path, 'mkdir -p -- "${_opengeni_credential_path%/*}"'),
|
|
38366
|
+
options.commandRunner
|
|
38367
|
+
);
|
|
38368
|
+
await writeCredentialFile(session, directory, file.path, file.content, options.commandRunner);
|
|
37609
38369
|
await runCredentialCommand(
|
|
37610
38370
|
session,
|
|
37611
|
-
|
|
38371
|
+
credentialFileCommand(
|
|
38372
|
+
directory,
|
|
38373
|
+
file.path,
|
|
38374
|
+
`chmod -- ${shellQuote8(file.mode ?? "0600")} "$_opengeni_credential_path"`
|
|
38375
|
+
),
|
|
37612
38376
|
options.commandRunner
|
|
37613
38377
|
);
|
|
37614
38378
|
}
|
|
37615
38379
|
await runCredentialCommand(
|
|
37616
38380
|
session,
|
|
37617
38381
|
[
|
|
38382
|
+
// Bind validated identifiers once rather than repeatedly expanding long
|
|
38383
|
+
// paths through cancellation and SDK run-as shell quoting.
|
|
38384
|
+
`_opengeni_credential_root=${shellQuote8(root)}`,
|
|
38385
|
+
`_opengeni_credential_version_name=${shellQuote8(versionName)}`,
|
|
38386
|
+
`_opengeni_credential_prefix=${shellQuote8(prefix2)}`,
|
|
37618
38387
|
...pointerLockAcquireCommands(root),
|
|
37619
|
-
|
|
37620
|
-
|
|
37621
|
-
`printf '%s\\n' $
|
|
37622
|
-
|
|
38388
|
+
'previous=$(cat -- "$_opengeni_credential_root/current" 2>/dev/null || :)',
|
|
38389
|
+
'mv -- "$_opengeni_credential_root/versions/.stage-$_opengeni_credential_version_name" "$_opengeni_credential_root/versions/$_opengeni_credential_version_name"',
|
|
38390
|
+
`printf '%s\\n' "$_opengeni_credential_version_name" > "$_opengeni_credential_root/.next"`,
|
|
38391
|
+
'mv -f -- "$_opengeni_credential_root/.next" "$_opengeni_credential_root/current"',
|
|
37623
38392
|
...options.prunePreviousGenerations ? [
|
|
37624
|
-
|
|
38393
|
+
'find "$_opengeni_credential_root/versions" -mindepth 1 -maxdepth 1 ! -name "$_opengeni_credential_version_name" -exec rm -rf -- {} +'
|
|
37625
38394
|
] : options.pruneOtherAttempts ? [
|
|
37626
|
-
|
|
38395
|
+
'find "$_opengeni_credential_root/versions" -mindepth 1 -maxdepth 1 ! -name "${_opengeni_credential_prefix}*" -exec rm -rf -- {} +'
|
|
37627
38396
|
] : options.pruneSupersededGenerations ? [
|
|
37628
|
-
|
|
38397
|
+
'for candidate in "$_opengeni_credential_root/versions/$_opengeni_credential_prefix"*; do',
|
|
37629
38398
|
` [ -e "$candidate" ] || continue`,
|
|
37630
38399
|
` name=\${candidate##*/}`,
|
|
37631
|
-
|
|
38400
|
+
' [ "$name" = "$_opengeni_credential_version_name" ] || [ "$name" = "$previous" ] || rm -rf -- "$candidate"',
|
|
37632
38401
|
"done"
|
|
37633
38402
|
] : [],
|
|
37634
38403
|
...pointerLockReleaseCommands()
|
|
@@ -40379,6 +41148,8 @@ export {
|
|
|
40379
41148
|
UnsupportedProtocolJsonValueError,
|
|
40380
41149
|
normalizeProtocolJsonValue,
|
|
40381
41150
|
ProviderCommandStartOutcomeUnknownError,
|
|
41151
|
+
ProviderCommandObservationUnavailableError,
|
|
41152
|
+
isProviderCommandObservationUnavailableError,
|
|
40382
41153
|
withModalCommandStartSignal,
|
|
40383
41154
|
getModalCommandStartInvocation,
|
|
40384
41155
|
parseExecBannerSessionId,
|
|
@@ -40443,6 +41214,7 @@ export {
|
|
|
40443
41214
|
renderRoutingMutationOutcomeUnknownToolResult,
|
|
40444
41215
|
RoutingSandboxSession,
|
|
40445
41216
|
ModalCloudBucketMountStrategy,
|
|
41217
|
+
reduceModalRawOutputPage,
|
|
40446
41218
|
captureWorkspaceArchiveForStorage,
|
|
40447
41219
|
disposeWorkspaceArchive,
|
|
40448
41220
|
WorkspaceArchiveIntegrityError,
|
|
@@ -40460,6 +41232,10 @@ export {
|
|
|
40460
41232
|
CAPABILITY_DESCRIPTORS,
|
|
40461
41233
|
DESKTOP_STREAM_PORT,
|
|
40462
41234
|
assertDescriptorRegistryInvariants,
|
|
41235
|
+
classifyProviderSandboxFailure,
|
|
41236
|
+
isProviderSandboxNotFoundError2 as isProviderSandboxNotFoundError,
|
|
41237
|
+
isProviderSandboxGoneDuringRoutedOperation,
|
|
41238
|
+
isProviderSandboxTransientError,
|
|
40463
41239
|
modalSandboxAttributionEnvironment,
|
|
40464
41240
|
modalSandboxAttributionTags,
|
|
40465
41241
|
isModalTaskExecStartPreDispatchUnavailableError,
|
|
@@ -40533,10 +41309,6 @@ export {
|
|
|
40533
41309
|
backendSupportsOs,
|
|
40534
41310
|
desktopCapableBackend,
|
|
40535
41311
|
negotiateCapabilities,
|
|
40536
|
-
classifyProviderSandboxFailure,
|
|
40537
|
-
isProviderSandboxNotFoundError2 as isProviderSandboxNotFoundError,
|
|
40538
|
-
isProviderSandboxGoneDuringRoutedOperation,
|
|
40539
|
-
isProviderSandboxTransientError,
|
|
40540
41312
|
sandboxCommandExitCode,
|
|
40541
41313
|
sandboxCommandOutput,
|
|
40542
41314
|
sandboxCommandStdout,
|
|
@@ -40647,4 +41419,4 @@ export {
|
|
|
40647
41419
|
collectSandboxEnvironment2 as collectSandboxEnvironment,
|
|
40648
41420
|
parseExposedPorts2 as parseExposedPorts
|
|
40649
41421
|
};
|
|
40650
|
-
//# sourceMappingURL=chunk-
|
|
41422
|
+
//# sourceMappingURL=chunk-R25L27T3.js.map
|