@opengeni/runtime 0.14.1 → 0.14.15
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/{chunk-4YJ5Z52Z.js → chunk-7E2ZSCZK.js} +6 -6
- package/dist/{chunk-4YJ5Z52Z.js.map → chunk-7E2ZSCZK.js.map} +1 -1
- package/dist/{chunk-HHWIZHQM.js → chunk-GNEGANUF.js} +942 -300
- package/dist/chunk-GNEGANUF.js.map +1 -0
- package/dist/codex-tool-search.d.ts +100 -0
- package/dist/context-compaction.d.ts +236 -0
- package/dist/history-sanitizer.d.ts +320 -0
- package/dist/index.d.ts +186 -718
- package/dist/index.js +612 -126
- package/dist/index.js.map +1 -1
- package/dist/{localSources-T3HZ6KY4.js → localSources-BXHBKGF4.js} +2 -2
- package/dist/mcp-network.d.ts +32 -35
- package/dist/metrics.d.ts +33 -0
- package/dist/sandbox/capabilities.d.ts +11 -0
- package/dist/sandbox/channel-a.d.ts +226 -0
- package/dist/sandbox/display-stack.d.ts +99 -0
- package/dist/sandbox/errors.d.ts +16 -0
- package/dist/sandbox/exec-banner.d.ts +19 -0
- package/dist/sandbox/index.d.ts +190 -6
- package/dist/sandbox/index.js +20 -4
- package/dist/sandbox/op-correlation.d.ts +24 -0
- package/dist/sandbox/provider-errors.d.ts +32 -0
- package/dist/sandbox/provider-operation-gate.d.ts +12 -0
- package/dist/sandbox/providers/blaxel.d.ts +2 -0
- package/dist/sandbox/providers/cloudflare.d.ts +2 -0
- package/dist/sandbox/providers/daytona.d.ts +2 -0
- package/dist/sandbox/providers/docker.d.ts +2 -0
- package/dist/sandbox/providers/e2b.d.ts +2 -0
- package/dist/sandbox/providers/index.d.ts +11 -0
- package/dist/sandbox/providers/local.d.ts +2 -0
- package/dist/sandbox/providers/modal.d.ts +132 -0
- package/dist/sandbox/providers/none.d.ts +2 -0
- package/dist/sandbox/providers/runloop.d.ts +2 -0
- package/dist/sandbox/providers/selfhosted.d.ts +2 -0
- package/dist/sandbox/providers/types.d.ts +30 -0
- package/dist/sandbox/providers/vercel.d.ts +2 -0
- package/dist/sandbox/recording.d.ts +80 -0
- package/dist/sandbox/routing/backend-resolver.d.ts +173 -0
- package/dist/sandbox/routing/routing-session.d.ts +401 -0
- package/dist/sandbox/run-credentials.d.ts +65 -0
- package/dist/sandbox/select.d.ts +120 -0
- package/dist/sandbox/selfhosted/capabilities.d.ts +91 -0
- package/dist/sandbox/selfhosted/control-rpc.d.ts +175 -0
- package/dist/sandbox/selfhosted/fault-rendering.d.ts +40 -0
- package/dist/sandbox/selfhosted/op-observer.d.ts +40 -0
- package/dist/sandbox/selfhosted/op-stream.d.ts +104 -0
- package/dist/sandbox/selfhosted/op-testing.d.ts +108 -0
- package/dist/sandbox/selfhosted/op-transport.d.ts +60 -0
- package/dist/sandbox/selfhosted/retry-policy.d.ts +106 -0
- package/dist/sandbox/selfhosted/session.d.ts +552 -0
- package/dist/sandbox/selfhosted/testing.d.ts +48 -0
- package/dist/sandbox/stream-port.d.ts +80 -0
- package/dist/sandbox/stream-token.d.ts +44 -0
- package/dist/sandbox/terminal-server.d.ts +67 -0
- package/dist/sandbox/toolspace-token.d.ts +23 -0
- package/dist/sandbox/turn-tool-cancellation.d.ts +72 -0
- package/dist/sandbox/workspace-archive.d.ts +39 -0
- package/dist/sandbox-computer.d.ts +227 -0
- package/dist/screenshot-error-card.d.ts +1 -0
- package/dist/skill-library.d.ts +10 -12
- package/dist/usage-telemetry.d.ts +45 -0
- package/dist/workspace-skills.d.ts +31 -0
- package/package.json +7 -7
- package/src/context-compaction.ts +600 -6
- package/src/history-sanitizer.ts +10 -92
- package/src/index.ts +301 -62
- package/src/sandbox/channel-a.ts +267 -81
- package/src/sandbox/index.ts +56 -94
- package/src/sandbox/provider-operation-gate.ts +110 -0
- package/src/sandbox/providers/docker.ts +13 -1
- package/src/sandbox/providers/modal.ts +433 -3
- package/src/sandbox/routing/routing-session.ts +84 -8
- package/src/sandbox/selfhosted/session.ts +7 -6
- package/src/sandbox/turn-tool-cancellation.ts +47 -7
- package/src/sandbox/workspace-archive.ts +176 -73
- package/src/sandbox-computer.ts +25 -75
- package/dist/chunk-HHWIZHQM.js.map +0 -1
- package/dist/index-BraazrAO.d.ts +0 -2931
- /package/dist/{localSources-T3HZ6KY4.js.map → localSources-BXHBKGF4.js.map} +0 -0
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
validateCredentialPair,
|
|
29
29
|
validateRemoteSandboxPathForManifest,
|
|
30
30
|
validateSandboxArchiveLimits
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-7E2ZSCZK.js";
|
|
32
32
|
import {
|
|
33
33
|
FileMode,
|
|
34
34
|
Manifest,
|
|
@@ -129,7 +129,7 @@ function assertDescriptorRegistryInvariants() {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
132
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/editor.mjs
|
|
133
133
|
var RemoteSandboxEditor = class {
|
|
134
134
|
io;
|
|
135
135
|
constructor(io) {
|
|
@@ -184,7 +184,7 @@ var RemoteSandboxEditor = class {
|
|
|
184
184
|
}
|
|
185
185
|
};
|
|
186
186
|
|
|
187
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
187
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/archive.mjs
|
|
188
188
|
var TAR_BLOCK_SIZE = 512;
|
|
189
189
|
var ZERO_BLOCK = new Uint8Array(TAR_BLOCK_SIZE);
|
|
190
190
|
function assertTarWorkspacePersistence(providerName, workspacePersistence) {
|
|
@@ -624,7 +624,7 @@ function tarError(member, reason) {
|
|
|
624
624
|
});
|
|
625
625
|
}
|
|
626
626
|
|
|
627
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
627
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/metadata.mjs
|
|
628
628
|
var MOUNT_MANIFEST_METADATA_SUPPORT = {
|
|
629
629
|
mounts: true
|
|
630
630
|
};
|
|
@@ -705,7 +705,7 @@ function joinSandboxPath(parent, child) {
|
|
|
705
705
|
return `${parent.replace(/\/+$/u, "")}/${normalizedChild}`;
|
|
706
706
|
}
|
|
707
707
|
|
|
708
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
708
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/ports.mjs
|
|
709
709
|
function assertConfiguredExposedPort(args) {
|
|
710
710
|
const port = normalizeExposedPort(args.port);
|
|
711
711
|
if (args.allowOnDemand) {
|
|
@@ -768,7 +768,7 @@ function parseExposedPortEndpoint(value, args) {
|
|
|
768
768
|
};
|
|
769
769
|
}
|
|
770
770
|
|
|
771
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
771
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/pty.mjs
|
|
772
772
|
var PTY_YIELD_TIME_MS_MIN = 250;
|
|
773
773
|
var PTY_EMPTY_YIELD_TIME_MS_MIN = 5e3;
|
|
774
774
|
var PTY_YIELD_TIME_MS_MAX = 3e4;
|
|
@@ -1085,7 +1085,7 @@ function formatWebSocketEvent(event) {
|
|
|
1085
1085
|
return "unknown error";
|
|
1086
1086
|
}
|
|
1087
1087
|
|
|
1088
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
1088
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/session.mjs
|
|
1089
1089
|
async function closeRemoteSessionOnManifestError(providerName, session, manifestError) {
|
|
1090
1090
|
try {
|
|
1091
1091
|
await session.close();
|
|
@@ -1434,7 +1434,7 @@ function isNotFoundErrorMessage(message) {
|
|
|
1434
1434
|
return /\b(sandbox|sandbox instance|instance|devbox)\b.*\b(not found|missing|does not exist|no such)\b/iu.test(text) || /\b(not found|missing|does not exist|no such)\b.*\b(sandbox|sandbox instance|instance|devbox)\b/iu.test(text);
|
|
1435
1435
|
}
|
|
1436
1436
|
|
|
1437
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
1437
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/runAs.mjs
|
|
1438
1438
|
function sandboxUserShellCommand(command, user) {
|
|
1439
1439
|
if (!user) {
|
|
1440
1440
|
return command;
|
|
@@ -1566,7 +1566,7 @@ function randomId() {
|
|
|
1566
1566
|
return (globalThis.crypto?.randomUUID?.() ?? Math.random().toString(16).slice(2)).replace(/-/gu, "");
|
|
1567
1567
|
}
|
|
1568
1568
|
|
|
1569
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
1569
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/sessionBase.mjs
|
|
1570
1570
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1571
1571
|
var RemoteSandboxSessionBase = class {
|
|
1572
1572
|
state;
|
|
@@ -2004,7 +2004,7 @@ function joinRemoteCommandOutput(result) {
|
|
|
2004
2004
|
return [result.stdout ?? "", result.stderr ?? ""].filter((value) => value.trim().length > 0).join("\n");
|
|
2005
2005
|
}
|
|
2006
2006
|
|
|
2007
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
2007
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/sessionState.mjs
|
|
2008
2008
|
function serializeRemoteSandboxSessionState(state) {
|
|
2009
2009
|
return {
|
|
2010
2010
|
...state,
|
|
@@ -2034,7 +2034,7 @@ function deserializeRemotePersistedEnvironmentForRuntime(manifest, environment,
|
|
|
2034
2034
|
};
|
|
2035
2035
|
}
|
|
2036
2036
|
|
|
2037
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
2037
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/snapshots.mjs
|
|
2038
2038
|
var NATIVE_SNAPSHOT_PREFIXES = {
|
|
2039
2039
|
e2b: "E2B_SANDBOX_SNAPSHOT_V1\n",
|
|
2040
2040
|
modal_snapshot_directory: "MODAL_SANDBOX_DIR_SNAPSHOT_V1\n",
|
|
@@ -2076,10 +2076,10 @@ function decodeNativeSnapshotRef(data) {
|
|
|
2076
2076
|
return void 0;
|
|
2077
2077
|
}
|
|
2078
2078
|
|
|
2079
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
2079
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/blaxel/mounts.mjs
|
|
2080
2080
|
import { createHash } from "crypto";
|
|
2081
2081
|
|
|
2082
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
2082
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/shared/inContainerMounts.mjs
|
|
2083
2083
|
var DEFAULT_PACKAGE_MANAGERS = ["apt"];
|
|
2084
2084
|
var SAFE_PIDFILE_KILL_FUNCTION = String.raw`openai_agents_kill_pidfile() {
|
|
2085
2085
|
pidfile=$1
|
|
@@ -2699,7 +2699,7 @@ function normalizeBoxRemotePath(path) {
|
|
|
2699
2699
|
return path?.replace(/^\/+/gu, "") ?? "";
|
|
2700
2700
|
}
|
|
2701
2701
|
|
|
2702
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
2702
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/blaxel/mounts.mjs
|
|
2703
2703
|
var GCSFUSE_VERSION = "3.4.4";
|
|
2704
2704
|
var GCSFUSE_AMD64_DEB_SHA256 = "406945ecc736e8cf0eee92a617fd4a038d138c9c31e48980b99862a5f1f55bb5";
|
|
2705
2705
|
var GCSFUSE_ARM64_DEB_SHA256 = "8587fe2ee274075d8ec5a363e32761bc523a72c531922a69dd35035a371fdf3a";
|
|
@@ -3157,7 +3157,7 @@ function safeId(value) {
|
|
|
3157
3157
|
return createHash("sha256").update(value).digest("hex");
|
|
3158
3158
|
}
|
|
3159
3159
|
|
|
3160
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
3160
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/blaxel/sandbox.mjs
|
|
3161
3161
|
var BLAXEL_AUTOGENERATED_NAME_CREATE_ATTEMPTS = 5;
|
|
3162
3162
|
var BLAXEL_NON_RESUMABLE_SANDBOX_STATUSES = /* @__PURE__ */ new Set([
|
|
3163
3163
|
"DEACTIVATING",
|
|
@@ -4292,7 +4292,7 @@ var blaxelProvider = {
|
|
|
4292
4292
|
}
|
|
4293
4293
|
};
|
|
4294
4294
|
|
|
4295
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
4295
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/cloudflare/mounts.mjs
|
|
4296
4296
|
function buildCloudflareBucketMountConfig(mount) {
|
|
4297
4297
|
if (isS3Mount(mount)) {
|
|
4298
4298
|
const accessKeyId = readOptionalString(mount, "accessKeyId");
|
|
@@ -4428,7 +4428,7 @@ function validateCredentialPair4(args) {
|
|
|
4428
4428
|
});
|
|
4429
4429
|
}
|
|
4430
4430
|
|
|
4431
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
4431
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/cloudflare/sandbox.mjs
|
|
4432
4432
|
var CloudflareSandboxSession = class {
|
|
4433
4433
|
state;
|
|
4434
4434
|
apiKey;
|
|
@@ -4651,7 +4651,7 @@ var CloudflareSandboxSession = class {
|
|
|
4651
4651
|
async materializeEntry(args) {
|
|
4652
4652
|
assertSandboxEntryMetadataSupported("CloudflareSandboxClient", args.path, args.entry, MOUNT_MANIFEST_METADATA_SUPPORT);
|
|
4653
4653
|
if (entryContainsLocalSource(args.entry)) {
|
|
4654
|
-
const { applyLocalSourceManifestEntryToState: applyLocalSourceManifestEntryToState2 } = await import("./localSources-
|
|
4654
|
+
const { applyLocalSourceManifestEntryToState: applyLocalSourceManifestEntryToState2 } = await import("./localSources-BXHBKGF4.js");
|
|
4655
4655
|
await applyLocalSourceManifestEntryToState2(this.state, args.path, args.entry, "cloudflare", this.writer(), this.remotePathResolver, this.manifestMaterializationOptions(args.runAs));
|
|
4656
4656
|
return;
|
|
4657
4657
|
}
|
|
@@ -4662,7 +4662,7 @@ var CloudflareSandboxSession = class {
|
|
|
4662
4662
|
assertSandboxManifestMetadataSupported("CloudflareSandboxClient", manifest, MOUNT_MANIFEST_METADATA_SUPPORT);
|
|
4663
4663
|
assertCloudflareManifestMountsSupported(manifest);
|
|
4664
4664
|
if (manifestContainsLocalSource(manifest)) {
|
|
4665
|
-
const { applyLocalSourceManifestToState: applyLocalSourceManifestToState2 } = await import("./localSources-
|
|
4665
|
+
const { applyLocalSourceManifestToState: applyLocalSourceManifestToState2 } = await import("./localSources-BXHBKGF4.js");
|
|
4666
4666
|
await applyLocalSourceManifestToState2(this.state, manifest, "cloudflare", this.writer(), this.remotePathResolver, this.manifestMaterializationOptions(runAs));
|
|
4667
4667
|
return;
|
|
4668
4668
|
}
|
|
@@ -5581,12 +5581,12 @@ var cloudflareProvider = {
|
|
|
5581
5581
|
}
|
|
5582
5582
|
};
|
|
5583
5583
|
|
|
5584
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
5584
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/daytona/mounts.mjs
|
|
5585
5585
|
function isDaytonaCloudBucketMountEntry(entry) {
|
|
5586
5586
|
return isRcloneCloudBucketMountEntry(entry, "daytona_cloud_bucket");
|
|
5587
5587
|
}
|
|
5588
5588
|
|
|
5589
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
5589
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/daytona/sandbox.mjs
|
|
5590
5590
|
var DEFAULT_WORKSPACE_ROOT = "/home/daytona/workspace";
|
|
5591
5591
|
var DEFAULT_EXPOSED_PORT_URL_TTL_S = 60;
|
|
5592
5592
|
var DAYTONA_DELETE_RETRY_DELAYS_MS = [1e3, 2e3, 4e3];
|
|
@@ -10647,27 +10647,37 @@ function getHostDockerUser() {
|
|
|
10647
10647
|
}
|
|
10648
10648
|
|
|
10649
10649
|
// src/sandbox/providers/docker.ts
|
|
10650
|
+
import { isAbsolute as isAbsolute4 } from "path";
|
|
10650
10651
|
var dockerProvider = {
|
|
10651
10652
|
backend: "docker",
|
|
10652
10653
|
descriptor: CAPABILITY_DESCRIPTORS.docker,
|
|
10653
10654
|
// Local dev container — no credentials. (The dockerNetwork decoration is
|
|
10654
10655
|
// applied by the factory, not here: it wraps the constructed client.)
|
|
10655
|
-
validateCredentials() {
|
|
10656
|
+
validateCredentials(settings) {
|
|
10657
|
+
const workspaceBaseDir = settings.dockerWorkspaceBaseDir?.trim();
|
|
10658
|
+
if (workspaceBaseDir && !isAbsolute4(workspaceBaseDir)) {
|
|
10659
|
+
throw new SandboxConfigError(
|
|
10660
|
+
"docker",
|
|
10661
|
+
"OPENGENI_DOCKER_WORKSPACE_BASE_DIR must be an absolute path"
|
|
10662
|
+
);
|
|
10663
|
+
}
|
|
10656
10664
|
},
|
|
10657
10665
|
build({ settings, exposedPorts }) {
|
|
10666
|
+
const workspaceBaseDir = settings.dockerWorkspaceBaseDir?.trim();
|
|
10658
10667
|
return new DockerSandboxClient({
|
|
10659
10668
|
image: settings.dockerImage,
|
|
10660
|
-
exposedPorts
|
|
10669
|
+
exposedPorts,
|
|
10670
|
+
...workspaceBaseDir ? { workspaceBaseDir } : {}
|
|
10661
10671
|
});
|
|
10662
10672
|
}
|
|
10663
10673
|
};
|
|
10664
10674
|
|
|
10665
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
10675
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/e2b/mounts.mjs
|
|
10666
10676
|
function isE2BCloudBucketMountEntry(entry) {
|
|
10667
10677
|
return isRcloneCloudBucketMountEntry(entry, "e2b_cloud_bucket");
|
|
10668
10678
|
}
|
|
10669
10679
|
|
|
10670
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
10680
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/e2b/sandbox.mjs
|
|
10671
10681
|
var E2BSandboxSession = class extends RemoteSandboxSessionBase {
|
|
10672
10682
|
sandbox;
|
|
10673
10683
|
ptyProcesses = new PtyProcessRegistry();
|
|
@@ -11449,10 +11459,10 @@ var localProvider = {
|
|
|
11449
11459
|
}
|
|
11450
11460
|
};
|
|
11451
11461
|
|
|
11452
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
11462
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/modal/sandbox.mjs
|
|
11453
11463
|
import { posix as pathPosix } from "path";
|
|
11454
11464
|
|
|
11455
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
11465
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/modal/mounts.mjs
|
|
11456
11466
|
var ModalCloudBucketMountStrategy = class {
|
|
11457
11467
|
type = "modal_cloud_bucket";
|
|
11458
11468
|
secretName;
|
|
@@ -11636,7 +11646,7 @@ function isGCSMount2(entry) {
|
|
|
11636
11646
|
return entry.type === "gcs_mount";
|
|
11637
11647
|
}
|
|
11638
11648
|
|
|
11639
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
11649
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/modal/sandbox.mjs
|
|
11640
11650
|
var DEFAULT_MODAL_IMAGE_TAG = "debian:bookworm-slim";
|
|
11641
11651
|
var DEFAULT_EXEC_YIELD_TIME_MS2 = 1e4;
|
|
11642
11652
|
var DEFAULT_WRITE_STDIN_YIELD_TIME_MS2 = 250;
|
|
@@ -13058,7 +13068,11 @@ async function terminateModalSandboxAfterTimeout(sandbox) {
|
|
|
13058
13068
|
|
|
13059
13069
|
// src/sandbox/providers/modal.ts
|
|
13060
13070
|
import { effectiveModalIdleTimeoutSeconds } from "@opengeni/config";
|
|
13071
|
+
import {
|
|
13072
|
+
canonicalModalCheckpointProviderBinding
|
|
13073
|
+
} from "@opengeni/contracts";
|
|
13061
13074
|
var MODAL_ORPHAN_SWEEP_LIMIT = 50;
|
|
13075
|
+
var OPENGENI_MODAL_SDK_VERSION = "0.9.0";
|
|
13062
13076
|
var MODAL_UNATTRIBUTED_ORPHAN_GRACE_MS = 2 * 6e4;
|
|
13063
13077
|
function modalSandboxAttributionEnvironment(input) {
|
|
13064
13078
|
return {
|
|
@@ -13075,6 +13089,113 @@ function modalSandboxAttributionTags(input) {
|
|
|
13075
13089
|
opengeni_sandbox_group_id: input.sandboxGroupId
|
|
13076
13090
|
};
|
|
13077
13091
|
}
|
|
13092
|
+
var modalRetentionWrappedSessions = /* @__PURE__ */ new WeakSet();
|
|
13093
|
+
var modalFilesystemRetentionWrappedSandboxes = /* @__PURE__ */ new WeakSet();
|
|
13094
|
+
var modalDirectoryRetentionWrappedSandboxes = /* @__PURE__ */ new WeakSet();
|
|
13095
|
+
var MODAL_EXEC_STDIN_WRITE_PATH = "/modal.task_command_router.TaskCommandRouter/TaskExecStdinWrite";
|
|
13096
|
+
var MODAL_EXEC_ALREADY_COMPLETED_DETAILS = /^Exec has already completed; stdin is no longer accepting writes(?: \(Error code: [A-Z0-9]+\))?$/;
|
|
13097
|
+
function isModalExecAlreadyCompletedError(error) {
|
|
13098
|
+
if (!error || typeof error !== "object") return false;
|
|
13099
|
+
const record = error;
|
|
13100
|
+
return record.name === "ClientError" && record.path === MODAL_EXEC_STDIN_WRITE_PATH && record.code === 9 && typeof record.details === "string" && MODAL_EXEC_ALREADY_COMPLETED_DETAILS.test(record.details);
|
|
13101
|
+
}
|
|
13102
|
+
function assertPinnedModalSdk(session) {
|
|
13103
|
+
const actualVersion = session.modal?.version?.();
|
|
13104
|
+
if (actualVersion !== OPENGENI_MODAL_SDK_VERSION) {
|
|
13105
|
+
throw new Error(
|
|
13106
|
+
`OpenGeni Modal snapshot compatibility requires modal@${OPENGENI_MODAL_SDK_VERSION}; the active session reported ${actualVersion ?? "no version"}`
|
|
13107
|
+
);
|
|
13108
|
+
}
|
|
13109
|
+
}
|
|
13110
|
+
function installModalNativeSnapshotRetention(session) {
|
|
13111
|
+
const persistence = session.state?.workspacePersistence;
|
|
13112
|
+
if (persistence !== "snapshot_filesystem" && persistence !== "snapshot_directory") {
|
|
13113
|
+
return;
|
|
13114
|
+
}
|
|
13115
|
+
const sandbox = session.sandbox;
|
|
13116
|
+
if (!sandbox || typeof sandbox !== "object") {
|
|
13117
|
+
throw new Error(`Modal ${persistence} persistence has no active provider sandbox`);
|
|
13118
|
+
}
|
|
13119
|
+
if (persistence === "snapshot_filesystem") {
|
|
13120
|
+
if (modalFilesystemRetentionWrappedSandboxes.has(sandbox)) return;
|
|
13121
|
+
const snapshotFilesystem = sandbox.snapshotFilesystem;
|
|
13122
|
+
if (typeof snapshotFilesystem !== "function") {
|
|
13123
|
+
throw new Error("Modal snapshot_filesystem persistence is unavailable");
|
|
13124
|
+
}
|
|
13125
|
+
sandbox.snapshotFilesystem = async (legacyParams) => {
|
|
13126
|
+
if (legacyParams !== void 0 && typeof legacyParams !== "number") {
|
|
13127
|
+
throw new Error("Unexpected Modal snapshot_filesystem adapter call shape");
|
|
13128
|
+
}
|
|
13129
|
+
return await snapshotFilesystem.call(sandbox, {
|
|
13130
|
+
...legacyParams === void 0 ? {} : { timeoutMs: legacyParams },
|
|
13131
|
+
ttlMs: null
|
|
13132
|
+
});
|
|
13133
|
+
};
|
|
13134
|
+
modalFilesystemRetentionWrappedSandboxes.add(sandbox);
|
|
13135
|
+
return;
|
|
13136
|
+
}
|
|
13137
|
+
if (modalDirectoryRetentionWrappedSandboxes.has(sandbox)) return;
|
|
13138
|
+
const snapshotDirectory = sandbox.snapshotDirectory;
|
|
13139
|
+
if (typeof snapshotDirectory !== "function") {
|
|
13140
|
+
throw new Error("Modal snapshot_directory persistence is unavailable");
|
|
13141
|
+
}
|
|
13142
|
+
sandbox.snapshotDirectory = async (path, legacyParams) => {
|
|
13143
|
+
if (typeof path !== "string" || legacyParams !== void 0) {
|
|
13144
|
+
throw new Error("Unexpected Modal snapshot_directory adapter call shape");
|
|
13145
|
+
}
|
|
13146
|
+
return await snapshotDirectory.call(sandbox, path, {
|
|
13147
|
+
...session.state?.snapshotFilesystemTimeoutMs === void 0 ? {} : { timeoutMs: session.state.snapshotFilesystemTimeoutMs },
|
|
13148
|
+
ttlMs: null
|
|
13149
|
+
});
|
|
13150
|
+
};
|
|
13151
|
+
modalDirectoryRetentionWrappedSandboxes.add(sandbox);
|
|
13152
|
+
}
|
|
13153
|
+
function installModalExecCompletionRecovery(session) {
|
|
13154
|
+
const writeStdin = session.writeStdin;
|
|
13155
|
+
if (typeof writeStdin !== "function") return;
|
|
13156
|
+
session.writeStdin = async (args) => {
|
|
13157
|
+
try {
|
|
13158
|
+
return await writeStdin.call(session, args);
|
|
13159
|
+
} catch (error) {
|
|
13160
|
+
if (!isModalExecAlreadyCompletedError(error) || !Number.isSafeInteger(args.sessionId) || args.sessionId <= 0) {
|
|
13161
|
+
throw error;
|
|
13162
|
+
}
|
|
13163
|
+
try {
|
|
13164
|
+
return await writeStdin.call(session, { ...args, chars: "" });
|
|
13165
|
+
} catch {
|
|
13166
|
+
return `write_stdin failed: session not found: ${args.sessionId}`;
|
|
13167
|
+
}
|
|
13168
|
+
}
|
|
13169
|
+
};
|
|
13170
|
+
}
|
|
13171
|
+
function installOpenGeniModalSnapshotPolicy(session) {
|
|
13172
|
+
const mutable = session;
|
|
13173
|
+
if (modalRetentionWrappedSessions.has(session)) return session;
|
|
13174
|
+
if (typeof mutable.persistWorkspace !== "function") {
|
|
13175
|
+
throw new Error("Modal session does not expose workspace persistence");
|
|
13176
|
+
}
|
|
13177
|
+
assertPinnedModalSdk(mutable);
|
|
13178
|
+
installModalNativeSnapshotRetention(mutable);
|
|
13179
|
+
installModalExecCompletionRecovery(mutable);
|
|
13180
|
+
const persistWorkspace = mutable.persistWorkspace.bind(session);
|
|
13181
|
+
mutable.persistWorkspace = async () => {
|
|
13182
|
+
assertPinnedModalSdk(mutable);
|
|
13183
|
+
installModalNativeSnapshotRetention(mutable);
|
|
13184
|
+
return await persistWorkspace();
|
|
13185
|
+
};
|
|
13186
|
+
modalRetentionWrappedSessions.add(session);
|
|
13187
|
+
return session;
|
|
13188
|
+
}
|
|
13189
|
+
var OpenGeniModalSandboxClient = class extends ModalSandboxClient {
|
|
13190
|
+
async create(args, manifestOptions) {
|
|
13191
|
+
const session = await super.create(args, manifestOptions);
|
|
13192
|
+
return installOpenGeniModalSnapshotPolicy(session);
|
|
13193
|
+
}
|
|
13194
|
+
async resume(state) {
|
|
13195
|
+
const session = await super.resume(state);
|
|
13196
|
+
return installOpenGeniModalSnapshotPolicy(session);
|
|
13197
|
+
}
|
|
13198
|
+
};
|
|
13078
13199
|
var modalProvider = {
|
|
13079
13200
|
backend: "modal",
|
|
13080
13201
|
descriptor: CAPABILITY_DESCRIPTORS.modal,
|
|
@@ -13119,7 +13240,7 @@ var modalProvider = {
|
|
|
13119
13240
|
if (settings.modalEnvironment) {
|
|
13120
13241
|
options.environment = settings.modalEnvironment;
|
|
13121
13242
|
}
|
|
13122
|
-
return new
|
|
13243
|
+
return new OpenGeniModalSandboxClient(options);
|
|
13123
13244
|
}
|
|
13124
13245
|
};
|
|
13125
13246
|
var defaultModalLoader = () => import("modal");
|
|
@@ -13177,14 +13298,148 @@ function modalClientOptions(settings) {
|
|
|
13177
13298
|
return {
|
|
13178
13299
|
...settings.modalTokenId ? { tokenId: settings.modalTokenId } : {},
|
|
13179
13300
|
...settings.modalTokenSecret ? { tokenSecret: settings.modalTokenSecret } : {},
|
|
13180
|
-
...settings.modalEnvironment ? { environment: settings.modalEnvironment } : {}
|
|
13181
|
-
...settings.modalTimeoutSeconds ? { timeoutMs: settings.modalTimeoutSeconds * 1e3 } : {}
|
|
13301
|
+
...settings.modalEnvironment ? { environment: settings.modalEnvironment } : {}
|
|
13182
13302
|
};
|
|
13183
13303
|
}
|
|
13184
13304
|
async function createModalClient(settings) {
|
|
13185
13305
|
const modal = await import("modal");
|
|
13186
13306
|
return new modal.ModalClient(modalClientOptions(settings));
|
|
13187
13307
|
}
|
|
13308
|
+
function isModalNotFoundError(error) {
|
|
13309
|
+
const candidate = error;
|
|
13310
|
+
return candidate?.name === "NotFoundError" || candidate?.code === 5;
|
|
13311
|
+
}
|
|
13312
|
+
async function modalCheckpointProviderBindingForClient(settings, modal) {
|
|
13313
|
+
const identity = await modal.cpClient.workspaceNameLookup({});
|
|
13314
|
+
const workspaceName = identity.workspaceName || identity.username;
|
|
13315
|
+
if (!workspaceName) {
|
|
13316
|
+
throw new Error("Modal credential resolved no workspace identity");
|
|
13317
|
+
}
|
|
13318
|
+
const resolved = canonicalModalCheckpointProviderBinding({
|
|
13319
|
+
version: 1,
|
|
13320
|
+
serverUrl: modal.profile.serverUrl,
|
|
13321
|
+
workspaceName,
|
|
13322
|
+
// Resolve through the authenticated client, not the optional OpenGeni
|
|
13323
|
+
// override alone. When the override is absent Modal may select a profile
|
|
13324
|
+
// environment; persisting "" would fail to fence a later profile change.
|
|
13325
|
+
environment: modal.environmentName(settings.modalEnvironment)
|
|
13326
|
+
});
|
|
13327
|
+
if (!resolved) {
|
|
13328
|
+
throw new Error("Modal credential resolved an invalid checkpoint provider identity");
|
|
13329
|
+
}
|
|
13330
|
+
return resolved.binding;
|
|
13331
|
+
}
|
|
13332
|
+
var modalSessionCheckpointBindings = /* @__PURE__ */ new WeakMap();
|
|
13333
|
+
async function resolveModalCheckpointProviderBindingForSession(settings, session) {
|
|
13334
|
+
if (!session || typeof session !== "object") {
|
|
13335
|
+
throw new Error("Modal checkpoint session identity is unavailable");
|
|
13336
|
+
}
|
|
13337
|
+
const cached = modalSessionCheckpointBindings.get(session);
|
|
13338
|
+
if (cached) return await cached;
|
|
13339
|
+
const modal = session.modal;
|
|
13340
|
+
if (!modal || typeof modal.cpClient?.workspaceNameLookup !== "function" || typeof modal.profile?.serverUrl !== "string" || typeof modal.environmentName !== "function") {
|
|
13341
|
+
throw new Error("Pinned Modal session no longer exposes its authenticated checkpoint identity");
|
|
13342
|
+
}
|
|
13343
|
+
const pending = modalCheckpointProviderBindingForClient(settings, modal).then(
|
|
13344
|
+
(binding) => canonicalModalCheckpointProviderBinding(binding)
|
|
13345
|
+
);
|
|
13346
|
+
modalSessionCheckpointBindings.set(session, pending);
|
|
13347
|
+
try {
|
|
13348
|
+
return await pending;
|
|
13349
|
+
} catch (error) {
|
|
13350
|
+
modalSessionCheckpointBindings.delete(session);
|
|
13351
|
+
throw error;
|
|
13352
|
+
}
|
|
13353
|
+
}
|
|
13354
|
+
async function modalSessionMatchesCheckpointProviderBinding(settings, session, expectedBindingKey) {
|
|
13355
|
+
const identity = await resolveModalCheckpointProviderBindingForSession(settings, session);
|
|
13356
|
+
return identity.key === expectedBindingKey;
|
|
13357
|
+
}
|
|
13358
|
+
async function resolveModalCheckpointProviderBinding(settings, createClient = createModalClient) {
|
|
13359
|
+
const modal = await createClient(settings);
|
|
13360
|
+
try {
|
|
13361
|
+
const binding = await modalCheckpointProviderBindingForClient(settings, modal);
|
|
13362
|
+
return canonicalModalCheckpointProviderBinding(binding);
|
|
13363
|
+
} finally {
|
|
13364
|
+
modal.close();
|
|
13365
|
+
}
|
|
13366
|
+
}
|
|
13367
|
+
async function resolveModalCheckpointProviderBindingForLiveSandbox(settings, sandboxId, createClient = createModalClient) {
|
|
13368
|
+
if (!sandboxId) throw new Error("Modal live-sandbox identity requires a sandbox id");
|
|
13369
|
+
const modal = await createClient(settings);
|
|
13370
|
+
try {
|
|
13371
|
+
const binding = await modalCheckpointProviderBindingForClient(settings, modal);
|
|
13372
|
+
const sandbox = await modal.sandboxes.fromId(sandboxId);
|
|
13373
|
+
const exitCode = await sandbox.poll();
|
|
13374
|
+
if (exitCode !== null) {
|
|
13375
|
+
throw new Error(`Modal sandbox ${sandboxId} is no longer running`);
|
|
13376
|
+
}
|
|
13377
|
+
return canonicalModalCheckpointProviderBinding(binding);
|
|
13378
|
+
} finally {
|
|
13379
|
+
modal.close();
|
|
13380
|
+
}
|
|
13381
|
+
}
|
|
13382
|
+
async function inspectModalSandboxLifecycle(settings, sandboxId, expectedBindingKey, createClient = createModalClient) {
|
|
13383
|
+
if (!sandboxId) throw new Error("Modal lifecycle inspection requires a sandbox id");
|
|
13384
|
+
const modal = await createClient(settings);
|
|
13385
|
+
try {
|
|
13386
|
+
const binding = canonicalModalCheckpointProviderBinding(
|
|
13387
|
+
await modalCheckpointProviderBindingForClient(settings, modal)
|
|
13388
|
+
);
|
|
13389
|
+
if (expectedBindingKey && binding.key !== expectedBindingKey) {
|
|
13390
|
+
throw new Error(
|
|
13391
|
+
"Modal lifecycle inspection refused because the configured credential workspace changed"
|
|
13392
|
+
);
|
|
13393
|
+
}
|
|
13394
|
+
try {
|
|
13395
|
+
const sandbox = await modal.sandboxes.fromId(sandboxId);
|
|
13396
|
+
const exitCode = await sandbox.poll();
|
|
13397
|
+
return exitCode === null ? {
|
|
13398
|
+
status: "running",
|
|
13399
|
+
providerBindingKey: binding.key,
|
|
13400
|
+
providerBinding: binding.binding
|
|
13401
|
+
} : {
|
|
13402
|
+
status: "terminated",
|
|
13403
|
+
exitCode,
|
|
13404
|
+
providerBindingKey: binding.key,
|
|
13405
|
+
providerBinding: binding.binding
|
|
13406
|
+
};
|
|
13407
|
+
} catch (error) {
|
|
13408
|
+
if (isModalNotFoundError(error)) {
|
|
13409
|
+
return {
|
|
13410
|
+
status: "not_found",
|
|
13411
|
+
providerBindingKey: binding.key,
|
|
13412
|
+
providerBinding: binding.binding
|
|
13413
|
+
};
|
|
13414
|
+
}
|
|
13415
|
+
throw error;
|
|
13416
|
+
}
|
|
13417
|
+
} finally {
|
|
13418
|
+
modal.close();
|
|
13419
|
+
}
|
|
13420
|
+
}
|
|
13421
|
+
async function deleteModalCheckpointSnapshot(settings, expectedBindingKey, snapshotId, createClient = createModalClient) {
|
|
13422
|
+
if (!snapshotId) throw new Error("Modal checkpoint deletion requires a snapshot id");
|
|
13423
|
+
const modal = await createClient(settings);
|
|
13424
|
+
try {
|
|
13425
|
+
const binding = await modalCheckpointProviderBindingForClient(settings, modal);
|
|
13426
|
+
const identity = canonicalModalCheckpointProviderBinding(binding);
|
|
13427
|
+
if (expectedBindingKey !== identity.key) {
|
|
13428
|
+
throw new Error(
|
|
13429
|
+
"Modal checkpoint deletion refused because the configured credential workspace changed"
|
|
13430
|
+
);
|
|
13431
|
+
}
|
|
13432
|
+
try {
|
|
13433
|
+
await modal.images.delete(snapshotId);
|
|
13434
|
+
return "deleted";
|
|
13435
|
+
} catch (error) {
|
|
13436
|
+
if (isModalNotFoundError(error)) return "not_found";
|
|
13437
|
+
throw error;
|
|
13438
|
+
}
|
|
13439
|
+
} finally {
|
|
13440
|
+
modal.close();
|
|
13441
|
+
}
|
|
13442
|
+
}
|
|
13188
13443
|
async function tagModalSandbox(settings, sandboxId, attribution) {
|
|
13189
13444
|
if (!sandboxId) {
|
|
13190
13445
|
return false;
|
|
@@ -13359,15 +13614,15 @@ var noneProvider = {
|
|
|
13359
13614
|
}
|
|
13360
13615
|
};
|
|
13361
13616
|
|
|
13362
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
13617
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/runloop/sandbox.mjs
|
|
13363
13618
|
import { posix as pathPosix2 } from "path";
|
|
13364
13619
|
|
|
13365
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
13620
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/runloop/mounts.mjs
|
|
13366
13621
|
function isRunloopCloudBucketMountEntry(entry) {
|
|
13367
13622
|
return isRcloneCloudBucketMountEntry(entry, "runloop_cloud_bucket");
|
|
13368
13623
|
}
|
|
13369
13624
|
|
|
13370
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
13625
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/runloop/sandbox.mjs
|
|
13371
13626
|
var DEFAULT_RUNLOOP_WORKSPACE_ROOT = "/home/user";
|
|
13372
13627
|
var DEFAULT_RUNLOOP_ROOT_WORKSPACE_ROOT = "/root";
|
|
13373
13628
|
var UNKNOWN_RUNLOOP_EXIT_CODE = 1;
|
|
@@ -15950,10 +16205,11 @@ var SelfhostedSession = class {
|
|
|
15950
16205
|
}
|
|
15951
16206
|
}
|
|
15952
16207
|
}
|
|
15953
|
-
/** The clamped exec process deadline (ms): the exec-specific budget
|
|
15954
|
-
* else the control timeout.
|
|
15955
|
-
*
|
|
15956
|
-
|
|
16208
|
+
/** The effective clamped exec process deadline (ms): the exec-specific budget
|
|
16209
|
+
* when threaded, else the control timeout. Public so adapters that project a
|
|
16210
|
+
* structured command receipt can report the exact deadline the agent enforces
|
|
16211
|
+
* instead of repeating (and potentially drifting from) this normalization. */
|
|
16212
|
+
get effectiveExecDeadlineMs() {
|
|
15957
16213
|
return Math.max(
|
|
15958
16214
|
1,
|
|
15959
16215
|
Math.min(Math.trunc(this.execTimeoutMs ?? this.timeoutMs), SELFHOSTED_MAX_EXEC_TIMEOUT_MS)
|
|
@@ -15961,7 +16217,7 @@ var SelfhostedSession = class {
|
|
|
15961
16217
|
}
|
|
15962
16218
|
/** Channel-A `exec`: run a command on the machine and return its output. */
|
|
15963
16219
|
async exec(args) {
|
|
15964
|
-
const executionTimeoutMs = this.
|
|
16220
|
+
const executionTimeoutMs = this.effectiveExecDeadlineMs;
|
|
15965
16221
|
const execReq = {
|
|
15966
16222
|
// The agent does NOT shell-interpret unless `shell` — Channel-A passes a
|
|
15967
16223
|
// single shell command string, so run it through the platform shell.
|
|
@@ -16090,7 +16346,7 @@ var SelfhostedSession = class {
|
|
|
16090
16346
|
async execCommand(args) {
|
|
16091
16347
|
const result = await this.exec({ cmd: args.cmd, workdir: args.workdir, runAs: args.runAs });
|
|
16092
16348
|
if (result.timedOut) {
|
|
16093
|
-
const hint = execDeadlineHint(Math.round(this.
|
|
16349
|
+
const hint = execDeadlineHint(Math.round(this.effectiveExecDeadlineMs / 1e3));
|
|
16094
16350
|
return result.output ? `${result.output}
|
|
16095
16351
|
${hint}` : hint;
|
|
16096
16352
|
}
|
|
@@ -16606,7 +16862,7 @@ var selfhostedProvider = {
|
|
|
16606
16862
|
}
|
|
16607
16863
|
};
|
|
16608
16864
|
|
|
16609
|
-
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+
|
|
16865
|
+
// ../../node_modules/.bun/@openai+agents-extensions@0.13.3+b8edd3968b3469c2/node_modules/@openai/agents-extensions/dist/sandbox/vercel/sandbox.mjs
|
|
16610
16866
|
var DEFAULT_VERCEL_WORKSPACE_ROOT = "/vercel/sandbox";
|
|
16611
16867
|
var VercelSandboxSession = class _VercelSandboxSession extends RemoteSandboxSessionBase {
|
|
16612
16868
|
sandbox;
|
|
@@ -17602,7 +17858,99 @@ function isProviderSandboxTransientError(backendId, error) {
|
|
|
17602
17858
|
|
|
17603
17859
|
// src/sandbox/workspace-archive.ts
|
|
17604
17860
|
import { createHash as createHash4 } from "crypto";
|
|
17605
|
-
|
|
17861
|
+
import {
|
|
17862
|
+
WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION,
|
|
17863
|
+
decodeNativeSnapshotRef as decodeNativeSnapshotRef2,
|
|
17864
|
+
parseWorkspaceArchiveDescriptor
|
|
17865
|
+
} from "@opengeni/contracts";
|
|
17866
|
+
|
|
17867
|
+
// src/sandbox/provider-operation-gate.ts
|
|
17868
|
+
var providerOperationGates = /* @__PURE__ */ new WeakMap();
|
|
17869
|
+
function sessionIdentity(session) {
|
|
17870
|
+
const identityType = typeof session;
|
|
17871
|
+
if (!["object", "function"].includes(identityType) || session === null) {
|
|
17872
|
+
throw new Error("Sandbox provider operation has no session identity");
|
|
17873
|
+
}
|
|
17874
|
+
return session;
|
|
17875
|
+
}
|
|
17876
|
+
function gateFor(session) {
|
|
17877
|
+
const existing = providerOperationGates.get(session);
|
|
17878
|
+
if (existing) return existing;
|
|
17879
|
+
const created = {
|
|
17880
|
+
activeOperations: 0,
|
|
17881
|
+
captureActive: false,
|
|
17882
|
+
operationWaiters: [],
|
|
17883
|
+
captureWaiters: []
|
|
17884
|
+
};
|
|
17885
|
+
providerOperationGates.set(session, created);
|
|
17886
|
+
return created;
|
|
17887
|
+
}
|
|
17888
|
+
async function enterOperation(gate) {
|
|
17889
|
+
if (!gate.captureActive && gate.captureWaiters.length === 0) {
|
|
17890
|
+
gate.activeOperations += 1;
|
|
17891
|
+
return;
|
|
17892
|
+
}
|
|
17893
|
+
await new Promise((resolve5) => gate.operationWaiters.push(resolve5));
|
|
17894
|
+
}
|
|
17895
|
+
function leaveOperation(gate) {
|
|
17896
|
+
gate.activeOperations -= 1;
|
|
17897
|
+
if (gate.activeOperations < 0) {
|
|
17898
|
+
throw new Error("Sandbox provider operation gate underflow");
|
|
17899
|
+
}
|
|
17900
|
+
if (gate.activeOperations === 0) {
|
|
17901
|
+
const nextCapture = gate.captureWaiters.shift();
|
|
17902
|
+
if (nextCapture) {
|
|
17903
|
+
gate.captureActive = true;
|
|
17904
|
+
nextCapture();
|
|
17905
|
+
}
|
|
17906
|
+
}
|
|
17907
|
+
}
|
|
17908
|
+
async function enterCapture(gate) {
|
|
17909
|
+
if (!gate.captureActive && gate.activeOperations === 0) {
|
|
17910
|
+
gate.captureActive = true;
|
|
17911
|
+
return;
|
|
17912
|
+
}
|
|
17913
|
+
await new Promise((resolve5) => gate.captureWaiters.push(resolve5));
|
|
17914
|
+
}
|
|
17915
|
+
function leaveCapture(gate) {
|
|
17916
|
+
if (!gate.captureActive) {
|
|
17917
|
+
throw new Error("Sandbox provider capture gate was not held");
|
|
17918
|
+
}
|
|
17919
|
+
const nextCapture = gate.captureWaiters.shift();
|
|
17920
|
+
if (nextCapture) {
|
|
17921
|
+
nextCapture();
|
|
17922
|
+
return;
|
|
17923
|
+
}
|
|
17924
|
+
gate.captureActive = false;
|
|
17925
|
+
const operations = gate.operationWaiters.splice(0);
|
|
17926
|
+
gate.activeOperations += operations.length;
|
|
17927
|
+
for (const operation of operations) operation();
|
|
17928
|
+
}
|
|
17929
|
+
async function withSandboxProviderOperation(session, operation) {
|
|
17930
|
+
const gate = gateFor(sessionIdentity(session));
|
|
17931
|
+
await enterOperation(gate);
|
|
17932
|
+
try {
|
|
17933
|
+
return await operation();
|
|
17934
|
+
} finally {
|
|
17935
|
+
leaveOperation(gate);
|
|
17936
|
+
}
|
|
17937
|
+
}
|
|
17938
|
+
async function withSandboxProviderCapture(session, capture) {
|
|
17939
|
+
const gate = gateFor(sessionIdentity(session));
|
|
17940
|
+
await enterCapture(gate);
|
|
17941
|
+
try {
|
|
17942
|
+
return await capture();
|
|
17943
|
+
} finally {
|
|
17944
|
+
leaveCapture(gate);
|
|
17945
|
+
}
|
|
17946
|
+
}
|
|
17947
|
+
|
|
17948
|
+
// src/sandbox/workspace-archive.ts
|
|
17949
|
+
import {
|
|
17950
|
+
WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION as WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION2,
|
|
17951
|
+
decodeNativeSnapshotRef as decodeNativeSnapshotRef3,
|
|
17952
|
+
parseWorkspaceArchiveDescriptor as parseWorkspaceArchiveDescriptor2
|
|
17953
|
+
} from "@opengeni/contracts";
|
|
17606
17954
|
var WorkspaceArchiveIntegrityError = class extends Error {
|
|
17607
17955
|
constructor(code, message, options = {}) {
|
|
17608
17956
|
super(message);
|
|
@@ -17612,23 +17960,9 @@ var WorkspaceArchiveIntegrityError = class extends Error {
|
|
|
17612
17960
|
name = "WorkspaceArchiveIntegrityError";
|
|
17613
17961
|
retryable;
|
|
17614
17962
|
};
|
|
17615
|
-
var SHA256 = /^[a-f0-9]{64}$/;
|
|
17616
|
-
var REVISION = /^wa1:[0-9]{13}:[a-f0-9]{64}$/;
|
|
17617
17963
|
function sha256(bytes) {
|
|
17618
17964
|
return createHash4("sha256").update(bytes).digest("hex");
|
|
17619
17965
|
}
|
|
17620
|
-
function nonnegativeInteger(value) {
|
|
17621
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
17622
|
-
}
|
|
17623
|
-
function parseWorkspaceArchiveDescriptor(value) {
|
|
17624
|
-
if (!value || typeof value !== "object") return null;
|
|
17625
|
-
const candidate = value;
|
|
17626
|
-
const workspace = candidate.workspace;
|
|
17627
|
-
if (candidate.version !== WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION || typeof candidate.revision !== "string" || !REVISION.test(candidate.revision) || typeof candidate.archiveSha256 !== "string" || !SHA256.test(candidate.archiveSha256) || !nonnegativeInteger(candidate.archiveBytes) || candidate.archiveBytes === 0 || typeof candidate.capturedAt !== "string" || !Number.isFinite(Date.parse(candidate.capturedAt)) || !workspace || workspace.algorithm !== "sha256" || typeof workspace.sha256 !== "string" || !SHA256.test(workspace.sha256) || !nonnegativeInteger(workspace.entryCount) || !nonnegativeInteger(workspace.fileCount) || !nonnegativeInteger(workspace.totalFileBytes)) {
|
|
17628
|
-
return null;
|
|
17629
|
-
}
|
|
17630
|
-
return candidate;
|
|
17631
|
-
}
|
|
17632
17966
|
function decodeBase64Strict(value) {
|
|
17633
17967
|
if (value.length === 0 || value.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(value)) {
|
|
17634
17968
|
return null;
|
|
@@ -17636,6 +17970,29 @@ function decodeBase64Strict(value) {
|
|
|
17636
17970
|
const bytes = Uint8Array.from(Buffer.from(value, "base64"));
|
|
17637
17971
|
return Buffer.from(bytes).toString("base64") === value ? bytes : null;
|
|
17638
17972
|
}
|
|
17973
|
+
function describeNativeSnapshotArchive(bytes, capturedAtMs = Date.now()) {
|
|
17974
|
+
const native = decodeNativeSnapshotRef2(bytes);
|
|
17975
|
+
if (!native) return null;
|
|
17976
|
+
const archiveSha256 = sha256(bytes);
|
|
17977
|
+
return {
|
|
17978
|
+
version: WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION,
|
|
17979
|
+
kind: "provider_snapshot",
|
|
17980
|
+
revision: `wa2:${String(capturedAtMs).padStart(13, "0")}:${archiveSha256}`,
|
|
17981
|
+
archiveSha256,
|
|
17982
|
+
archiveBytes: bytes.length,
|
|
17983
|
+
capturedAt: new Date(capturedAtMs).toISOString(),
|
|
17984
|
+
provider: native.provider,
|
|
17985
|
+
snapshotId: native.snapshotId,
|
|
17986
|
+
...native.workspacePersistence ? { workspacePersistence: native.workspacePersistence } : {}
|
|
17987
|
+
};
|
|
17988
|
+
}
|
|
17989
|
+
function describeLegacyNativeSnapshotArchive(base642, observedAtMs = Date.now()) {
|
|
17990
|
+
if (typeof base642 !== "string") return null;
|
|
17991
|
+
const bytes = decodeBase64Strict(base642);
|
|
17992
|
+
if (!bytes) return null;
|
|
17993
|
+
const descriptor = describeNativeSnapshotArchive(bytes, observedAtMs);
|
|
17994
|
+
return descriptor ? { archiveBase64: base642, descriptor } : null;
|
|
17995
|
+
}
|
|
17639
17996
|
function readVerifiedWorkspaceArchive(base642, metadata) {
|
|
17640
17997
|
if (base642 === void 0 || base642 === null || base642 === "") return null;
|
|
17641
17998
|
if (typeof base642 !== "string") {
|
|
@@ -17671,7 +18028,27 @@ function readVerifiedWorkspaceArchive(base642, metadata) {
|
|
|
17671
18028
|
`workspace archive revision ${descriptor.revision} failed SHA-256/size verification`
|
|
17672
18029
|
);
|
|
17673
18030
|
}
|
|
17674
|
-
|
|
18031
|
+
const nativeSnapshot = decodeNativeSnapshotRef2(bytes);
|
|
18032
|
+
if (descriptor.version === WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION) {
|
|
18033
|
+
if (!nativeSnapshot || nativeSnapshot.provider !== descriptor.provider || nativeSnapshot.snapshotId !== descriptor.snapshotId || nativeSnapshot.workspacePersistence !== descriptor.workspacePersistence) {
|
|
18034
|
+
throw new WorkspaceArchiveIntegrityError(
|
|
18035
|
+
"native_snapshot_reference_invalid",
|
|
18036
|
+
`native snapshot receipt does not match descriptor revision ${descriptor.revision}`
|
|
18037
|
+
);
|
|
18038
|
+
}
|
|
18039
|
+
} else if (nativeSnapshot) {
|
|
18040
|
+
throw new WorkspaceArchiveIntegrityError(
|
|
18041
|
+
"native_snapshot_reference_invalid",
|
|
18042
|
+
`legacy native snapshot receipt ${descriptor.revision} was not durably upgraded to a v2 provider descriptor`
|
|
18043
|
+
);
|
|
18044
|
+
}
|
|
18045
|
+
return {
|
|
18046
|
+
bytes,
|
|
18047
|
+
base64: base642,
|
|
18048
|
+
descriptor,
|
|
18049
|
+
kind: descriptor.version === WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION ? "provider_snapshot" : "tar",
|
|
18050
|
+
...descriptor.version === WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION && nativeSnapshot ? { nativeSnapshot } : {}
|
|
18051
|
+
};
|
|
17675
18052
|
}
|
|
17676
18053
|
function stdoutFromExecResult(value) {
|
|
17677
18054
|
if (typeof value === "string") {
|
|
@@ -17682,15 +18059,33 @@ function stdoutFromExecResult(value) {
|
|
|
17682
18059
|
const output = value;
|
|
17683
18060
|
return typeof output.stdout === "string" ? output.stdout : typeof output.output === "string" ? output.output : "";
|
|
17684
18061
|
}
|
|
17685
|
-
|
|
17686
|
-
|
|
18062
|
+
function shellQuote3(value) {
|
|
18063
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
18064
|
+
}
|
|
18065
|
+
function workspaceFingerprintExcludes(session) {
|
|
18066
|
+
const paths = session.state?.manifest?.ephemeralPersistencePaths?.();
|
|
18067
|
+
if (!paths) return [];
|
|
18068
|
+
return [...paths].filter((path) => typeof path === "string" && path.length > 0).sort((left, right) => left.localeCompare(right));
|
|
18069
|
+
}
|
|
18070
|
+
function workspaceFingerprintCommand(excludedPaths) {
|
|
18071
|
+
const tarExcludes = excludedPaths.flatMap((path) => [
|
|
18072
|
+
shellQuote3(`--exclude=${path}`),
|
|
18073
|
+
shellQuote3(`--exclude=./${path}`)
|
|
18074
|
+
]);
|
|
18075
|
+
const findExcludes = excludedPaths.flatMap((path) => [
|
|
18076
|
+
`-path ${shellQuote3(`./${path}`)}`,
|
|
18077
|
+
`-path ${shellQuote3(`./${path}/*`)}`
|
|
18078
|
+
]);
|
|
18079
|
+
const findPrefix = findExcludes.length === 0 ? "" : `\\( ${findExcludes.join(" -o ")} \\) -prune -o `;
|
|
18080
|
+
const script = String.raw`set -eu
|
|
17687
18081
|
cd /workspace
|
|
17688
|
-
digest=$(LC_ALL=C tar --sort=name --mtime="@0" --owner=0 --group=0 --numeric-owner --format=gnu -cf - . | sha256sum | awk "{print \$1}")
|
|
17689
|
-
entries=$(find . -xdev -mindepth 1 -printf x | wc -c | tr -d " ")
|
|
17690
|
-
files=$(find . -xdev -type f -printf x | wc -c | tr -d " ")
|
|
17691
|
-
bytes=$(find . -xdev -type f -printf "%s\n" | awk "{s+=\$1} END {printf \"%.0f\", s+0}")
|
|
17692
|
-
printf "OPENGENI_WORKSPACE_FINGERPRINT_V1 %s %s %s %s\n" "$digest" "$entries" "$files" "$bytes"
|
|
17693
|
-
|
|
18082
|
+
digest=$(LC_ALL=C tar ${tarExcludes.join(" ")} --sort=name --mtime="@0" --owner=0 --group=0 --numeric-owner --hard-dereference --format=gnu -cf - . | sha256sum | awk "{print \$1}")
|
|
18083
|
+
entries=$(find . -xdev -mindepth 1 ${findPrefix}-printf x | wc -c | tr -d " ")
|
|
18084
|
+
files=$(find . -xdev ${findPrefix}-type f -printf x | wc -c | tr -d " ")
|
|
18085
|
+
bytes=$(find . -xdev ${findPrefix}-type f -printf "%s\n" | awk "{s+=\$1} END {printf \"%.0f\", s+0}")
|
|
18086
|
+
printf "OPENGENI_WORKSPACE_FINGERPRINT_V1 %s %s %s %s\n" "$digest" "$entries" "$files" "$bytes"`;
|
|
18087
|
+
return `bash -o pipefail -c ${shellQuote3(script)}`;
|
|
18088
|
+
}
|
|
17694
18089
|
async function fingerprintSandboxWorkspace(session) {
|
|
17695
18090
|
const target = session;
|
|
17696
18091
|
const run2 = target.exec ?? target.execCommand;
|
|
@@ -17701,7 +18096,7 @@ async function fingerprintSandboxWorkspace(session) {
|
|
|
17701
18096
|
);
|
|
17702
18097
|
}
|
|
17703
18098
|
const result = await run2.call(target, {
|
|
17704
|
-
cmd:
|
|
18099
|
+
cmd: workspaceFingerprintCommand(workspaceFingerprintExcludes(target)),
|
|
17705
18100
|
yieldTimeMs: 12e4,
|
|
17706
18101
|
maxOutputTokens: 1e3
|
|
17707
18102
|
});
|
|
@@ -17734,6 +18129,11 @@ function fingerprintsEqual(a, b) {
|
|
|
17734
18129
|
return a.sha256 === b.sha256 && a.entryCount === b.entryCount && a.fileCount === b.fileCount && a.totalFileBytes === b.totalFileBytes;
|
|
17735
18130
|
}
|
|
17736
18131
|
async function captureVerifiedWorkspaceArchive(session, capturedAtMs = Date.now()) {
|
|
18132
|
+
return await withSandboxProviderCapture(session, async () => {
|
|
18133
|
+
return await captureVerifiedWorkspaceArchiveExclusive(session, capturedAtMs);
|
|
18134
|
+
});
|
|
18135
|
+
}
|
|
18136
|
+
async function captureVerifiedWorkspaceArchiveExclusive(session, capturedAtMs) {
|
|
17737
18137
|
const target = session;
|
|
17738
18138
|
if (typeof target.persistWorkspace !== "function") {
|
|
17739
18139
|
throw new WorkspaceArchiveIntegrityError(
|
|
@@ -17741,7 +18141,10 @@ async function captureVerifiedWorkspaceArchive(session, capturedAtMs = Date.now(
|
|
|
17741
18141
|
"sandbox session does not support workspace persistence"
|
|
17742
18142
|
);
|
|
17743
18143
|
}
|
|
17744
|
-
const
|
|
18144
|
+
const configuredPersistence = target.state?.workspacePersistence;
|
|
18145
|
+
const configuredTarFallback = workspaceFingerprintExcludes(target).length > 0;
|
|
18146
|
+
const expectsNativeSnapshot = typeof configuredPersistence === "string" && configuredPersistence !== "tar" && !configuredTarFallback;
|
|
18147
|
+
const before = expectsNativeSnapshot ? null : await fingerprintSandboxWorkspace(target);
|
|
17745
18148
|
const bytes = await target.persistWorkspace();
|
|
17746
18149
|
if (!bytes || bytes.length === 0) {
|
|
17747
18150
|
throw new WorkspaceArchiveIntegrityError(
|
|
@@ -17750,8 +18153,25 @@ async function captureVerifiedWorkspaceArchive(session, capturedAtMs = Date.now(
|
|
|
17750
18153
|
{ retryable: true }
|
|
17751
18154
|
);
|
|
17752
18155
|
}
|
|
18156
|
+
const nativeSnapshot = decodeNativeSnapshotRef2(bytes);
|
|
18157
|
+
if (nativeSnapshot) {
|
|
18158
|
+
const descriptor2 = describeNativeSnapshotArchive(bytes, capturedAtMs);
|
|
18159
|
+
return {
|
|
18160
|
+
bytes,
|
|
18161
|
+
base64: Buffer.from(bytes).toString("base64"),
|
|
18162
|
+
descriptor: descriptor2,
|
|
18163
|
+
kind: "provider_snapshot",
|
|
18164
|
+
nativeSnapshot
|
|
18165
|
+
};
|
|
18166
|
+
}
|
|
18167
|
+
if (expectsNativeSnapshot) {
|
|
18168
|
+
throw new WorkspaceArchiveIntegrityError(
|
|
18169
|
+
"native_snapshot_fallback_unverified",
|
|
18170
|
+
`sandbox configured for ${String(configuredPersistence)} returned a tar archive instead of a native snapshot receipt`
|
|
18171
|
+
);
|
|
18172
|
+
}
|
|
17753
18173
|
const after = await fingerprintSandboxWorkspace(target);
|
|
17754
|
-
if (!fingerprintsEqual(before, after)) {
|
|
18174
|
+
if (!before || !fingerprintsEqual(before, after)) {
|
|
17755
18175
|
throw new WorkspaceArchiveIntegrityError(
|
|
17756
18176
|
"workspace_changed_during_capture",
|
|
17757
18177
|
"workspace changed while its durable archive was being captured",
|
|
@@ -17760,7 +18180,7 @@ async function captureVerifiedWorkspaceArchive(session, capturedAtMs = Date.now(
|
|
|
17760
18180
|
}
|
|
17761
18181
|
const archiveSha256 = sha256(bytes);
|
|
17762
18182
|
const descriptor = {
|
|
17763
|
-
version:
|
|
18183
|
+
version: 1,
|
|
17764
18184
|
revision: `wa1:${String(capturedAtMs).padStart(13, "0")}:${archiveSha256}`,
|
|
17765
18185
|
archiveSha256,
|
|
17766
18186
|
archiveBytes: bytes.length,
|
|
@@ -17770,10 +18190,14 @@ async function captureVerifiedWorkspaceArchive(session, capturedAtMs = Date.now(
|
|
|
17770
18190
|
return {
|
|
17771
18191
|
bytes,
|
|
17772
18192
|
base64: Buffer.from(bytes).toString("base64"),
|
|
17773
|
-
descriptor
|
|
18193
|
+
descriptor,
|
|
18194
|
+
kind: "tar"
|
|
17774
18195
|
};
|
|
17775
18196
|
}
|
|
17776
18197
|
async function verifyRestoredWorkspace(session, descriptor) {
|
|
18198
|
+
if (descriptor.version === WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION) {
|
|
18199
|
+
return null;
|
|
18200
|
+
}
|
|
17777
18201
|
const actual = await fingerprintSandboxWorkspace(session);
|
|
17778
18202
|
if (!fingerprintsEqual(actual, descriptor.workspace)) {
|
|
17779
18203
|
throw new WorkspaceArchiveIntegrityError(
|
|
@@ -18136,7 +18560,7 @@ function buildDisplayStackScript(options = {}) {
|
|
|
18136
18560
|
const port = options.port ?? DESKTOP_STREAM_PORT4;
|
|
18137
18561
|
const env = `DESKTOP_W=${geometry.width} DESKTOP_H=${geometry.height} DESKTOP_DPI=${geometry.dpi} STREAM_PORT=${port}`;
|
|
18138
18562
|
const lockedLauncher = `ds_started=$1; fw=$2; ds_class=cold; ds_stage() { ds_now=$(date +%s%3N); echo "OPENGENI_DISPLAY_STAGE stage=$1 elapsed_ms=$((ds_now-ds_started)) classification=$ds_class"; }; fa=$(date +%s%3N); fd=$((fa-fw)); [ "$fd" -ge 50 ] && ds_class=contention; ds_stage outer_flock_acquired; ds_stage launcher_issued; env ${env} opengeni-desktop-up; urc=$?; ds_stage launcher_complete; exit "$urc"`;
|
|
18139
|
-
const bringUp = `if nc -z 127.0.0.1 ${port} >/dev/null 2>&1 && nc -z 127.0.0.1 5900 >/dev/null 2>&1; then ds_class=already_ready; ds_stage precheck_ready; echo "OPENGENI_DESKTOP_UP port=${port} geometry=${geometry.width}x${geometry.height} dpi=${geometry.dpi} (precheck)"; else ds_class=cold; ds_stage precheck_miss; mkdir -p /tmp/opengeni-desktop; ds_stage outer_flock_wait; fw=$(date +%s%3N); flock --close --conflict-exit-code 75 --wait 45 /tmp/opengeni-desktop/up.outer.lock bash -c ${
|
|
18563
|
+
const bringUp = `if nc -z 127.0.0.1 ${port} >/dev/null 2>&1 && nc -z 127.0.0.1 5900 >/dev/null 2>&1; then ds_class=already_ready; ds_stage precheck_ready; echo "OPENGENI_DESKTOP_UP port=${port} geometry=${geometry.width}x${geometry.height} dpi=${geometry.dpi} (precheck)"; else ds_class=cold; ds_stage precheck_miss; mkdir -p /tmp/opengeni-desktop; ds_stage outer_flock_wait; fw=$(date +%s%3N); flock --close --conflict-exit-code 75 --wait 45 /tmp/opengeni-desktop/up.outer.lock bash -c ${shellQuote4(lockedLauncher)} _ "$ds_started" "$fw"; frc=$?; if [ "$frc" -eq 75 ]; then ds_stage outer_flock_timeout; echo "OPENGENI_DESKTOP_LOCK_TIMEOUT"; exit 15; fi; if [ "$frc" -ne 0 ]; then exit "$frc"; fi; fi`;
|
|
18140
18564
|
const paintProbe = `ds_stage paint_probe_started; p=/tmp/opengeni-desktop/paint-probe.png; prev=0; for i in $(seq 1 ${PAINT_PROBE_ATTEMPTS}); do if DISPLAY=:0 scrot -o "$p" >/dev/null 2>&1; then sz=$(wc -c < "$p" 2>/dev/null || echo 0); else sz=0; fi; rm -f "$p"; if [ "$sz" -ge ${PAINT_MIN_BYTES} ] && [ "$prev" -ge ${PAINT_MIN_BYTES} ]; then d=$((sz-prev)); [ "$d" -lt 0 ] && d=$((0-d)); if [ "$d" -le ${PAINT_SETTLE_DELTA_BYTES} ]; then ds_stage paint_ready; break; fi; fi; prev=$sz; if [ "$i" = "${PAINT_PROBE_ATTEMPTS}" ]; then ds_stage paint_failed; echo "OPENGENI_DESKTOP_NOT_PAINTING scrot below ${PAINT_MIN_BYTES}B or unsettled after warmup (last=$sz)"; exit 14; fi; sleep ${PAINT_PROBE_INTERVAL_S}; done`;
|
|
18141
18565
|
const trace = `ds_started=$(date +%s%3N); ds_class=unknown; ds_stage() { ds_now=$(date +%s%3N); echo "OPENGENI_DISPLAY_STAGE stage=$1 elapsed_ms=$((ds_now-ds_started)) classification=$ds_class"; }; ds_stage script_entry`;
|
|
18142
18566
|
return `${trace}; mkdir -p /tmp/opengeni-desktop; { ${bringUp} ; } && { ${paintProbe} ; }`;
|
|
@@ -18163,7 +18587,7 @@ function execResultSessionId(result) {
|
|
|
18163
18587
|
const value = result.sessionId ?? result.session_id;
|
|
18164
18588
|
return typeof value === "number" ? value : null;
|
|
18165
18589
|
}
|
|
18166
|
-
function
|
|
18590
|
+
function shellQuote4(value) {
|
|
18167
18591
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
18168
18592
|
}
|
|
18169
18593
|
function boundedDisplayStackCommand(command, timeoutMs, markerPath, markerToken) {
|
|
@@ -18175,13 +18599,13 @@ function boundedDisplayStackCommand(command, timeoutMs, markerPath, markerToken)
|
|
|
18175
18599
|
const killAfterMs = Math.max(1, Math.floor(graceMs / 2));
|
|
18176
18600
|
const commandTimeoutSeconds = (commandTimeoutMs / 1e3).toFixed(3);
|
|
18177
18601
|
const killAfterSeconds = (killAfterMs / 1e3).toFixed(3);
|
|
18178
|
-
const managedCommand = `marker=${
|
|
18602
|
+
const managedCommand = `marker=${shellQuote4(markerPath)}; token=${shellQuote4(markerToken)}; cancel="$marker.cancelled"; if [ -e "$cancel" ]; then echo "OPENGENI_DISPLAY_CANCELLED"; exit 124; fi; pid=$$; pgid=$(ps -o pgid= -p "$pid" 2>/dev/null | tr -d ' '); start=$(awk '{print $22}' "/proc/$pid/stat" 2>/dev/null || true); printf '%s %s %s %s\\n' "$pid" "$pgid" "$start" "$token" >"$marker"; if [ -e "$cancel" ]; then rm -f "$marker"; echo "OPENGENI_DISPLAY_CANCELLED"; exit 124; fi; bash -c ${shellQuote4(command)}; rc=$?; rm -f "$marker"; exit "$rc"`;
|
|
18179
18603
|
return (
|
|
18180
18604
|
// Do not use timeout --foreground here. The display command contains flock
|
|
18181
18605
|
// supervisors and launcher children; default process-group mode is required
|
|
18182
18606
|
// so a deadline cannot leave a waiter alive to acquire the lock and launch
|
|
18183
18607
|
// after the caller has already failed.
|
|
18184
|
-
`timeout --signal=TERM --kill-after=${killAfterSeconds}s ${commandTimeoutSeconds}s bash -c ${
|
|
18608
|
+
`timeout --signal=TERM --kill-after=${killAfterSeconds}s ${commandTimeoutSeconds}s bash -c ${shellQuote4(managedCommand)}; rc=$?; if [ "$rc" -eq 124 ]; then echo "OPENGENI_DISPLAY_TIMEOUT elapsed_ms=${commandTimeoutMs}"; fi; exit "$rc"`
|
|
18185
18609
|
);
|
|
18186
18610
|
}
|
|
18187
18611
|
var DisplayStackWallTimeoutError = class extends Error {
|
|
@@ -18416,10 +18840,10 @@ async function beforeDeadline(promise, deadline, now = monotonicNow) {
|
|
|
18416
18840
|
}
|
|
18417
18841
|
}
|
|
18418
18842
|
function displayStackCleanupCommand(markerPath, markerToken) {
|
|
18419
|
-
const marker =
|
|
18420
|
-
const token =
|
|
18843
|
+
const marker = shellQuote4(markerPath);
|
|
18844
|
+
const token = shellQuote4(markerToken);
|
|
18421
18845
|
const script = `marker=${marker}; token=${token}; cancel="$marker.cancelled"; : >"$cancel" || { echo "OPENGENI_DISPLAY_CLEANUP status=invalid"; exit 75; }; if [ ! -r "$marker" ]; then echo "OPENGENI_DISPLAY_CLEANUP status=stopped"; exit 0; fi; read -r pid pgid start actual <"$marker" || { echo "OPENGENI_DISPLAY_CLEANUP status=invalid"; exit 75; }; [ "$actual" = "$token" ] || { echo "OPENGENI_DISPLAY_CLEANUP status=invalid"; exit 75; }; case "$pid" in ''|*[!0-9]*) echo "OPENGENI_DISPLAY_CLEANUP status=invalid"; exit 75;; esac; case "$pgid" in ''|*[!0-9]*) echo "OPENGENI_DISPLAY_CLEANUP status=invalid"; exit 75;; esac; case "$start" in ''|*[!0-9]*) echo "OPENGENI_DISPLAY_CLEANUP status=invalid"; exit 75;; esac; current=$(awk '{print $22}' "/proc/$pid/stat" 2>/dev/null || true); if [ -z "$current" ] || [ "$current" != "$start" ]; then rm -f "$marker"; echo "OPENGENI_DISPLAY_CLEANUP status=stopped"; exit 0; fi; kill -TERM -- "-$pgid" 2>/dev/null || true; for i in $(seq 1 10); do if ! kill -0 -- "-$pgid" 2>/dev/null; then rm -f "$marker"; echo "OPENGENI_DISPLAY_CLEANUP status=stopped"; exit 0; fi; sleep 0.05; done; kill -KILL -- "-$pgid" 2>/dev/null || true; for i in $(seq 1 20); do if ! kill -0 -- "-$pgid" 2>/dev/null; then rm -f "$marker"; echo "OPENGENI_DISPLAY_CLEANUP status=stopped"; exit 0; fi; sleep 0.05; done; echo "OPENGENI_DISPLAY_CLEANUP status=alive"; exit 75`;
|
|
18422
|
-
return `timeout --signal=TERM --kill-after=0.2s 1.5s bash -c ${
|
|
18846
|
+
return `timeout --signal=TERM --kill-after=0.2s 1.5s bash -c ${shellQuote4(script)}`;
|
|
18423
18847
|
}
|
|
18424
18848
|
async function runProviderCommandToDeadline(session, command, deadline) {
|
|
18425
18849
|
const controller = new AbortController();
|
|
@@ -19163,7 +19587,7 @@ function runCredentialRoot(sessionId) {
|
|
|
19163
19587
|
function runCredentialPointerFile(sessionId) {
|
|
19164
19588
|
return `${runCredentialRoot(sessionId)}/current`;
|
|
19165
19589
|
}
|
|
19166
|
-
function
|
|
19590
|
+
function shellQuote5(value) {
|
|
19167
19591
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
19168
19592
|
}
|
|
19169
19593
|
function base64(value) {
|
|
@@ -19181,8 +19605,8 @@ function portableBase64DecodeCommand() {
|
|
|
19181
19605
|
].join("\n");
|
|
19182
19606
|
}
|
|
19183
19607
|
function pointerLockAcquireCommands(root) {
|
|
19184
|
-
const lockFile =
|
|
19185
|
-
const lockDirectory =
|
|
19608
|
+
const lockFile = shellQuote5(`${root}/.pointer.lock`);
|
|
19609
|
+
const lockDirectory = shellQuote5(`${root}/.pointer.lockdir`);
|
|
19186
19610
|
return [
|
|
19187
19611
|
`if command -v flock >/dev/null 2>&1; then`,
|
|
19188
19612
|
` exec 9>${lockFile}`,
|
|
@@ -19228,7 +19652,7 @@ ${cmd}
|
|
|
19228
19652
|
printf '\\n${COMMAND_OK_MARKER}\\n'`;
|
|
19229
19653
|
const args = {
|
|
19230
19654
|
cmd: `set +x
|
|
19231
|
-
env -u BASH_ENV bash --noprofile --norc -c ${
|
|
19655
|
+
env -u BASH_ENV bash --noprofile --norc -c ${shellQuote5(marked)}`,
|
|
19232
19656
|
yieldTimeMs: 12e4,
|
|
19233
19657
|
maxOutputTokens: 4e3
|
|
19234
19658
|
};
|
|
@@ -19238,19 +19662,19 @@ env -u BASH_ENV bash --noprofile --norc -c ${shellQuote4(marked)}`,
|
|
|
19238
19662
|
}
|
|
19239
19663
|
}
|
|
19240
19664
|
async function writeCredentialFile(session, path, content, commandRunner) {
|
|
19241
|
-
await runCredentialCommand(session, `: > ${
|
|
19665
|
+
await runCredentialCommand(session, `: > ${shellQuote5(path)}`, commandRunner);
|
|
19242
19666
|
const encoded = base64(content);
|
|
19243
19667
|
for (let offset = 0; offset < encoded.length; offset += WRITE_CHUNK_BYTES) {
|
|
19244
19668
|
const chunk = encoded.slice(offset, offset + WRITE_CHUNK_BYTES);
|
|
19245
19669
|
await runCredentialCommand(
|
|
19246
19670
|
session,
|
|
19247
|
-
`printf %s ${
|
|
19671
|
+
`printf %s ${shellQuote5(chunk)} | ${portableBase64DecodeCommand()} >> ${shellQuote5(path)}`,
|
|
19248
19672
|
commandRunner
|
|
19249
19673
|
);
|
|
19250
19674
|
}
|
|
19251
19675
|
await runCredentialCommand(
|
|
19252
19676
|
session,
|
|
19253
|
-
`[ "$(wc -c < ${
|
|
19677
|
+
`[ "$(wc -c < ${shellQuote5(path)} | tr -d '[:space:]')" = ${shellQuote5(String(byteLength(content)))} ]`,
|
|
19254
19678
|
commandRunner
|
|
19255
19679
|
);
|
|
19256
19680
|
}
|
|
@@ -19275,19 +19699,19 @@ async function materializeRunCredentials(session, material, options) {
|
|
|
19275
19699
|
session,
|
|
19276
19700
|
[
|
|
19277
19701
|
"umask 077",
|
|
19278
|
-
`mkdir -p -- ${
|
|
19279
|
-
`chmod 0700 -- ${
|
|
19280
|
-
`rm -rf -- ${
|
|
19281
|
-
`mkdir -p -- ${
|
|
19702
|
+
`mkdir -p -- ${shellQuote5(`${root}/versions`)}`,
|
|
19703
|
+
`chmod 0700 -- ${shellQuote5(root)} ${shellQuote5(`${root}/versions`)}`,
|
|
19704
|
+
`rm -rf -- ${shellQuote5(stage)}`,
|
|
19705
|
+
`mkdir -p -- ${shellQuote5(`${stage}/files`)}`
|
|
19282
19706
|
].join("\n"),
|
|
19283
19707
|
options.commandRunner
|
|
19284
19708
|
);
|
|
19285
19709
|
const environmentLines = [
|
|
19286
19710
|
...Object.entries(material.environment).map(
|
|
19287
|
-
([name, value]) => `export ${name}=${
|
|
19711
|
+
([name, value]) => `export ${name}=${shellQuote5(value)}`
|
|
19288
19712
|
),
|
|
19289
19713
|
...Object.entries(material.fileEnvironment).map(
|
|
19290
|
-
([name, path]) => `export ${name}=${
|
|
19714
|
+
([name, path]) => `export ${name}=${shellQuote5(`${version}/files/${path}`)}`
|
|
19291
19715
|
)
|
|
19292
19716
|
];
|
|
19293
19717
|
await writeCredentialFile(
|
|
@@ -19299,17 +19723,17 @@ async function materializeRunCredentials(session, material, options) {
|
|
|
19299
19723
|
);
|
|
19300
19724
|
await runCredentialCommand(
|
|
19301
19725
|
session,
|
|
19302
|
-
`chmod 0600 -- ${
|
|
19726
|
+
`chmod 0600 -- ${shellQuote5(`${stage}/env`)}`,
|
|
19303
19727
|
options.commandRunner
|
|
19304
19728
|
);
|
|
19305
19729
|
for (const file of material.files) {
|
|
19306
19730
|
const target = `${stage}/files/${file.path}`;
|
|
19307
19731
|
const parent = target.slice(0, target.lastIndexOf("/"));
|
|
19308
|
-
await runCredentialCommand(session, `mkdir -p -- ${
|
|
19732
|
+
await runCredentialCommand(session, `mkdir -p -- ${shellQuote5(parent)}`, options.commandRunner);
|
|
19309
19733
|
await writeCredentialFile(session, target, file.content, options.commandRunner);
|
|
19310
19734
|
await runCredentialCommand(
|
|
19311
19735
|
session,
|
|
19312
|
-
`chmod ${
|
|
19736
|
+
`chmod ${shellQuote5(file.mode ?? "0600")} -- ${shellQuote5(target)}`,
|
|
19313
19737
|
options.commandRunner
|
|
19314
19738
|
);
|
|
19315
19739
|
}
|
|
@@ -19317,19 +19741,19 @@ async function materializeRunCredentials(session, material, options) {
|
|
|
19317
19741
|
session,
|
|
19318
19742
|
[
|
|
19319
19743
|
...pointerLockAcquireCommands(root),
|
|
19320
|
-
`previous=$(cat -- ${
|
|
19321
|
-
`mv -- ${
|
|
19322
|
-
`printf '%s\\n' ${
|
|
19323
|
-
`mv -f -- ${
|
|
19744
|
+
`previous=$(cat -- ${shellQuote5(`${root}/current`)} 2>/dev/null || :)`,
|
|
19745
|
+
`mv -- ${shellQuote5(stage)} ${shellQuote5(version)}`,
|
|
19746
|
+
`printf '%s\\n' ${shellQuote5(versionName)} > ${shellQuote5(`${root}/.next`)}`,
|
|
19747
|
+
`mv -f -- ${shellQuote5(`${root}/.next`)} ${shellQuote5(`${root}/current`)}`,
|
|
19324
19748
|
...options.prunePreviousGenerations ? [
|
|
19325
|
-
`find ${
|
|
19749
|
+
`find ${shellQuote5(`${root}/versions`)} -mindepth 1 -maxdepth 1 ! -name ${shellQuote5(versionName)} -exec rm -rf -- {} +`
|
|
19326
19750
|
] : options.pruneOtherAttempts ? [
|
|
19327
|
-
`find ${
|
|
19751
|
+
`find ${shellQuote5(`${root}/versions`)} -mindepth 1 -maxdepth 1 ! -name ${shellQuote5(`${attemptId}-${options.executionGeneration}-*`)} -exec rm -rf -- {} +`
|
|
19328
19752
|
] : options.pruneSupersededGenerations ? [
|
|
19329
|
-
`for candidate in ${
|
|
19753
|
+
`for candidate in ${shellQuote5(`${root}/versions`)}/${prefix}*; do`,
|
|
19330
19754
|
` [ -e "$candidate" ] || continue`,
|
|
19331
19755
|
` name=\${candidate##*/}`,
|
|
19332
|
-
` [ "$name" = ${
|
|
19756
|
+
` [ "$name" = ${shellQuote5(versionName)} ] || [ "$name" = "$previous" ] || rm -rf -- "$candidate"`,
|
|
19333
19757
|
"done"
|
|
19334
19758
|
] : [],
|
|
19335
19759
|
...pointerLockReleaseCommands()
|
|
@@ -19342,10 +19766,10 @@ async function clearRunCredentials(session, sessionId, commandRunner) {
|
|
|
19342
19766
|
await runCredentialCommand(
|
|
19343
19767
|
session,
|
|
19344
19768
|
[
|
|
19345
|
-
`if [ -d ${
|
|
19769
|
+
`if [ -d ${shellQuote5(root)} ]; then`,
|
|
19346
19770
|
...pointerLockAcquireCommands(root).map((line) => ` ${line}`),
|
|
19347
|
-
` rm -f -- ${
|
|
19348
|
-
` rm -rf -- ${
|
|
19771
|
+
` rm -f -- ${shellQuote5(`${root}/current`)} ${shellQuote5(`${root}/.next`)}`,
|
|
19772
|
+
` rm -rf -- ${shellQuote5(`${root}/versions`)}`,
|
|
19349
19773
|
...pointerLockReleaseCommands().map((line) => ` ${line}`),
|
|
19350
19774
|
"fi"
|
|
19351
19775
|
].join("\n"),
|
|
@@ -19362,15 +19786,15 @@ async function clearRunCredentialsForAttempt(session, options, commandRunner) {
|
|
|
19362
19786
|
await runCredentialCommand(
|
|
19363
19787
|
session,
|
|
19364
19788
|
[
|
|
19365
|
-
`if [ -d ${
|
|
19789
|
+
`if [ -d ${shellQuote5(root)} ]; then`,
|
|
19366
19790
|
...pointerLockAcquireCommands(root).map((line) => ` ${line}`),
|
|
19367
|
-
` if [ -r ${
|
|
19368
|
-
` current=$(cat -- ${
|
|
19369
|
-
` case "$current" in ${
|
|
19791
|
+
` if [ -r ${shellQuote5(`${root}/current`)} ]; then`,
|
|
19792
|
+
` current=$(cat -- ${shellQuote5(`${root}/current`)} 2>/dev/null || :)`,
|
|
19793
|
+
` case "$current" in ${shellQuote5(prefix)}*) rm -f -- ${shellQuote5(`${root}/current`)} ;; esac`,
|
|
19370
19794
|
" fi",
|
|
19371
|
-
` if [ -d ${
|
|
19372
|
-
` find ${
|
|
19373
|
-
` find ${
|
|
19795
|
+
` if [ -d ${shellQuote5(`${root}/versions`)} ]; then`,
|
|
19796
|
+
` find ${shellQuote5(`${root}/versions`)} -mindepth 1 -maxdepth 1 -name ${shellQuote5(`${prefix}*`)} -exec rm -rf -- {} +`,
|
|
19797
|
+
` find ${shellQuote5(`${root}/versions`)} -mindepth 1 -maxdepth 1 -name ${shellQuote5(`.stage-${prefix}*`)} -exec rm -rf -- {} +`,
|
|
19374
19798
|
" fi",
|
|
19375
19799
|
...pointerLockReleaseCommands().map((line) => ` ${line}`),
|
|
19376
19800
|
"fi"
|
|
@@ -19382,12 +19806,12 @@ function withRunCredentialEnvironment(cmd, sessionId) {
|
|
|
19382
19806
|
const root = runCredentialRoot(sessionId);
|
|
19383
19807
|
const pointerFile = runCredentialPointerFile(sessionId);
|
|
19384
19808
|
return [
|
|
19385
|
-
`if [ -r ${
|
|
19386
|
-
` _opengeni_credential_version=$(cat -- ${
|
|
19809
|
+
`if [ -r ${shellQuote5(pointerFile)} ]; then`,
|
|
19810
|
+
` _opengeni_credential_version=$(cat -- ${shellQuote5(pointerFile)} 2>/dev/null || :)`,
|
|
19387
19811
|
' case "$_opengeni_credential_version" in',
|
|
19388
19812
|
" ''|*[!A-Za-z0-9_-]*) ;;",
|
|
19389
19813
|
" *)",
|
|
19390
|
-
` _opengeni_credential_env=${
|
|
19814
|
+
` _opengeni_credential_env=${shellQuote5(`${root}/versions`)}/"$_opengeni_credential_version/env"`,
|
|
19391
19815
|
' if [ -r "$_opengeni_credential_env" ]; then',
|
|
19392
19816
|
" set -a",
|
|
19393
19817
|
' . "$_opengeni_credential_env"',
|
|
@@ -19465,7 +19889,7 @@ var ToolspaceTokenPathError = class extends Error {
|
|
|
19465
19889
|
this.name = "ToolspaceTokenPathError";
|
|
19466
19890
|
}
|
|
19467
19891
|
};
|
|
19468
|
-
function
|
|
19892
|
+
function shellQuote6(value) {
|
|
19469
19893
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
19470
19894
|
}
|
|
19471
19895
|
function assertToolspaceSessionId(sessionId) {
|
|
@@ -19490,7 +19914,7 @@ function assertToolspaceFilePath(value, label) {
|
|
|
19490
19914
|
}
|
|
19491
19915
|
function shellToolspacePath(value) {
|
|
19492
19916
|
const validated = assertToolspaceFilePath(value, "Toolspace token file");
|
|
19493
|
-
return isHomeRelativeToolspacePath(validated) ? `"${validated}"` :
|
|
19917
|
+
return isHomeRelativeToolspacePath(validated) ? `"${validated}"` : shellQuote6(validated);
|
|
19494
19918
|
}
|
|
19495
19919
|
function toolspaceTokenFileForSession(manifestTokenFile, sessionId) {
|
|
19496
19920
|
const normalizedManifestFile = assertToolspaceFilePath(
|
|
@@ -20161,7 +20585,10 @@ var RoutingSandboxSession = class {
|
|
|
20161
20585
|
if (!write) throw new RoutingUnsupportedError(op, record.backend.kind);
|
|
20162
20586
|
let result;
|
|
20163
20587
|
try {
|
|
20164
|
-
result = await
|
|
20588
|
+
result = await withSandboxProviderOperation(
|
|
20589
|
+
record.backend.session,
|
|
20590
|
+
() => write.call(record.backend.session, args)
|
|
20591
|
+
);
|
|
20165
20592
|
} catch (error) {
|
|
20166
20593
|
if (this.deps.afterProcessMutation) {
|
|
20167
20594
|
const pending = {
|
|
@@ -20222,7 +20649,10 @@ var RoutingSandboxSession = class {
|
|
|
20222
20649
|
await this.ensureParentPromotion(record);
|
|
20223
20650
|
const write = record.backend.session.writeStdin;
|
|
20224
20651
|
if (!write) throw new RoutingUnsupportedError("writeStdin", record.backend.kind);
|
|
20225
|
-
const result = await
|
|
20652
|
+
const result = await withSandboxProviderOperation(
|
|
20653
|
+
record.backend.session,
|
|
20654
|
+
() => write.call(record.backend.session, args)
|
|
20655
|
+
);
|
|
20226
20656
|
const proof = retainedProcessTerminalProof(result, providerSessionId);
|
|
20227
20657
|
if (proof) await this.settleRetainedProcess(record, proof, result);
|
|
20228
20658
|
return result;
|
|
@@ -20246,7 +20676,7 @@ var RoutingSandboxSession = class {
|
|
|
20246
20676
|
const admission = mutatesWorkspace ? await this.deps.beforeMutation?.({ op, backend }) : void 0;
|
|
20247
20677
|
let result;
|
|
20248
20678
|
try {
|
|
20249
|
-
result = await fn(backend.session);
|
|
20679
|
+
result = await withSandboxProviderOperation(backend.session, () => fn(backend.session));
|
|
20250
20680
|
} catch (error) {
|
|
20251
20681
|
if (mutatesWorkspace && this.deps.afterMutation) {
|
|
20252
20682
|
try {
|
|
@@ -20466,11 +20896,21 @@ var RoutingSandboxSession = class {
|
|
|
20466
20896
|
return terminal.result;
|
|
20467
20897
|
}
|
|
20468
20898
|
await this.ensureParentPromotion(record);
|
|
20469
|
-
|
|
20470
|
-
|
|
20899
|
+
const execCommand = record.backend.session.execCommand;
|
|
20900
|
+
if (execCommand) {
|
|
20901
|
+
return await withSandboxProviderOperation(
|
|
20902
|
+
record.backend.session,
|
|
20903
|
+
() => execCommand.call(record.backend.session, args)
|
|
20904
|
+
);
|
|
20471
20905
|
}
|
|
20472
|
-
|
|
20473
|
-
|
|
20906
|
+
const exec = record.backend.session.exec;
|
|
20907
|
+
if (exec) {
|
|
20908
|
+
return formatExecResult(
|
|
20909
|
+
await withSandboxProviderOperation(
|
|
20910
|
+
record.backend.session,
|
|
20911
|
+
() => exec.call(record.backend.session, args)
|
|
20912
|
+
)
|
|
20913
|
+
);
|
|
20474
20914
|
}
|
|
20475
20915
|
throw new RoutingUnsupportedError("execCommand", record.backend.kind);
|
|
20476
20916
|
}
|
|
@@ -20525,7 +20965,11 @@ var RoutingSandboxSession = class {
|
|
|
20525
20965
|
if (!s.materializeEntry) {
|
|
20526
20966
|
throw new RoutingUnsupportedError("materializeEntry", this.cached?.kind ?? "unknown");
|
|
20527
20967
|
}
|
|
20528
|
-
|
|
20968
|
+
await s.materializeEntry(args);
|
|
20969
|
+
const path = args && typeof args === "object" && typeof args.path === "string" ? args.path : null;
|
|
20970
|
+
if (path) {
|
|
20971
|
+
await assertProviderCanSeeMaterializedPath(s, path);
|
|
20972
|
+
}
|
|
20529
20973
|
});
|
|
20530
20974
|
}
|
|
20531
20975
|
/** PTY support reflects the LAST-resolved backend (a synchronous probe; the SDK
|
|
@@ -20589,6 +21033,39 @@ var RoutingSandboxSession = class {
|
|
|
20589
21033
|
return this.resolve();
|
|
20590
21034
|
}
|
|
20591
21035
|
};
|
|
21036
|
+
var MATERIALIZED_PATH_MARKER = "__OPENGENI_MATERIALIZED_PATH_VISIBLE__";
|
|
21037
|
+
async function assertProviderCanSeeMaterializedPath(session, path) {
|
|
21038
|
+
const command = `test -e ${shellSingleQuote(path)} && printf %s ${shellSingleQuote(
|
|
21039
|
+
MATERIALIZED_PATH_MARKER
|
|
21040
|
+
)}`;
|
|
21041
|
+
const args = {
|
|
21042
|
+
cmd: command,
|
|
21043
|
+
workdir: providerManifestRoot(session) ?? "/workspace",
|
|
21044
|
+
shell: "sh",
|
|
21045
|
+
login: false,
|
|
21046
|
+
tty: false
|
|
21047
|
+
};
|
|
21048
|
+
let output;
|
|
21049
|
+
if (session.execCommand) {
|
|
21050
|
+
output = await session.execCommand(args);
|
|
21051
|
+
} else if (session.exec) {
|
|
21052
|
+
output = formatExecResult(await session.exec(args));
|
|
21053
|
+
} else {
|
|
21054
|
+
throw new RoutingUnsupportedError("materializeEntry.verify", "unknown");
|
|
21055
|
+
}
|
|
21056
|
+
if (!output.includes(MATERIALIZED_PATH_MARKER)) {
|
|
21057
|
+
throw new Error(
|
|
21058
|
+
`Sandbox materialization completed but the provider cannot read the destination path: ${path}`
|
|
21059
|
+
);
|
|
21060
|
+
}
|
|
21061
|
+
}
|
|
21062
|
+
function providerManifestRoot(session) {
|
|
21063
|
+
const root = session.state?.manifest?.root;
|
|
21064
|
+
return typeof root === "string" && root.length > 0 ? root : null;
|
|
21065
|
+
}
|
|
21066
|
+
function shellSingleQuote(value) {
|
|
21067
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
21068
|
+
}
|
|
20592
21069
|
|
|
20593
21070
|
// src/sandbox/turn-tool-cancellation.ts
|
|
20594
21071
|
var TURN_EXEC_YIELD_MS = 250;
|
|
@@ -20692,15 +21169,52 @@ function singleQuote(value) {
|
|
|
20692
21169
|
function shellMarkerPath(token) {
|
|
20693
21170
|
return `${SHELL_MARKER_DIR}/${token}`;
|
|
20694
21171
|
}
|
|
21172
|
+
function processInspectionCommandLines() {
|
|
21173
|
+
return [
|
|
21174
|
+
"__opengeni_process_group_id() {",
|
|
21175
|
+
' __opengeni_lookup_pid="$1"',
|
|
21176
|
+
' __opengeni_lookup_pgid=""',
|
|
21177
|
+
" if command -v ps >/dev/null 2>&1; then",
|
|
21178
|
+
` __opengeni_lookup_pgid="$(command ps -o pgid= -p "$__opengeni_lookup_pid" 2>/dev/null | command tr -d '[:space:]')"`,
|
|
21179
|
+
" fi",
|
|
21180
|
+
' case "$__opengeni_lookup_pgid" in',
|
|
21181
|
+
' ""|*[!0-9]*) ;;',
|
|
21182
|
+
` *) command printf '%s\\n' "$__opengeni_lookup_pgid"; return 0 ;;`,
|
|
21183
|
+
" esac",
|
|
21184
|
+
' [ -r "/proc/$__opengeni_lookup_pid/stat" ] || return 1',
|
|
21185
|
+
' IFS= read -r __opengeni_lookup_stat < "/proc/$__opengeni_lookup_pid/stat" || return 1',
|
|
21186
|
+
' __opengeni_lookup_tail="${__opengeni_lookup_stat##*) }"',
|
|
21187
|
+
' [ "$__opengeni_lookup_tail" != "$__opengeni_lookup_stat" ] || return 1',
|
|
21188
|
+
" set -- $__opengeni_lookup_tail",
|
|
21189
|
+
' [ "$#" -ge 3 ] || return 1',
|
|
21190
|
+
' case "$3" in ""|*[!0-9]*) return 1 ;; esac',
|
|
21191
|
+
` command printf '%s\\n' "$3"`,
|
|
21192
|
+
"}",
|
|
21193
|
+
"__opengeni_process_args() {",
|
|
21194
|
+
' __opengeni_lookup_pid="$1"',
|
|
21195
|
+
' __opengeni_lookup_args=""',
|
|
21196
|
+
" if command -v ps >/dev/null 2>&1; then",
|
|
21197
|
+
' __opengeni_lookup_args="$(command ps -ww -o args= -p "$__opengeni_lookup_pid" 2>/dev/null)"',
|
|
21198
|
+
" fi",
|
|
21199
|
+
' if [ -n "$__opengeni_lookup_args" ]; then',
|
|
21200
|
+
` command printf '%s\\n' "$__opengeni_lookup_args"`,
|
|
21201
|
+
" return 0",
|
|
21202
|
+
" fi",
|
|
21203
|
+
' [ -r "/proc/$__opengeni_lookup_pid/cmdline" ] || return 1',
|
|
21204
|
+
` command tr '\\000' ' ' < "/proc/$__opengeni_lookup_pid/cmdline"`,
|
|
21205
|
+
"}"
|
|
21206
|
+
];
|
|
21207
|
+
}
|
|
20695
21208
|
function cancellableGroupLeaderCommand(command, markerPath) {
|
|
20696
21209
|
const marker = singleQuote(markerPath);
|
|
20697
21210
|
const markerDir = singleQuote(SHELL_MARKER_DIR);
|
|
20698
21211
|
return [
|
|
21212
|
+
...processInspectionCommandLines(),
|
|
20699
21213
|
`__opengeni_marker=${marker}`,
|
|
20700
21214
|
"umask 077",
|
|
20701
21215
|
`command mkdir -p ${markerDir} || exit 125`,
|
|
20702
21216
|
'__opengeni_pid="$$"',
|
|
20703
|
-
|
|
21217
|
+
'__opengeni_pgid="$(__opengeni_process_group_id "$__opengeni_pid")"',
|
|
20704
21218
|
'case "$__opengeni_pid:$__opengeni_pgid" in *[!0-9:]*|*:|:*) exit 125 ;; esac',
|
|
20705
21219
|
'[ "$__opengeni_pid" -gt 1 ] && [ "$__opengeni_pgid" -gt 1 ] || exit 125',
|
|
20706
21220
|
// Never signal a provider/container-wide process group. A cancellable PTY
|
|
@@ -20718,8 +21232,9 @@ function cancellableGroupLeaderCommand(command, markerPath) {
|
|
|
20718
21232
|
function cancellableShellCommand(command, markerPath) {
|
|
20719
21233
|
const groupLeaderCommand = cancellableGroupLeaderCommand(command, markerPath);
|
|
20720
21234
|
return [
|
|
21235
|
+
...processInspectionCommandLines(),
|
|
20721
21236
|
'__opengeni_outer_pid="$$"',
|
|
20722
|
-
|
|
21237
|
+
'__opengeni_outer_pgid="$(__opengeni_process_group_id "$__opengeni_outer_pid")"',
|
|
20723
21238
|
'case "$__opengeni_outer_pid:$__opengeni_outer_pgid" in *[!0-9:]*|*:|:*) exit 125 ;; esac',
|
|
20724
21239
|
'if [ "$__opengeni_outer_pid" != "$__opengeni_outer_pgid" ]; then',
|
|
20725
21240
|
' __opengeni_setsid="$(command -v setsid 2>/dev/null)"',
|
|
@@ -20764,15 +21279,16 @@ function identityGuardScript(state, body, missingIdentityExitCode) {
|
|
|
20764
21279
|
if (!identity || !state.token) return `exit ${missingIdentityExitCode}`;
|
|
20765
21280
|
const token = singleQuote(state.token);
|
|
20766
21281
|
return [
|
|
21282
|
+
...processInspectionCommandLines(),
|
|
20767
21283
|
`__opengeni_pid=${identity.pid}`,
|
|
20768
21284
|
`__opengeni_pgid=${identity.processGroupId}`,
|
|
20769
21285
|
`__opengeni_token=${token}`,
|
|
20770
|
-
// The randomized token lands late in the wrapped command line. Procps
|
|
20771
|
-
//
|
|
20772
|
-
//
|
|
20773
|
-
|
|
21286
|
+
// The randomized token lands late in the wrapped command line. Procps needs
|
|
21287
|
+
// `-ww` to avoid terminal-width truncation; minimal Linux images may omit ps,
|
|
21288
|
+
// so the same exact command line is read from /proc instead.
|
|
21289
|
+
`__opengeni_args="$(__opengeni_process_args "$__opengeni_pid")" || exit ${missingIdentityExitCode}`,
|
|
20774
21290
|
'case "$__opengeni_args" in *"$__opengeni_token"*) ;; *) exit 0 ;; esac',
|
|
20775
|
-
`__opengeni_live_pgid="$(
|
|
21291
|
+
`__opengeni_live_pgid="$(__opengeni_process_group_id "$__opengeni_pid")" || exit ${missingIdentityExitCode}`,
|
|
20776
21292
|
'[ "$__opengeni_live_pgid" = "$__opengeni_pgid" ] || exit 0',
|
|
20777
21293
|
body
|
|
20778
21294
|
].join("\n");
|
|
@@ -21445,6 +21961,42 @@ var FS_LIST_TRUNCATED_MARKER = "__OPENGENI_FS_LIST_TRUNCATED__";
|
|
|
21445
21961
|
var FS_LIST_MAX_OUTPUT_BYTES = 768 * 1024;
|
|
21446
21962
|
var GIT_COMMAND_CHUNK_BYTES = 512 * 1024;
|
|
21447
21963
|
var GIT_METADATA_MAX_BYTES = 2 * 1024 * 1024;
|
|
21964
|
+
var GIT_MEASURE_FRAME = "__OPENGENI_GIT_MEASURE_V1__";
|
|
21965
|
+
var GIT_CHUNK_FRAME = "__OPENGENI_GIT_CHUNK_V1__";
|
|
21966
|
+
var GIT_CHUNK_FRAME_END = "__OPENGENI_GIT_CHUNK_END_V1__";
|
|
21967
|
+
var PORTABLE_SHA256_FILE_FUNCTION = [
|
|
21968
|
+
"opengeni_sha256_file() {",
|
|
21969
|
+
` if command -v sha256sum >/dev/null 2>&1 && digest=$(sha256sum -- "$1" 2>/dev/null); then printf "%s\\n" "$digest" | awk '{print $1}'; return; fi`,
|
|
21970
|
+
` if command -v shasum >/dev/null 2>&1 && digest=$(shasum -a 256 "$1" 2>/dev/null); then printf "%s\\n" "$digest" | awk '{print $1}'; return; fi`,
|
|
21971
|
+
` if command -v openssl >/dev/null 2>&1 && digest=$(openssl dgst -sha256 "$1" 2>/dev/null); then printf "%s\\n" "$digest" | sed 's/^.*= //'; return; fi`,
|
|
21972
|
+
" return 127",
|
|
21973
|
+
"}"
|
|
21974
|
+
].join("\n");
|
|
21975
|
+
var PORTABLE_DESCRIPTOR_FUNCTIONS = [
|
|
21976
|
+
"opengeni_set_fd_path() {",
|
|
21977
|
+
' fd="$1"',
|
|
21978
|
+
" opengeni_fd_path=",
|
|
21979
|
+
' if opengeni_fd_path=$(readlink -f -- "/proc/$$/fd/$fd" 2>/dev/null); then [ -n "$opengeni_fd_path" ]; return; fi',
|
|
21980
|
+
" lsof_bin=",
|
|
21981
|
+
" if [ -x /usr/sbin/lsof ]; then lsof_bin=/usr/sbin/lsof; elif command -v lsof >/dev/null 2>&1; then lsof_bin=$(command -v lsof); else return 127; fi",
|
|
21982
|
+
` while IFS= read -r -d '' field; do case "$field" in n*) opengeni_fd_path=\${field#n} ;; esac; done < <("$lsof_bin" -a -p "$$" -d "$fd" -Fn0 2>/dev/null)`,
|
|
21983
|
+
' [ -n "$opengeni_fd_path" ]',
|
|
21984
|
+
"}",
|
|
21985
|
+
"opengeni_fd_identity() {",
|
|
21986
|
+
' fd="$1"',
|
|
21987
|
+
' if identity=$(stat -Lc "%d:%i" -- "/proc/$$/fd/$fd" 2>/dev/null); then printf "%s" "$identity"; return; fi',
|
|
21988
|
+
' stat -f "%d:%i" "/dev/fd/$fd" 2>/dev/null',
|
|
21989
|
+
"}",
|
|
21990
|
+
"opengeni_path_identity() {",
|
|
21991
|
+
' if identity=$(stat -c "%d:%i" -- "$1" 2>/dev/null); then printf "%s" "$identity"; return; fi',
|
|
21992
|
+
' stat -f "%d:%i" "$1" 2>/dev/null',
|
|
21993
|
+
"}",
|
|
21994
|
+
"opengeni_fd_size() {",
|
|
21995
|
+
' fd="$1"',
|
|
21996
|
+
' if size=$(stat -Lc "%s" -- "/proc/$$/fd/$fd" 2>/dev/null); then printf "%s" "$size"; return; fi',
|
|
21997
|
+
' stat -f "%z" "/dev/fd/$fd" 2>/dev/null',
|
|
21998
|
+
"}"
|
|
21999
|
+
].join("\n");
|
|
21448
22000
|
var US = String.fromCharCode(31);
|
|
21449
22001
|
var RS = String.fromCharCode(30);
|
|
21450
22002
|
var SELFHOSTED_VIRTUAL_ROOT2 = "/workspace";
|
|
@@ -21534,11 +22086,11 @@ var SandboxChannelAService = class {
|
|
|
21534
22086
|
const depthArg = Math.max(1, req.depth);
|
|
21535
22087
|
const maxCommandEntries = req.maxEntries + 1;
|
|
21536
22088
|
const gnuPrint = `-printf '%y\\t%s\\t%T@\\t%m\\t%p\\0'`;
|
|
21537
|
-
const gnuSelector = pruneNames.length ? `\\( -type d \\( ${pruneNames.map((name) => `-name ${
|
|
22089
|
+
const gnuSelector = pruneNames.length ? `\\( -type d \\( ${pruneNames.map((name) => `-name ${shellQuote7(name)}`).join(" -o ")} \\) ${gnuPrint} -prune \\) -o ${gnuPrint}` : gnuPrint;
|
|
21538
22090
|
const gnuVisibleSelector = req.includeHidden ? gnuSelector : `\\( -path '*/.*' -prune \\) -o \\( ${gnuSelector} \\)`;
|
|
21539
22091
|
const gnuFind = `find ${findRoot} -mindepth 1 -maxdepth ${depthArg} \\( ${gnuVisibleSelector} \\) 2>/dev/null`;
|
|
21540
22092
|
const portableHiddenGuard = req.includeHidden ? "" : `if [[ "$base" == .* ]]; then continue; fi;`;
|
|
21541
|
-
const portablePruneCase = pruneNames.length ? `case "$base" in ${pruneNames.map(
|
|
22093
|
+
const portablePruneCase = pruneNames.length ? `case "$base" in ${pruneNames.map(shellQuote7).join("|")}) pruned=1 ;; *) pruned=0 ;; esac;` : "pruned=0;";
|
|
21542
22094
|
const portableWalk = [
|
|
21543
22095
|
"shopt -s nullglob dotglob; count=0; stop=0;",
|
|
21544
22096
|
'walk() { local dir="$1" level="$2" p base t size mtime mode pruned;',
|
|
@@ -21567,12 +22119,12 @@ var SandboxChannelAService = class {
|
|
|
21567
22119
|
`if [ "$records" -ge ${req.maxEntries} ] || [ $((bytes + record_bytes + 1)) -gt ${FS_LIST_MAX_OUTPUT_BYTES} ]; then truncated=1; break; fi;`,
|
|
21568
22120
|
`printf '%s\\0' "$record"; bytes=$((bytes + record_bytes + 1)); records=$((records + 1));`,
|
|
21569
22121
|
"done;",
|
|
21570
|
-
`if [ "$truncated" -eq 1 ]; then printf '%s\\0' ${
|
|
22122
|
+
`if [ "$truncated" -eq 1 ]; then printf '%s\\0' ${shellQuote7(FS_LIST_TRUNCATED_MARKER)}; fi`
|
|
21571
22123
|
].join(" ");
|
|
21572
22124
|
const findCommand = [
|
|
21573
22125
|
`{ ${rawFindCommand}; } | { ${boundedOutput}; };`,
|
|
21574
22126
|
"producer_status=${PIPESTATUS[0]};",
|
|
21575
|
-
`if [ "$producer_status" -ne 0 ] && [ "$producer_status" -ne 141 ]; then printf '%s\\0' ${
|
|
22127
|
+
`if [ "$producer_status" -ne 0 ] && [ "$producer_status" -ne 141 ]; then printf '%s\\0' ${shellQuote7(FS_LIST_TRUNCATED_MARKER)}; fi`
|
|
21576
22128
|
].join(" ");
|
|
21577
22129
|
const { stdout, exitCode } = await this.runInConfinedDirectory(root, {
|
|
21578
22130
|
cmd: internalBashCommand(findCommand),
|
|
@@ -21665,11 +22217,11 @@ var SandboxChannelAService = class {
|
|
|
21665
22217
|
async assertConfinedExistingDirectory(path) {
|
|
21666
22218
|
const root = this.workspaceRoot || ".";
|
|
21667
22219
|
const abs = this.joinRoot(path);
|
|
21668
|
-
const rejectLink = path ? `test ! -L ${
|
|
22220
|
+
const rejectLink = path ? `test ! -L ${shellQuote7(abs)} || { printf '__OPENGENI_FS_SYMLINK__'; exit 68; }` : ":";
|
|
21669
22221
|
const script = [
|
|
21670
|
-
`root=$(realpath -e -- ${
|
|
22222
|
+
`root=$(realpath -e -- ${shellQuote7(root)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
21671
22223
|
rejectLink,
|
|
21672
|
-
`target=$(realpath -e -- ${
|
|
22224
|
+
`target=$(realpath -e -- ${shellQuote7(abs)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
21673
22225
|
`case "$target" in "$root"|"$root"/*) ;; *) printf '__OPENGENI_FS_ESCAPE__'; exit 67 ;; esac`,
|
|
21674
22226
|
`test -d "$target" || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
21675
22227
|
`printf '__OPENGENI_FS_CONFINED_OK__'`
|
|
@@ -21680,13 +22232,13 @@ var SandboxChannelAService = class {
|
|
|
21680
22232
|
async assertConfinedMutationParent(path, options) {
|
|
21681
22233
|
const root = this.workspaceRoot || ".";
|
|
21682
22234
|
const abs = this.joinRoot(path);
|
|
21683
|
-
const rejectLink = options.rejectFinalSymlink ? `test ! -L ${
|
|
22235
|
+
const rejectLink = options.rejectFinalSymlink ? `test ! -L ${shellQuote7(abs)} || { printf '__OPENGENI_FS_SYMLINK__'; exit 68; }` : ":";
|
|
21684
22236
|
const locateParent = options.allowMissingParents ? 'probe="$parent"; while [ ! -e "$probe" ] && [ ! -L "$probe" ]; do next=$(dirname -- "$probe"); [ "$next" != "$probe" ] || break; probe="$next"; done' : 'probe="$parent"';
|
|
21685
22237
|
const requireParent = options.allowMissingParents ? ":" : 'test -d "$parent" || { printf "__OPENGENI_FS_NOT_FOUND__"; exit 66; }';
|
|
21686
22238
|
const script = [
|
|
21687
|
-
`root=$(realpath -e -- ${
|
|
22239
|
+
`root=$(realpath -e -- ${shellQuote7(root)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
21688
22240
|
rejectLink,
|
|
21689
|
-
`parent=$(dirname -- ${
|
|
22241
|
+
`parent=$(dirname -- ${shellQuote7(abs)})`,
|
|
21690
22242
|
locateParent,
|
|
21691
22243
|
`target=$(realpath -e -- "$probe") || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
21692
22244
|
`case "$target" in "$root"|"$root"/*) ;; *) printf '__OPENGENI_FS_ESCAPE__'; exit 67 ;; esac`,
|
|
@@ -21723,8 +22275,8 @@ var SandboxChannelAService = class {
|
|
|
21723
22275
|
const root = this.workspaceRoot || ".";
|
|
21724
22276
|
const abs = this.joinRoot(path);
|
|
21725
22277
|
const script = [
|
|
21726
|
-
`root=$(realpath -e -- ${
|
|
21727
|
-
`exec 3<${
|
|
22278
|
+
`root=$(realpath -e -- ${shellQuote7(root)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
22279
|
+
`exec 3<${shellQuote7(abs)} || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
21728
22280
|
`target=$(readlink -f -- "/proc/$$/fd/3") || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
21729
22281
|
`case "$target" in "$root"|"$root"/*) ;; *) printf '__OPENGENI_FS_ESCAPE__'; exit 67 ;; esac`,
|
|
21730
22282
|
`test -f "$target" || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
@@ -21793,7 +22345,7 @@ var SandboxChannelAService = class {
|
|
|
21793
22345
|
});
|
|
21794
22346
|
if (!req.overwrite) {
|
|
21795
22347
|
const { exitCode: exitCode2 } = await this.run({
|
|
21796
|
-
cmd: `test -e ${
|
|
22348
|
+
cmd: `test -e ${shellQuote7(abs)} || test -L ${shellQuote7(abs)}`
|
|
21797
22349
|
});
|
|
21798
22350
|
if (exitCode2 === 0) {
|
|
21799
22351
|
throw new ChannelAConflictError(`path exists and overwrite is false: ${path}`);
|
|
@@ -21801,7 +22353,7 @@ var SandboxChannelAService = class {
|
|
|
21801
22353
|
}
|
|
21802
22354
|
if (req.createParents) {
|
|
21803
22355
|
const dir = dirnameAbs(abs);
|
|
21804
|
-
if (dir) await this.run({ cmd: `mkdir -p ${
|
|
22356
|
+
if (dir) await this.run({ cmd: `mkdir -p ${shellQuote7(dir)}` });
|
|
21805
22357
|
await this.assertConfinedMutationParent(path, {
|
|
21806
22358
|
allowMissingParents: false,
|
|
21807
22359
|
rejectFinalSymlink: true
|
|
@@ -21809,7 +22361,7 @@ var SandboxChannelAService = class {
|
|
|
21809
22361
|
}
|
|
21810
22362
|
const b64 = bytes.toString("base64");
|
|
21811
22363
|
const { exitCode, stderr } = await this.run({
|
|
21812
|
-
cmd: `printf %s ${
|
|
22364
|
+
cmd: `printf %s ${shellQuote7(b64)} | base64 -d > ${shellQuote7(abs)}`
|
|
21813
22365
|
});
|
|
21814
22366
|
if (exitCode !== null && exitCode !== 0) {
|
|
21815
22367
|
if (req.encoding !== "base64" && this.session.createEditor) {
|
|
@@ -21850,7 +22402,7 @@ var SandboxChannelAService = class {
|
|
|
21850
22402
|
rejectFinalSymlink: false
|
|
21851
22403
|
});
|
|
21852
22404
|
const flag = req.recursive ? "-rf" : "-f";
|
|
21853
|
-
const { exitCode, stderr } = await this.run({ cmd: `rm ${flag} ${
|
|
22405
|
+
const { exitCode, stderr } = await this.run({ cmd: `rm ${flag} ${shellQuote7(abs)}` });
|
|
21854
22406
|
if (exitCode !== null && exitCode !== 0) {
|
|
21855
22407
|
throw new ChannelAValidationError(
|
|
21856
22408
|
`failed to delete ${path}: ${stderr || `exit ${exitCode}`}`
|
|
@@ -21875,7 +22427,7 @@ var SandboxChannelAService = class {
|
|
|
21875
22427
|
});
|
|
21876
22428
|
if (!req.overwrite) {
|
|
21877
22429
|
const { exitCode: exitCode2 } = await this.run({
|
|
21878
|
-
cmd: `test -e ${
|
|
22430
|
+
cmd: `test -e ${shellQuote7(newAbs)} || test -L ${shellQuote7(newAbs)}`
|
|
21879
22431
|
});
|
|
21880
22432
|
if (exitCode2 === 0) {
|
|
21881
22433
|
throw new ChannelAConflictError(`destination exists and overwrite is false: ${newPath}`);
|
|
@@ -21883,7 +22435,7 @@ var SandboxChannelAService = class {
|
|
|
21883
22435
|
}
|
|
21884
22436
|
if (req.createParents) {
|
|
21885
22437
|
const dir = dirnameAbs(newAbs);
|
|
21886
|
-
if (dir) await this.run({ cmd: `mkdir -p ${
|
|
22438
|
+
if (dir) await this.run({ cmd: `mkdir -p ${shellQuote7(dir)}` });
|
|
21887
22439
|
await this.assertConfinedMutationParent(newPath, {
|
|
21888
22440
|
allowMissingParents: false,
|
|
21889
22441
|
rejectFinalSymlink: true
|
|
@@ -21891,7 +22443,7 @@ var SandboxChannelAService = class {
|
|
|
21891
22443
|
}
|
|
21892
22444
|
const flag = req.overwrite ? "-f " : "";
|
|
21893
22445
|
const { exitCode, stderr } = await this.run({
|
|
21894
|
-
cmd: `mv ${flag}${
|
|
22446
|
+
cmd: `mv ${flag}${shellQuote7(abs)} ${shellQuote7(newAbs)}`
|
|
21895
22447
|
});
|
|
21896
22448
|
if (exitCode !== null && exitCode !== 0) {
|
|
21897
22449
|
throw new ChannelAValidationError(
|
|
@@ -21916,7 +22468,7 @@ var SandboxChannelAService = class {
|
|
|
21916
22468
|
rejectFinalSymlink: true
|
|
21917
22469
|
});
|
|
21918
22470
|
const flag = req.recursive ? "-p " : "";
|
|
21919
|
-
const { exitCode, stderr } = await this.run({ cmd: `mkdir ${flag}${
|
|
22471
|
+
const { exitCode, stderr } = await this.run({ cmd: `mkdir ${flag}${shellQuote7(abs)}` });
|
|
21920
22472
|
if (exitCode !== null && exitCode !== 0) {
|
|
21921
22473
|
throw new ChannelAValidationError(`failed to mkdir ${path}: ${stderr || `exit ${exitCode}`}`);
|
|
21922
22474
|
}
|
|
@@ -21931,44 +22483,60 @@ var SandboxChannelAService = class {
|
|
|
21931
22483
|
async measureConfinedCommandBytes(repo, command) {
|
|
21932
22484
|
const measured = await this.runInConfinedDirectory(repo, {
|
|
21933
22485
|
cmd: [
|
|
21934
|
-
|
|
21935
|
-
|
|
21936
|
-
"
|
|
21937
|
-
|
|
22486
|
+
PORTABLE_SHA256_FILE_FUNCTION,
|
|
22487
|
+
"tmp=$(mktemp) || exit 70",
|
|
22488
|
+
`trap 'rm -f "$tmp"' EXIT`,
|
|
22489
|
+
`/bin/bash --noprofile --norc -c ${shellQuote7(command)} >"$tmp" 2>/dev/null`,
|
|
22490
|
+
"producer_status=$?",
|
|
22491
|
+
`bytes=$(wc -c <"$tmp" | tr -d ' \\n')`,
|
|
22492
|
+
`sha256=$(opengeni_sha256_file "$tmp") || exit 71`,
|
|
22493
|
+
`printf '${GIT_MEASURE_FRAME}\\t%s\\t%s\\t%s' "$producer_status" "$bytes" "$sha256"`
|
|
21938
22494
|
].join("; "),
|
|
21939
22495
|
maxOutputTokens: 1024
|
|
21940
22496
|
});
|
|
21941
|
-
const match = measured.stdout.match(
|
|
21942
|
-
|
|
22497
|
+
const match = measured.stdout.match(
|
|
22498
|
+
new RegExp(`^${GIT_MEASURE_FRAME}\\t(\\d+)\\t(\\d+)\\t([0-9a-f]{64})$`)
|
|
22499
|
+
);
|
|
22500
|
+
if (!match || measured.exitCode !== null && measured.exitCode !== 0 || Number(match[1]) !== 0) {
|
|
21943
22501
|
throw new ChannelAUnavailableError(
|
|
21944
22502
|
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
21945
22503
|
);
|
|
21946
22504
|
}
|
|
21947
|
-
const size = Number(match[
|
|
22505
|
+
const size = Number(match[2]);
|
|
21948
22506
|
if (!Number.isSafeInteger(size) || size < 0) {
|
|
21949
22507
|
throw new ChannelAUnavailableError(
|
|
21950
22508
|
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
21951
22509
|
);
|
|
21952
22510
|
}
|
|
21953
|
-
return size;
|
|
22511
|
+
return { sizeBytes: size, sha256: match[3] };
|
|
21954
22512
|
}
|
|
21955
22513
|
/** Read an exact prefix of a command's output in chunks that remain below
|
|
21956
22514
|
* every supported execCommand retained-output ceiling. The producer is
|
|
21957
22515
|
* intentionally rerun per chunk; turn-end capture calls this only after the
|
|
21958
22516
|
* durable mutation authority has quiesced the workspace. */
|
|
21959
|
-
async readConfinedCommandPrefix(repo, command,
|
|
21960
|
-
if (
|
|
22517
|
+
async readConfinedCommandPrefix(repo, command, measurement, prefixByteLength = measurement.sizeBytes) {
|
|
22518
|
+
if (!Number.isSafeInteger(prefixByteLength) || prefixByteLength < 0 || prefixByteLength > measurement.sizeBytes) {
|
|
22519
|
+
throw new ChannelAUnavailableError(
|
|
22520
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22521
|
+
);
|
|
22522
|
+
}
|
|
22523
|
+
if (prefixByteLength === 0) return Buffer.alloc(0);
|
|
21961
22524
|
const chunks = [];
|
|
21962
|
-
for (let offset = 0; offset <
|
|
21963
|
-
const expected = Math.min(GIT_COMMAND_CHUNK_BYTES,
|
|
22525
|
+
for (let offset = 0; offset < prefixByteLength; offset += GIT_COMMAND_CHUNK_BYTES) {
|
|
22526
|
+
const expected = Math.min(GIT_COMMAND_CHUNK_BYTES, prefixByteLength - offset);
|
|
21964
22527
|
const chunk = await this.runInConfinedDirectory(repo, {
|
|
21965
22528
|
cmd: [
|
|
21966
|
-
|
|
21967
|
-
|
|
21968
|
-
`
|
|
21969
|
-
"
|
|
21970
|
-
|
|
21971
|
-
|
|
22529
|
+
PORTABLE_SHA256_FILE_FUNCTION,
|
|
22530
|
+
"tmp=$(mktemp) || exit 70",
|
|
22531
|
+
`trap 'rm -f "$tmp"' EXIT`,
|
|
22532
|
+
`/bin/bash --noprofile --norc -c ${shellQuote7(command)} >"$tmp" 2>/dev/null`,
|
|
22533
|
+
"producer_status=$?",
|
|
22534
|
+
`bytes=$(wc -c <"$tmp" | tr -d ' \\n')`,
|
|
22535
|
+
`sha256=$(opengeni_sha256_file "$tmp") || exit 71`,
|
|
22536
|
+
`printf '${GIT_CHUNK_FRAME}\\t%s\\t%s\\t%s\\t%s\\t%s\\n' "$producer_status" "$bytes" "$sha256" ${offset} ${expected}`,
|
|
22537
|
+
`if [ "$producer_status" -eq 0 ]; then tail -c +${offset + 1} "$tmp" | head -c ${expected} | base64 | tr -d '\\n'; fi`,
|
|
22538
|
+
`printf '\\n${GIT_CHUNK_FRAME_END}'`
|
|
22539
|
+
].join("; "),
|
|
21972
22540
|
maxOutputTokens: Math.ceil(GIT_COMMAND_CHUNK_BYTES * 4 / 3) + 1024
|
|
21973
22541
|
});
|
|
21974
22542
|
if (chunk.exitCode !== null && chunk.exitCode !== 0) {
|
|
@@ -21976,7 +22544,21 @@ var SandboxChannelAService = class {
|
|
|
21976
22544
|
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
21977
22545
|
);
|
|
21978
22546
|
}
|
|
21979
|
-
const
|
|
22547
|
+
const headerEnd = chunk.stdout.indexOf("\n");
|
|
22548
|
+
const trailer = `
|
|
22549
|
+
${GIT_CHUNK_FRAME_END}`;
|
|
22550
|
+
if (headerEnd < 0 || !chunk.stdout.endsWith(trailer)) {
|
|
22551
|
+
throw new ChannelAUnavailableError(
|
|
22552
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22553
|
+
);
|
|
22554
|
+
}
|
|
22555
|
+
const header = chunk.stdout.slice(0, headerEnd).split(" ");
|
|
22556
|
+
if (header.length !== 6 || header[0] !== GIT_CHUNK_FRAME || header[1] !== "0" || header[2] !== String(measurement.sizeBytes) || header[3] !== measurement.sha256 || header[4] !== String(offset) || header[5] !== String(expected)) {
|
|
22557
|
+
throw new ChannelAUnavailableError(
|
|
22558
|
+
"Workspace Git data changed during capture. Retry the operation."
|
|
22559
|
+
);
|
|
22560
|
+
}
|
|
22561
|
+
const encoded = chunk.stdout.slice(headerEnd + 1, -trailer.length);
|
|
21980
22562
|
const bytes = Buffer.from(encoded, "base64");
|
|
21981
22563
|
if (bytes.byteLength !== expected || bytes.toString("base64") !== encoded) {
|
|
21982
22564
|
throw new ChannelAUnavailableError(
|
|
@@ -21985,35 +22567,61 @@ var SandboxChannelAService = class {
|
|
|
21985
22567
|
}
|
|
21986
22568
|
chunks.push(bytes);
|
|
21987
22569
|
}
|
|
21988
|
-
return Buffer.concat(chunks,
|
|
22570
|
+
return Buffer.concat(chunks, prefixByteLength);
|
|
21989
22571
|
}
|
|
21990
22572
|
async readConfinedCommandBytes(repo, command, maxBytes) {
|
|
21991
|
-
const
|
|
21992
|
-
if (sizeBytes > maxBytes) {
|
|
21993
|
-
return { bytes: Buffer.alloc(0), sizeBytes, truncated: true };
|
|
22573
|
+
const measurement = await this.measureConfinedCommandBytes(repo, command);
|
|
22574
|
+
if (measurement.sizeBytes > maxBytes) {
|
|
22575
|
+
return { bytes: Buffer.alloc(0), sizeBytes: measurement.sizeBytes, truncated: true };
|
|
21994
22576
|
}
|
|
21995
22577
|
return {
|
|
21996
|
-
bytes: await this.readConfinedCommandPrefix(repo, command,
|
|
21997
|
-
sizeBytes,
|
|
22578
|
+
bytes: await this.readConfinedCommandPrefix(repo, command, measurement),
|
|
22579
|
+
sizeBytes: measurement.sizeBytes,
|
|
21998
22580
|
truncated: false
|
|
21999
22581
|
};
|
|
22000
22582
|
}
|
|
22583
|
+
/** Bind an untracked regular-file descriptor to its repository root and its
|
|
22584
|
+
* lstat identity before producing bytes. The final producer reads fd 3 rather
|
|
22585
|
+
* than reopening the path, so a check→read symlink swap cannot disclose a
|
|
22586
|
+
* target outside the repository (or substitute another in-repository inode). */
|
|
22587
|
+
confinedUntrackedRegularFileCommand(target, body) {
|
|
22588
|
+
const fileArg = target.startsWith("./") ? target : `./${target}`;
|
|
22589
|
+
return [
|
|
22590
|
+
PORTABLE_DESCRIPTOR_FUNCTIONS,
|
|
22591
|
+
`file=${shellQuote7(fileArg)}`,
|
|
22592
|
+
'exec 3<"$file" || exit 66',
|
|
22593
|
+
'exec 4<"$file" || exit 66',
|
|
22594
|
+
"root=$(pwd -P) || exit 66",
|
|
22595
|
+
"opengeni_set_fd_path 3 || exit 66",
|
|
22596
|
+
'opened3="$opengeni_fd_path"',
|
|
22597
|
+
"opengeni_set_fd_path 4 || exit 66",
|
|
22598
|
+
'opened4="$opengeni_fd_path"',
|
|
22599
|
+
'case "$opened3" in "$root"|"$root"/*) ;; *) exit 67 ;; esac',
|
|
22600
|
+
'case "$opened4" in "$root"|"$root"/*) ;; *) exit 67 ;; esac',
|
|
22601
|
+
'test ! -L "$file" && test -f "$file" || exit 66',
|
|
22602
|
+
"opened3_identity=$(opengeni_fd_identity 3) || exit 66",
|
|
22603
|
+
"opened4_identity=$(opengeni_fd_identity 4) || exit 66",
|
|
22604
|
+
'path_identity=$(opengeni_path_identity "$file") || exit 66',
|
|
22605
|
+
'test "$opened3_identity" = "$opened4_identity" || exit 66',
|
|
22606
|
+
'test "$opened3_identity" = "$path_identity" || exit 66',
|
|
22607
|
+
body
|
|
22608
|
+
].join("; ");
|
|
22609
|
+
}
|
|
22001
22610
|
/** Read a regular untracked file without routing its body through one large
|
|
22002
22611
|
* execCommand response. Native provider reads are binary-safe; providers
|
|
22003
22612
|
* without that surface use the same bounded chunk protocol as Git patches. */
|
|
22004
|
-
async readUntrackedRegularFile(repo, target,
|
|
22005
|
-
if (byteLength2 === 0) return Buffer.alloc(0);
|
|
22613
|
+
async readUntrackedRegularFile(repo, target, prefixByteLength, sizeBytes) {
|
|
22006
22614
|
const path = repo ? `${repo}/${target}` : target;
|
|
22007
22615
|
assertSafeRelPath(path);
|
|
22008
22616
|
if (this.session.readFile) {
|
|
22009
22617
|
try {
|
|
22010
22618
|
const raw = await this.session.readFile({
|
|
22011
22619
|
path: this.joinRoot(path),
|
|
22012
|
-
maxBytes:
|
|
22620
|
+
maxBytes: prefixByteLength,
|
|
22013
22621
|
...this.runAs ? { runAs: this.runAs } : {}
|
|
22014
22622
|
});
|
|
22015
22623
|
const bytes = typeof raw === "string" ? Buffer.from(raw, "utf8") : Buffer.from(raw);
|
|
22016
|
-
if (bytes.byteLength !==
|
|
22624
|
+
if (bytes.byteLength !== prefixByteLength) {
|
|
22017
22625
|
throw new ChannelAUnavailableError(
|
|
22018
22626
|
"Workspace Git data changed during capture. Retry the operation."
|
|
22019
22627
|
);
|
|
@@ -22034,12 +22642,14 @@ var SandboxChannelAService = class {
|
|
|
22034
22642
|
}
|
|
22035
22643
|
}
|
|
22036
22644
|
}
|
|
22037
|
-
const
|
|
22038
|
-
|
|
22039
|
-
|
|
22040
|
-
|
|
22041
|
-
|
|
22042
|
-
|
|
22645
|
+
const command = this.confinedUntrackedRegularFileCommand(target, "cat <&3");
|
|
22646
|
+
const measurement = await this.measureConfinedCommandBytes(repo, command);
|
|
22647
|
+
if (measurement.sizeBytes !== sizeBytes) {
|
|
22648
|
+
throw new ChannelAUnavailableError(
|
|
22649
|
+
"Workspace Git data changed during capture. Retry the operation."
|
|
22650
|
+
);
|
|
22651
|
+
}
|
|
22652
|
+
return await this.readConfinedCommandPrefix(repo, command, measurement, prefixByteLength);
|
|
22043
22653
|
}
|
|
22044
22654
|
async gitStatus(req) {
|
|
22045
22655
|
const repo = assertSafeRelPathOrRoot(req.path);
|
|
@@ -22068,24 +22678,24 @@ var SandboxChannelAService = class {
|
|
|
22068
22678
|
"Workspace Git metadata exceeded the safe capture limit. Retry with a narrower path."
|
|
22069
22679
|
);
|
|
22070
22680
|
}
|
|
22071
|
-
return { ...parsePorcelainV2(status.bytes
|
|
22681
|
+
return { ...parsePorcelainV2(decodeGitMetadataUtf8(status.bytes)), revision: this.revision };
|
|
22072
22682
|
}
|
|
22073
22683
|
async gitDiff(req) {
|
|
22074
22684
|
const repo = assertSafeRelPathOrRoot(req.path);
|
|
22075
22685
|
const ctx = req.contextLines;
|
|
22076
22686
|
let range = "";
|
|
22077
|
-
if (req.fromRef && req.toRef) range = `${
|
|
22687
|
+
if (req.fromRef && req.toRef) range = `${shellQuote7(req.fromRef)} ${shellQuote7(req.toRef)}`;
|
|
22078
22688
|
else if (req.fromRef) {
|
|
22079
22689
|
if (req.fromRef === "HEAD") {
|
|
22080
22690
|
const head = await this.runInConfinedDirectory(repo, {
|
|
22081
22691
|
cmd: "if git rev-parse --verify --quiet HEAD >/dev/null; then printf 'present'; else printf 'unborn'; fi"
|
|
22082
22692
|
});
|
|
22083
|
-
range = head.stdout.trim() === "present" ?
|
|
22693
|
+
range = head.stdout.trim() === "present" ? shellQuote7(req.fromRef) : "--cached";
|
|
22084
22694
|
} else {
|
|
22085
|
-
range =
|
|
22695
|
+
range = shellQuote7(req.fromRef);
|
|
22086
22696
|
}
|
|
22087
22697
|
} else if (req.staged) range = "--cached";
|
|
22088
|
-
const pathspec = req.pathspec.length ? ` -- ${req.pathspec.map(
|
|
22698
|
+
const pathspec = req.pathspec.length ? ` -- ${req.pathspec.map(shellQuote7).join(" ")}` : "";
|
|
22089
22699
|
const numstat = await this.readConfinedCommandBytes(
|
|
22090
22700
|
repo,
|
|
22091
22701
|
`git -c core.quotePath=false diff --no-color -z --numstat ${range}${pathspec}`.trim(),
|
|
@@ -22096,7 +22706,7 @@ var SandboxChannelAService = class {
|
|
|
22096
22706
|
"Workspace Git metadata exceeded the safe capture limit. Retry with a narrower path."
|
|
22097
22707
|
);
|
|
22098
22708
|
}
|
|
22099
|
-
const stats = parseNumstatZ(numstat.bytes
|
|
22709
|
+
const stats = parseNumstatZ(decodeGitMetadataUtf8(numstat.bytes));
|
|
22100
22710
|
const files = [];
|
|
22101
22711
|
for (const stat4 of stats) {
|
|
22102
22712
|
const target = stat4.newPath;
|
|
@@ -22117,7 +22727,7 @@ var SandboxChannelAService = class {
|
|
|
22117
22727
|
}
|
|
22118
22728
|
const patch = await this.readConfinedCommandBytes(
|
|
22119
22729
|
repo,
|
|
22120
|
-
`git -c core.quotePath=false diff --no-color -U${ctx} ${range} -- ${
|
|
22730
|
+
`git -c core.quotePath=false diff --no-color -U${ctx} ${range} -- ${shellQuote7(target)}`.trim(),
|
|
22121
22731
|
req.maxBytesPerFile
|
|
22122
22732
|
);
|
|
22123
22733
|
const parsed = patch.truncated ? { hunks: [], status: "modified" } : parseUnifiedPatch(patch.bytes.toString("utf8"));
|
|
@@ -22144,48 +22754,75 @@ var SandboxChannelAService = class {
|
|
|
22144
22754
|
"Workspace Git metadata exceeded the safe capture limit. Retry with a narrower path."
|
|
22145
22755
|
);
|
|
22146
22756
|
}
|
|
22147
|
-
for (const target of untracked.bytes
|
|
22757
|
+
for (const target of decodeGitMetadataUtf8(untracked.bytes).split(NUL).filter(Boolean)) {
|
|
22148
22758
|
const fileArg = target.startsWith("./") ? target : `./${target}`;
|
|
22149
|
-
const
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22153
|
-
|
|
22154
|
-
|
|
22155
|
-
'if [ "$size" -gt 0 ]; then last_byte=$(tail -c 1 "$file" | od -An -tu1 | tr -d " \\n"); if [ "$last_byte" != "10" ]; then line_count=$((line_count + 1)); fi; fi',
|
|
22156
|
-
'printf "F\\t%s\\t%s" "$size" "$line_count"'
|
|
22157
|
-
].join("; ")
|
|
22158
|
-
});
|
|
22159
|
-
if (read.exitCode !== null && read.exitCode !== 0) {
|
|
22759
|
+
const kind = await this.readConfinedCommandBytes(
|
|
22760
|
+
repo,
|
|
22761
|
+
`file=${shellQuote7(fileArg)}; if [ -L "$file" ]; then printf L; elif [ -f "$file" ]; then printf F; else exit 66; fi`,
|
|
22762
|
+
1
|
|
22763
|
+
);
|
|
22764
|
+
if (kind.truncated || kind.bytes[0] !== 76 && kind.bytes[0] !== 70) {
|
|
22160
22765
|
throw new ChannelAUnavailableError(
|
|
22161
22766
|
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22162
22767
|
);
|
|
22163
22768
|
}
|
|
22164
|
-
const [kind, first, second] = read.stdout.split(" ");
|
|
22165
22769
|
let sampled = Buffer.alloc(0);
|
|
22166
22770
|
let sizeBytes;
|
|
22167
22771
|
let lineCount;
|
|
22168
|
-
if (kind ===
|
|
22169
|
-
const
|
|
22170
|
-
|
|
22171
|
-
|
|
22772
|
+
if (kind.bytes[0] === 76) {
|
|
22773
|
+
const link = await this.readConfinedCommandBytes(
|
|
22774
|
+
repo,
|
|
22775
|
+
`file=${shellQuote7(fileArg)}; test -L "$file" || exit 66; readlink -n "$file" || exit 66; printf '\\0'`,
|
|
22776
|
+
GIT_METADATA_MAX_BYTES
|
|
22777
|
+
);
|
|
22778
|
+
if (link.truncated) {
|
|
22779
|
+
throw new ChannelAUnavailableError(
|
|
22780
|
+
"Workspace Git metadata exceeded the safe capture limit. Retry with a narrower path."
|
|
22781
|
+
);
|
|
22782
|
+
}
|
|
22783
|
+
sampled = link.bytes;
|
|
22784
|
+
if (sampled.at(-1) !== 0) {
|
|
22785
|
+
throw new ChannelAUnavailableError(
|
|
22786
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22787
|
+
);
|
|
22788
|
+
}
|
|
22172
22789
|
sampled = sampled.subarray(0, -1);
|
|
22173
22790
|
sizeBytes = sampled.length;
|
|
22174
22791
|
lineCount = addedLines(sampled).length;
|
|
22175
22792
|
} else {
|
|
22176
|
-
|
|
22177
|
-
|
|
22178
|
-
|
|
22179
|
-
|
|
22180
|
-
|
|
22793
|
+
const metadata = await this.readConfinedCommandBytes(
|
|
22794
|
+
repo,
|
|
22795
|
+
this.confinedUntrackedRegularFileCommand(
|
|
22796
|
+
target,
|
|
22797
|
+
[
|
|
22798
|
+
"size=$(opengeni_fd_size 3) || exit 66",
|
|
22799
|
+
"line_count=$(wc -l <&3) || exit 66",
|
|
22800
|
+
'if [ "$size" -gt 0 ]; then last_byte=$(tail -c 1 <&4 | od -An -tu1 | tr -d " \\n") || exit 66; if [ "$last_byte" != "10" ]; then line_count=$((line_count + 1)); fi; fi',
|
|
22801
|
+
'printf "%s\\t%s" "$size" "$line_count"'
|
|
22802
|
+
].join("; ")
|
|
22803
|
+
),
|
|
22804
|
+
128
|
|
22805
|
+
);
|
|
22806
|
+
if (metadata.truncated) {
|
|
22807
|
+
throw new ChannelAUnavailableError(
|
|
22808
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22809
|
+
);
|
|
22810
|
+
}
|
|
22811
|
+
const frame = metadata.bytes.toString("ascii").match(/^(0|[1-9]\d*)\t(0|[1-9]\d*)$/);
|
|
22812
|
+
const parsedSize = safeInt(frame?.[1]);
|
|
22813
|
+
const parsedLineCount = safeInt(frame?.[2]);
|
|
22814
|
+
if (parsedSize === null || parsedLineCount === null) {
|
|
22815
|
+
throw new ChannelAUnavailableError(
|
|
22816
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22817
|
+
);
|
|
22181
22818
|
}
|
|
22182
22819
|
sizeBytes = parsedSize;
|
|
22183
22820
|
lineCount = parsedLineCount;
|
|
22184
22821
|
const truncated2 = sizeBytes > req.maxBytesPerFile;
|
|
22185
22822
|
const sampleSize = Math.min(sizeBytes, 8192);
|
|
22186
|
-
sampled = await this.readUntrackedRegularFile(repo, target, sampleSize);
|
|
22823
|
+
sampled = await this.readUntrackedRegularFile(repo, target, sampleSize, sizeBytes);
|
|
22187
22824
|
if (!sniffBinary(sampled) && !truncated2 && sampleSize < sizeBytes) {
|
|
22188
|
-
sampled = await this.readUntrackedRegularFile(repo, target, sizeBytes);
|
|
22825
|
+
sampled = await this.readUntrackedRegularFile(repo, target, sizeBytes, sizeBytes);
|
|
22189
22826
|
}
|
|
22190
22827
|
}
|
|
22191
22828
|
const truncated = sizeBytes > req.maxBytesPerFile || sampled.length > req.maxBytesPerFile;
|
|
@@ -22219,9 +22856,9 @@ var SandboxChannelAService = class {
|
|
|
22219
22856
|
async gitLog(req) {
|
|
22220
22857
|
const repo = assertSafeRelPathOrRoot(req.path);
|
|
22221
22858
|
const fmt = `%H${US}%h${US}%P${US}%an${US}%ae${US}%at${US}%cn${US}%ce${US}%ct${US}%s${US}%b${RS}`;
|
|
22222
|
-
const pathspec = req.pathspec.length ? ` -- ${req.pathspec.map(
|
|
22859
|
+
const pathspec = req.pathspec.length ? ` -- ${req.pathspec.map(shellQuote7).join(" ")}` : "";
|
|
22223
22860
|
const { stdout, exitCode } = await this.runInConfinedDirectory(repo, {
|
|
22224
|
-
cmd: `git log --format=${
|
|
22861
|
+
cmd: `git log --format=${shellQuote7(fmt)} -n${req.maxCount + 1} --skip=${req.skip} ${shellQuote7(req.ref)}${pathspec}`
|
|
22225
22862
|
});
|
|
22226
22863
|
if (exitCode !== null && exitCode !== 0) {
|
|
22227
22864
|
return { commits: [], hasMore: false };
|
|
@@ -22248,7 +22885,7 @@ var SandboxChannelAService = class {
|
|
|
22248
22885
|
const repo = assertSafeRelPathOrRoot(req.path);
|
|
22249
22886
|
if (req.filePath) {
|
|
22250
22887
|
const { stdout, exitCode } = await this.runInConfinedDirectory(repo, {
|
|
22251
|
-
cmd: `git cat-file blob ${
|
|
22888
|
+
cmd: `git cat-file blob ${shellQuote7(`${req.ref}:${req.filePath}`)} 2>/dev/null | base64`
|
|
22252
22889
|
});
|
|
22253
22890
|
if (exitCode !== null && exitCode !== 0 && stdout.trim() === "") {
|
|
22254
22891
|
throw new ChannelANotFoundError(`blob not found: ${req.ref}:${req.filePath}`);
|
|
@@ -22521,19 +23158,28 @@ var SandboxChannelAService = class {
|
|
|
22521
23158
|
const safe = assertSafeRelPathOrRoot(rel);
|
|
22522
23159
|
const root = this.workspaceRoot || ".";
|
|
22523
23160
|
const abs = this.joinRoot(safe);
|
|
22524
|
-
const rejectLink = safe ? `test ! -L ${
|
|
22525
|
-
const script = [
|
|
22526
|
-
`root=$(realpath -e -- ${shellQuote6(root)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
22527
|
-
rejectLink,
|
|
22528
|
-
`target=$(realpath -e -- ${shellQuote6(abs)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
22529
|
-
`case "$target" in "$root"|"$root"/*) ;; *) printf '__OPENGENI_FS_ESCAPE__'; exit 67 ;; esac`,
|
|
22530
|
-
`test -d "$target" || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
22531
|
-
`cd -P -- "$target"`,
|
|
22532
|
-
`printf '__OPENGENI_FS_CONFINED_OK__\\n'`,
|
|
22533
|
-
args.cmd
|
|
22534
|
-
].join("; ");
|
|
22535
|
-
const successPrefix = "__OPENGENI_FS_CONFINED_OK__\n";
|
|
23161
|
+
const rejectLink = safe ? `test ! -L ${shellQuote7(abs)} || { printf '__OPENGENI_FS_SYMLINK__'; exit 68; }` : ":";
|
|
22536
23162
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
23163
|
+
const frameId = crypto.randomUUID().replaceAll("-", "");
|
|
23164
|
+
const successPrefix = `__OPENGENI_FS_CONFINED_${frameId}_OK__
|
|
23165
|
+
`;
|
|
23166
|
+
const successSuffixPrefix = `__OPENGENI_FS_CONFINED_${frameId}_END__:`;
|
|
23167
|
+
const successSuffixTerminator = "__";
|
|
23168
|
+
const script = [
|
|
23169
|
+
`root=$(realpath -e -- ${shellQuote7(root)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
23170
|
+
rejectLink,
|
|
23171
|
+
`target=$(realpath -e -- ${shellQuote7(abs)}) || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
23172
|
+
`case "$target" in "$root"|"$root"/*) ;; *) printf '__OPENGENI_FS_ESCAPE__'; exit 67 ;; esac`,
|
|
23173
|
+
`test -d "$target" || { printf '__OPENGENI_FS_NOT_FOUND__'; exit 66; }`,
|
|
23174
|
+
`cd -P -- "$target"`,
|
|
23175
|
+
`printf ${shellQuote7(successPrefix)}`,
|
|
23176
|
+
// Keep an operation-level `exit` inside the subshell so the trusted end
|
|
23177
|
+
// frame is emitted for every completed command.
|
|
23178
|
+
`( ${args.cmd} )`,
|
|
23179
|
+
`operation_status=$?`,
|
|
23180
|
+
`printf ${shellQuote7(`${successSuffixPrefix}%s${successSuffixTerminator}`)} "$operation_status"`,
|
|
23181
|
+
`exit "$operation_status"`
|
|
23182
|
+
].join("; ");
|
|
22537
23183
|
let result;
|
|
22538
23184
|
try {
|
|
22539
23185
|
result = await this.run({
|
|
@@ -22555,7 +23201,24 @@ var SandboxChannelAService = class {
|
|
|
22555
23201
|
}
|
|
22556
23202
|
const successIndex = result.stdout.indexOf(successPrefix);
|
|
22557
23203
|
if (successIndex >= 0) {
|
|
22558
|
-
|
|
23204
|
+
const payloadStart = successIndex + successPrefix.length;
|
|
23205
|
+
const suffixIndex = result.stdout.lastIndexOf(successSuffixPrefix);
|
|
23206
|
+
if (suffixIndex >= payloadStart) {
|
|
23207
|
+
const suffixEnd = result.stdout.indexOf(
|
|
23208
|
+
successSuffixTerminator,
|
|
23209
|
+
suffixIndex + successSuffixPrefix.length
|
|
23210
|
+
);
|
|
23211
|
+
const statusText = suffixEnd < 0 ? null : result.stdout.slice(suffixIndex + successSuffixPrefix.length, suffixEnd);
|
|
23212
|
+
if (statusText && /^(?:0|[1-9][0-9]{0,2})$/.test(statusText)) {
|
|
23213
|
+
const operationStatus = Number(statusText);
|
|
23214
|
+
if (operationStatus > 255) continue;
|
|
23215
|
+
return {
|
|
23216
|
+
...result,
|
|
23217
|
+
stdout: result.stdout.slice(payloadStart, suffixIndex),
|
|
23218
|
+
exitCode: operationStatus
|
|
23219
|
+
};
|
|
23220
|
+
}
|
|
23221
|
+
}
|
|
22559
23222
|
}
|
|
22560
23223
|
if (result.stdout.includes("__OPENGENI_FS_ESCAPE__") || result.exitCode === 67) {
|
|
22561
23224
|
throw new ChannelAValidationError(`path resolves outside workspace: ${safe || "."}`);
|
|
@@ -22640,6 +23303,15 @@ function sniffBinary(bytes) {
|
|
|
22640
23303
|
for (let i = 0; i < n; i++) if (bytes[i] === 0) return true;
|
|
22641
23304
|
return false;
|
|
22642
23305
|
}
|
|
23306
|
+
function decodeGitMetadataUtf8(bytes) {
|
|
23307
|
+
const decoded = bytes.toString("utf8");
|
|
23308
|
+
if (!Buffer.from(decoded, "utf8").equals(bytes)) {
|
|
23309
|
+
throw new ChannelAUnavailableError(
|
|
23310
|
+
"Workspace Git paths are not valid UTF-8 and cannot be captured authoritatively."
|
|
23311
|
+
);
|
|
23312
|
+
}
|
|
23313
|
+
return decoded;
|
|
23314
|
+
}
|
|
22643
23315
|
function addedLines(bytes) {
|
|
22644
23316
|
if (bytes.length === 0) return [];
|
|
22645
23317
|
const lines = bytes.toString("utf8").split("\n");
|
|
@@ -22668,11 +23340,11 @@ function assertSafeRelPath(p) {
|
|
|
22668
23340
|
if (norm === "") throw new ChannelAValidationError("path is required");
|
|
22669
23341
|
return norm;
|
|
22670
23342
|
}
|
|
22671
|
-
function
|
|
23343
|
+
function shellQuote7(s) {
|
|
22672
23344
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
22673
23345
|
}
|
|
22674
23346
|
function internalBashCommand(script) {
|
|
22675
|
-
return `env -u BASH_ENV bash --noprofile --norc -c ${
|
|
23347
|
+
return `env -u BASH_ENV bash --noprofile --norc -c ${shellQuote7(script)}`;
|
|
22676
23348
|
}
|
|
22677
23349
|
function assertSafePruneDirectoryName(name) {
|
|
22678
23350
|
if (name.length > 255 || !/^[A-Za-z0-9._@+-]+$/.test(name) || name === "." || name === "..") {
|
|
@@ -23377,7 +24049,9 @@ function withDockerNetwork(client, network) {
|
|
|
23377
24049
|
...client.resume ? {
|
|
23378
24050
|
resume: async (state) => await wrapSession(await client.resume(state))
|
|
23379
24051
|
} : {},
|
|
23380
|
-
...client.delete ? {
|
|
24052
|
+
...client.delete ? {
|
|
24053
|
+
delete: async (state) => await client.delete(state)
|
|
24054
|
+
} : {},
|
|
23381
24055
|
...client.serializeSessionState ? {
|
|
23382
24056
|
serializeSessionState: async (state, options) => await client.serializeSessionState(state, options)
|
|
23383
24057
|
} : {},
|
|
@@ -23447,55 +24121,9 @@ function readWorkspaceArchiveFromEnvelopeSessionState(sessionState) {
|
|
|
23447
24121
|
return void 0;
|
|
23448
24122
|
}
|
|
23449
24123
|
}
|
|
23450
|
-
var MODAL_SNAPSHOT_REF_PREFIXES = [
|
|
23451
|
-
"MODAL_SANDBOX_FS_SNAPSHOT_V1\n",
|
|
23452
|
-
"MODAL_SANDBOX_DIR_SNAPSHOT_V1\n"
|
|
23453
|
-
];
|
|
23454
24124
|
function decodeModalSnapshotId(archive) {
|
|
23455
|
-
|
|
23456
|
-
|
|
23457
|
-
text = new TextDecoder().decode(archive);
|
|
23458
|
-
} catch {
|
|
23459
|
-
return void 0;
|
|
23460
|
-
}
|
|
23461
|
-
for (const prefix of MODAL_SNAPSHOT_REF_PREFIXES) {
|
|
23462
|
-
if (!text.startsWith(prefix)) {
|
|
23463
|
-
continue;
|
|
23464
|
-
}
|
|
23465
|
-
try {
|
|
23466
|
-
const payload = JSON.parse(text.slice(prefix.length));
|
|
23467
|
-
return typeof payload.snapshot_id === "string" && payload.snapshot_id.length > 0 ? payload.snapshot_id : void 0;
|
|
23468
|
-
} catch {
|
|
23469
|
-
return void 0;
|
|
23470
|
-
}
|
|
23471
|
-
}
|
|
23472
|
-
return void 0;
|
|
23473
|
-
}
|
|
23474
|
-
async function deletePriorPersistedSnapshot(session, priorArchiveBase64) {
|
|
23475
|
-
if (!priorArchiveBase64) {
|
|
23476
|
-
return void 0;
|
|
23477
|
-
}
|
|
23478
|
-
let bytes;
|
|
23479
|
-
try {
|
|
23480
|
-
bytes = Uint8Array.from(Buffer.from(priorArchiveBase64, "base64"));
|
|
23481
|
-
} catch {
|
|
23482
|
-
return void 0;
|
|
23483
|
-
}
|
|
23484
|
-
const snapshotId = decodeModalSnapshotId(bytes);
|
|
23485
|
-
if (!snapshotId) {
|
|
23486
|
-
return void 0;
|
|
23487
|
-
}
|
|
23488
|
-
const modal = session.modal;
|
|
23489
|
-
const del = modal?.images?.delete;
|
|
23490
|
-
if (typeof del !== "function") {
|
|
23491
|
-
return void 0;
|
|
23492
|
-
}
|
|
23493
|
-
try {
|
|
23494
|
-
await del.call(modal.images, snapshotId);
|
|
23495
|
-
return snapshotId;
|
|
23496
|
-
} catch {
|
|
23497
|
-
return void 0;
|
|
23498
|
-
}
|
|
24125
|
+
const ref = decodeNativeSnapshotRef3(archive);
|
|
24126
|
+
return ref?.provider === "modal_snapshot_filesystem" || ref?.provider === "modal_snapshot_directory" ? ref.snapshotId : void 0;
|
|
23499
24127
|
}
|
|
23500
24128
|
async function deserializeSandboxSessionStateEnvelope(client, envelope) {
|
|
23501
24129
|
if (!envelope || typeof envelope !== "object") {
|
|
@@ -23609,7 +24237,11 @@ async function establishSandboxSessionFromEnvelope(settings, envelope, opts) {
|
|
|
23609
24237
|
const envelopeBackend = typeof envelope?.backendId === "string" ? envelope.backendId : void 0;
|
|
23610
24238
|
const backend = opts.backendOverride ?? envelopeBackend ?? settings.sandboxBackend;
|
|
23611
24239
|
const environment = opts.environment ?? collectSandboxEnvironment(settings);
|
|
23612
|
-
const client =
|
|
24240
|
+
const client = (opts.clientFactory ?? createSandboxClientForBackend)(
|
|
24241
|
+
backend,
|
|
24242
|
+
settings,
|
|
24243
|
+
environment
|
|
24244
|
+
);
|
|
23613
24245
|
if (!client) {
|
|
23614
24246
|
throw new SandboxConfigError(
|
|
23615
24247
|
backend,
|
|
@@ -23702,20 +24334,22 @@ async function establishSandboxSessionFromEnvelope(settings, envelope, opts) {
|
|
|
23702
24334
|
throw error;
|
|
23703
24335
|
}
|
|
23704
24336
|
}
|
|
23705
|
-
|
|
23706
|
-
|
|
23707
|
-
|
|
23708
|
-
|
|
23709
|
-
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
|
|
23714
|
-
|
|
24337
|
+
if (workspaceArchive.kind === "tar") {
|
|
24338
|
+
try {
|
|
24339
|
+
await verifyRestoredWorkspace(restored, workspaceArchive.descriptor);
|
|
24340
|
+
} catch (error) {
|
|
24341
|
+
await terminateCreatedSandbox(client, restored, restored.state);
|
|
24342
|
+
if (error instanceof WorkspaceArchiveIntegrityError) throw error;
|
|
24343
|
+
throw new WorkspaceArchiveIntegrityError(
|
|
24344
|
+
"workspace_fingerprint_unavailable",
|
|
24345
|
+
`failed to verify selected workspace archive revision ${workspaceArchive.descriptor.revision}`,
|
|
24346
|
+
{ retryable: true }
|
|
24347
|
+
);
|
|
24348
|
+
}
|
|
23715
24349
|
}
|
|
23716
24350
|
hydrationApplied = true;
|
|
23717
24351
|
console.info(
|
|
23718
|
-
`[sandbox] cold-restore verified
|
|
24352
|
+
`[sandbox] cold-restore applied ${workspaceArchive.kind === "provider_snapshot" ? "native snapshot receipt" : "verified tar archive"} revision ${workspaceArchive.descriptor.revision}`
|
|
23719
24353
|
);
|
|
23720
24354
|
}
|
|
23721
24355
|
restoredState = restored.state;
|
|
@@ -23898,6 +24532,12 @@ export {
|
|
|
23898
24532
|
modalSandboxAttributionEnvironment,
|
|
23899
24533
|
modalSandboxAttributionTags,
|
|
23900
24534
|
ensureModalRegistryImage,
|
|
24535
|
+
resolveModalCheckpointProviderBindingForSession,
|
|
24536
|
+
modalSessionMatchesCheckpointProviderBinding,
|
|
24537
|
+
resolveModalCheckpointProviderBinding,
|
|
24538
|
+
resolveModalCheckpointProviderBindingForLiveSandbox,
|
|
24539
|
+
inspectModalSandboxLifecycle,
|
|
24540
|
+
deleteModalCheckpointSnapshot,
|
|
23901
24541
|
tagModalSandbox,
|
|
23902
24542
|
terminateModalSandboxById,
|
|
23903
24543
|
sweepModalOrphanSandboxes,
|
|
@@ -23956,13 +24596,16 @@ export {
|
|
|
23956
24596
|
isProviderSandboxNotFoundError2 as isProviderSandboxNotFoundError,
|
|
23957
24597
|
isProviderSandboxGoneDuringRoutedOperation,
|
|
23958
24598
|
isProviderSandboxTransientError,
|
|
23959
|
-
WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION,
|
|
23960
24599
|
WorkspaceArchiveIntegrityError,
|
|
23961
|
-
|
|
24600
|
+
describeNativeSnapshotArchive,
|
|
24601
|
+
describeLegacyNativeSnapshotArchive,
|
|
23962
24602
|
readVerifiedWorkspaceArchive,
|
|
23963
24603
|
fingerprintSandboxWorkspace,
|
|
23964
24604
|
captureVerifiedWorkspaceArchive,
|
|
23965
24605
|
verifyRestoredWorkspace,
|
|
24606
|
+
WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION2 as WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION,
|
|
24607
|
+
decodeNativeSnapshotRef3 as decodeNativeSnapshotRef,
|
|
24608
|
+
parseWorkspaceArchiveDescriptor2 as parseWorkspaceArchiveDescriptor,
|
|
23966
24609
|
selectBackend,
|
|
23967
24610
|
backendSupportsOs,
|
|
23968
24611
|
desktopCapableBackend,
|
|
@@ -24052,7 +24695,6 @@ export {
|
|
|
24052
24695
|
restoredSandboxSessionStateFromEntry,
|
|
24053
24696
|
readWorkspaceArchiveFromEnvelopeSessionState,
|
|
24054
24697
|
decodeModalSnapshotId,
|
|
24055
|
-
deletePriorPersistedSnapshot,
|
|
24056
24698
|
deserializeSandboxSessionStateEnvelope,
|
|
24057
24699
|
SandboxExecReadinessError,
|
|
24058
24700
|
verifySandboxExecReadiness,
|
|
@@ -24065,4 +24707,4 @@ export {
|
|
|
24065
24707
|
collectSandboxEnvironment2 as collectSandboxEnvironment,
|
|
24066
24708
|
parseExposedPorts2 as parseExposedPorts
|
|
24067
24709
|
};
|
|
24068
|
-
//# sourceMappingURL=chunk-
|
|
24710
|
+
//# sourceMappingURL=chunk-GNEGANUF.js.map
|