@opengeni/runtime 0.14.1 → 0.14.3
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-HHWIZHQM.js → chunk-GQIFSLAC.js} +51 -4
- package/dist/chunk-GQIFSLAC.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/sandbox/index.js +1 -1
- package/package.json +3 -3
- package/src/sandbox/providers/docker.ts +13 -1
- package/src/sandbox/routing/routing-session.ts +64 -1
- package/dist/chunk-HHWIZHQM.js.map +0 -1
package/dist/index.js
CHANGED
package/dist/sandbox/index.js
CHANGED
|
@@ -170,7 +170,7 @@ import {
|
|
|
170
170
|
withToolspaceTokenClient,
|
|
171
171
|
withToolspaceTokenEnvironment,
|
|
172
172
|
withToolspaceTokenSession
|
|
173
|
-
} from "../chunk-
|
|
173
|
+
} from "../chunk-GQIFSLAC.js";
|
|
174
174
|
import "../chunk-4YJ5Z52Z.js";
|
|
175
175
|
import "../chunk-K4V4QYCL.js";
|
|
176
176
|
import "../chunk-PZ5AY32C.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/runtime",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"@openai/agents-extensions": "0.13.3",
|
|
51
51
|
"@opengeni/agent-proto": "^0.3.0",
|
|
52
52
|
"@opengeni/codex": "^0.2.7",
|
|
53
|
-
"@opengeni/config": "^0.7.
|
|
54
|
-
"@opengeni/contracts": "^0.
|
|
53
|
+
"@opengeni/config": "^0.7.13",
|
|
54
|
+
"@opengeni/contracts": "^0.23.0",
|
|
55
55
|
"@opengeni/network": "^0.1.1",
|
|
56
56
|
"debug": "4.4.3",
|
|
57
57
|
"modal": "0.7.6",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { DockerSandboxClient } from "@openai/agents/sandbox/local";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
2
3
|
import { CAPABILITY_DESCRIPTORS } from "../capabilities";
|
|
4
|
+
import { SandboxConfigError } from "../errors";
|
|
3
5
|
import type { ProviderRegistration } from "./types";
|
|
4
6
|
|
|
5
7
|
export const dockerProvider: ProviderRegistration = {
|
|
@@ -7,11 +9,21 @@ export const dockerProvider: ProviderRegistration = {
|
|
|
7
9
|
descriptor: CAPABILITY_DESCRIPTORS.docker,
|
|
8
10
|
// Local dev container — no credentials. (The dockerNetwork decoration is
|
|
9
11
|
// applied by the factory, not here: it wraps the constructed client.)
|
|
10
|
-
validateCredentials() {
|
|
12
|
+
validateCredentials(settings) {
|
|
13
|
+
const workspaceBaseDir = settings.dockerWorkspaceBaseDir?.trim();
|
|
14
|
+
if (workspaceBaseDir && !isAbsolute(workspaceBaseDir)) {
|
|
15
|
+
throw new SandboxConfigError(
|
|
16
|
+
"docker",
|
|
17
|
+
"OPENGENI_DOCKER_WORKSPACE_BASE_DIR must be an absolute path",
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
11
21
|
build({ settings, exposedPorts }) {
|
|
22
|
+
const workspaceBaseDir = settings.dockerWorkspaceBaseDir?.trim();
|
|
12
23
|
return new DockerSandboxClient({
|
|
13
24
|
image: settings.dockerImage,
|
|
14
25
|
exposedPorts,
|
|
26
|
+
...(workspaceBaseDir ? { workspaceBaseDir } : {}),
|
|
15
27
|
});
|
|
16
28
|
},
|
|
17
29
|
};
|
|
@@ -1228,7 +1228,22 @@ export class RoutingSandboxSession implements RoutableBackendSession {
|
|
|
1228
1228
|
if (!s.materializeEntry) {
|
|
1229
1229
|
throw new RoutingUnsupportedError("materializeEntry", this.cached?.kind ?? "unknown");
|
|
1230
1230
|
}
|
|
1231
|
-
|
|
1231
|
+
await s.materializeEntry(args);
|
|
1232
|
+
|
|
1233
|
+
// The local Docker SDK materializes through a host path and then bind-mounts
|
|
1234
|
+
// that path into the sandbox. A containerized worker using the host Docker
|
|
1235
|
+
// socket can otherwise write into its own container layer while the sandbox
|
|
1236
|
+
// sees a different, empty host directory. `pathExists()` and `readFile()` on
|
|
1237
|
+
// that SDK session inspect the worker-side path, so only a command executed
|
|
1238
|
+
// inside the actual sandbox proves the materialized path is usable by the
|
|
1239
|
+
// agent. Never let lazy `load_skill` report success on a split workspace.
|
|
1240
|
+
const path =
|
|
1241
|
+
args && typeof args === "object" && typeof (args as { path?: unknown }).path === "string"
|
|
1242
|
+
? (args as { path: string }).path
|
|
1243
|
+
: null;
|
|
1244
|
+
if (path) {
|
|
1245
|
+
await assertProviderCanSeeMaterializedPath(s, path);
|
|
1246
|
+
}
|
|
1232
1247
|
});
|
|
1233
1248
|
}
|
|
1234
1249
|
|
|
@@ -1304,3 +1319,51 @@ export class RoutingSandboxSession implements RoutableBackendSession {
|
|
|
1304
1319
|
return this.resolve();
|
|
1305
1320
|
}
|
|
1306
1321
|
}
|
|
1322
|
+
|
|
1323
|
+
const MATERIALIZED_PATH_MARKER = "__OPENGENI_MATERIALIZED_PATH_VISIBLE__";
|
|
1324
|
+
|
|
1325
|
+
async function assertProviderCanSeeMaterializedPath(
|
|
1326
|
+
session: RoutableBackendSession,
|
|
1327
|
+
path: string,
|
|
1328
|
+
): Promise<void> {
|
|
1329
|
+
const command = `test -e ${shellSingleQuote(path)} && printf %s ${shellSingleQuote(
|
|
1330
|
+
MATERIALIZED_PATH_MARKER,
|
|
1331
|
+
)}`;
|
|
1332
|
+
const args = {
|
|
1333
|
+
cmd: command,
|
|
1334
|
+
workdir: providerManifestRoot(session) ?? "/workspace",
|
|
1335
|
+
shell: "sh",
|
|
1336
|
+
login: false,
|
|
1337
|
+
tty: false,
|
|
1338
|
+
};
|
|
1339
|
+
let output: string;
|
|
1340
|
+
if (session.execCommand) {
|
|
1341
|
+
output = await session.execCommand(args);
|
|
1342
|
+
} else if (session.exec) {
|
|
1343
|
+
output = formatExecResult(await session.exec(args));
|
|
1344
|
+
} else {
|
|
1345
|
+
throw new RoutingUnsupportedError("materializeEntry.verify", "unknown");
|
|
1346
|
+
}
|
|
1347
|
+
if (!output.includes(MATERIALIZED_PATH_MARKER)) {
|
|
1348
|
+
throw new Error(
|
|
1349
|
+
`Sandbox materialization completed but the provider cannot read the destination path: ${path}`,
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
function providerManifestRoot(session: RoutableBackendSession): string | null {
|
|
1355
|
+
const root = (
|
|
1356
|
+
session.state as
|
|
1357
|
+
| {
|
|
1358
|
+
manifest?: {
|
|
1359
|
+
root?: unknown;
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1362
|
+
| undefined
|
|
1363
|
+
)?.manifest?.root;
|
|
1364
|
+
return typeof root === "string" && root.length > 0 ? root : null;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
function shellSingleQuote(value: string): string {
|
|
1368
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
1369
|
+
}
|