@rivet-dev/agentos-core 0.0.0-integrate-dylib-into-main.815fcda → 0.0.0-nathan-binding-workspace.13eb4d4
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/README.md +12 -12
- package/dist/{agent-os.d.ts → agentos.d.ts} +30 -85
- package/dist/{agent-os.js → agentos.js} +126 -185
- package/dist/agents.d.ts +1 -1
- package/dist/agents.js +1 -1
- package/dist/{host-tools-zod.d.ts → bindings-zod.d.ts} +1 -1
- package/dist/{host-tools-zod.js → bindings-zod.js} +16 -16
- package/dist/bindings.d.ts +45 -0
- package/dist/bindings.js +26 -0
- package/dist/cron/cron-manager.d.ts +3 -3
- package/dist/cron/cron-manager.js +1 -1
- package/dist/cron/types.d.ts +1 -1
- package/dist/host-dir-mount.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/json-rpc.d.ts +1 -17
- package/dist/json-rpc.js +0 -8
- package/dist/packages.js +1 -1
- package/dist/runtime-compat.d.ts +2 -2
- package/dist/runtime-compat.js +6 -5
- package/dist/runtime.d.ts +2 -2
- package/dist/sidecar/agentos-protocol.d.ts +0 -36
- package/dist/sidecar/agentos-protocol.js +1 -41
- package/dist/sidecar/native-process-client.d.ts +3 -2
- package/dist/sidecar/native-process-client.js +6 -1
- package/dist/sidecar/permissions.js +4 -4
- package/dist/sidecar/process.d.ts +4 -4
- package/dist/sidecar/process.js +3 -3
- package/dist/sidecar/rpc-client.d.ts +40 -40
- package/dist/sidecar/rpc-client.js +8 -8
- package/dist/test/runtime.d.ts +1 -1
- package/dist/test/runtime.js +1 -1
- package/dist/types.d.ts +3 -3
- package/package.json +5 -5
- package/dist/host-tools.d.ts +0 -45
- package/dist/host-tools.js +0 -26
|
@@ -4,22 +4,14 @@ import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, w
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { dirname, join, posix as posixPath, resolve as resolveHostPath, } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import {
|
|
8
|
-
import { zodToJsonSchema } from "./
|
|
7
|
+
import { validateBindings } from "./bindings.js";
|
|
8
|
+
import { zodToJsonSchema } from "./bindings-zod.js";
|
|
9
9
|
import { resolvePublishedSidecarBinary } from "./sidecar/binary.js";
|
|
10
10
|
import { findCargoBinary, resolveCargoBinary } from "./sidecar/cargo.js";
|
|
11
11
|
export { isAcpTimeoutErrorData } from "./json-rpc.js";
|
|
12
12
|
const ACP_PROTOCOL_VERSION = 1;
|
|
13
|
-
const ACP_EXTENSION_NAMESPACE = "dev.rivet.
|
|
13
|
+
const ACP_EXTENSION_NAMESPACE = "dev.rivet.agentos.acp";
|
|
14
14
|
const SHELL_DISPOSE_TIMEOUT_MS = 5_000;
|
|
15
|
-
/**
|
|
16
|
-
* Reserved `env` key on `AcpResumeSessionRequest` carrying the resolved adapter
|
|
17
|
-
* bin entrypoint. The resume wire request omits a dedicated `adapterEntrypoint`
|
|
18
|
-
* field; the sidecar reads the entrypoint from this key and strips it before
|
|
19
|
-
* launching the adapter. Must stay in sync with the sidecar constant of the same
|
|
20
|
-
* name in `crates/agentos-sidecar/src/acp_extension.rs`.
|
|
21
|
-
*/
|
|
22
|
-
const RESUME_ADAPTER_ENTRYPOINT_ENV = "AGENT_OS_RESUME_ADAPTER_ENTRYPOINT";
|
|
23
15
|
function defaultAcpClientCapabilities() {
|
|
24
16
|
return {
|
|
25
17
|
fs: {
|
|
@@ -49,10 +41,15 @@ import { createHostDirBackend } from "./host-dir-mount.js";
|
|
|
49
41
|
import { serializeMountConfigForSidecar, } from "./js-bridge.js";
|
|
50
42
|
import { createSnapshotExport, } from "./layers.js";
|
|
51
43
|
import { processSoftware, resolvePackageDir, } from "./packages.js";
|
|
44
|
+
// `@agentos-software/common` (coreutils, sed, grep, gawk, findutils, diffutils,
|
|
45
|
+
// tar, gzip) is part of the default VM software set, so callers never have to add
|
|
46
|
+
// it explicitly. It is prepended to any user-supplied `software` (deduped by
|
|
47
|
+
// reference, so passing it explicitly is still harmless).
|
|
48
|
+
import defaultCommonSoftware from "@agentos-software/common";
|
|
52
49
|
import { allowAll } from "./runtime-compat.js";
|
|
53
50
|
import { AcpRuntimeKind, decodeAcpCallback, decodeAcpEvent, decodeAcpResponse, encodeAcpCallbackResponse, encodeAcpRequest, } from "./sidecar/agentos-protocol.js";
|
|
54
51
|
import { serializePermissionsForSidecar } from "./sidecar/permissions.js";
|
|
55
|
-
import {
|
|
52
|
+
import { createAgentOSSidecarClient, NATIVE_SIDECAR_FRAME_TIMEOUT_MS, NativeSidecarKernelProxy, NativeSidecarProcessClient, serializeRootFilesystemForSidecar, } from "./sidecar/rpc-client.js";
|
|
56
53
|
const LEGACY_PERMISSION_METHOD = "request/permission";
|
|
57
54
|
const ACP_PERMISSION_METHOD = "session/request_permission";
|
|
58
55
|
class AcpDispatchError extends Error {
|
|
@@ -367,6 +364,7 @@ const KERNEL_POSIX_BOOTSTRAP_DIRS = [
|
|
|
367
364
|
"/media",
|
|
368
365
|
"/home",
|
|
369
366
|
"/home/user",
|
|
367
|
+
"/workspace",
|
|
370
368
|
"/usr",
|
|
371
369
|
"/usr/bin",
|
|
372
370
|
"/usr/games",
|
|
@@ -834,19 +832,19 @@ function collectSidecarMountPlan(options) {
|
|
|
834
832
|
hostPathMappings.sort((left, right) => right.vmPath.length - left.vmPath.length);
|
|
835
833
|
return { sidecarMounts, hostMounts, hostPathMappings };
|
|
836
834
|
}
|
|
837
|
-
function materializeToolShimDir(
|
|
838
|
-
const shimDir = mkdtempSync(join(tmpdir(), "agentos-
|
|
835
|
+
function materializeToolShimDir(bindingGroups) {
|
|
836
|
+
const shimDir = mkdtempSync(join(tmpdir(), "agentos-bindings-shims-"));
|
|
839
837
|
writeFileSync(join(shimDir, "agentos"), KERNEL_COMMAND_STUB, { mode: 0o755 });
|
|
840
|
-
for (const
|
|
841
|
-
writeFileSync(join(shimDir, `agentos-${
|
|
838
|
+
for (const group of bindingGroups) {
|
|
839
|
+
writeFileSync(join(shimDir, `agentos-${group.name}`), KERNEL_COMMAND_STUB, { mode: 0o755 });
|
|
842
840
|
}
|
|
843
841
|
return shimDir;
|
|
844
842
|
}
|
|
845
|
-
function collectToolkitBootstrapCommands(
|
|
846
|
-
if (
|
|
843
|
+
function collectToolkitBootstrapCommands(bindingGroups) {
|
|
844
|
+
if (bindingGroups.length === 0) {
|
|
847
845
|
return [];
|
|
848
846
|
}
|
|
849
|
-
return ["agentos", ...
|
|
847
|
+
return ["agentos", ...bindingGroups.map((group) => `agentos-${group.name}`)];
|
|
850
848
|
}
|
|
851
849
|
function validationMessage(error) {
|
|
852
850
|
if (typeof error === "object" &&
|
|
@@ -888,42 +886,42 @@ function combineInstructions(additionalInstructions, toolReference) {
|
|
|
888
886
|
}
|
|
889
887
|
return parts.join("\n\n");
|
|
890
888
|
}
|
|
891
|
-
function buildHostToolReference(
|
|
892
|
-
if (
|
|
889
|
+
function buildHostToolReference(bindingGroups) {
|
|
890
|
+
if (bindingGroups.length === 0) {
|
|
893
891
|
return "";
|
|
894
892
|
}
|
|
895
893
|
const lines = [
|
|
896
|
-
"## Available
|
|
894
|
+
"## Available Bindings",
|
|
897
895
|
"",
|
|
898
|
-
"Run `agentos list-tools` to see all available
|
|
896
|
+
"Run `agentos list-tools` to see all available bindings.",
|
|
899
897
|
"",
|
|
900
898
|
];
|
|
901
|
-
for (const
|
|
902
|
-
lines.push(`### ${
|
|
899
|
+
for (const group of bindingGroups) {
|
|
900
|
+
lines.push(`### ${group.name}`);
|
|
903
901
|
lines.push("");
|
|
904
|
-
lines.push(
|
|
902
|
+
lines.push(group.description);
|
|
905
903
|
lines.push("");
|
|
906
|
-
for (const [
|
|
904
|
+
for (const [bindingName, tool] of Object.entries(group.bindings)) {
|
|
907
905
|
const sidecarTool = toolToSidecarDefinition(tool);
|
|
908
906
|
const signature = buildToolFlagSignature(sidecarTool.inputSchema);
|
|
909
907
|
const suffix = signature.length > 0 ? ` ${signature}` : "";
|
|
910
|
-
lines.push(`- \`agentos-${
|
|
908
|
+
lines.push(`- \`agentos-${group.name} ${bindingName}${suffix}\` — ${tool.description}`);
|
|
911
909
|
}
|
|
912
910
|
lines.push("");
|
|
913
|
-
const toolsWithExamples = Object.entries(
|
|
911
|
+
const toolsWithExamples = Object.entries(group.bindings).filter(([, tool]) => tool.examples && tool.examples.length > 0);
|
|
914
912
|
if (toolsWithExamples.length > 0) {
|
|
915
913
|
lines.push("**Examples:**");
|
|
916
914
|
lines.push("");
|
|
917
|
-
for (const [
|
|
915
|
+
for (const [bindingName, tool] of toolsWithExamples) {
|
|
918
916
|
for (const example of tool.examples ?? []) {
|
|
919
917
|
const args = inputToToolFlags(example.input);
|
|
920
918
|
const suffix = args.length > 0 ? ` ${args}` : "";
|
|
921
|
-
lines.push(`- ${example.description}: \`agentos-${
|
|
919
|
+
lines.push(`- ${example.description}: \`agentos-${group.name} ${bindingName}${suffix}\``);
|
|
922
920
|
}
|
|
923
921
|
}
|
|
924
922
|
lines.push("");
|
|
925
923
|
}
|
|
926
|
-
lines.push(`Run \`agentos-${
|
|
924
|
+
lines.push(`Run \`agentos-${group.name} <binding> --help\` for details.`);
|
|
927
925
|
lines.push("");
|
|
928
926
|
}
|
|
929
927
|
return lines.join("\n");
|
|
@@ -1064,11 +1062,11 @@ async function handleHostCallback(request, context) {
|
|
|
1064
1062
|
};
|
|
1065
1063
|
}
|
|
1066
1064
|
}
|
|
1067
|
-
function buildToolMap(
|
|
1065
|
+
function buildToolMap(bindingGroups) {
|
|
1068
1066
|
const toolMap = new Map();
|
|
1069
|
-
for (const
|
|
1070
|
-
for (const [
|
|
1071
|
-
toolMap.set(`${
|
|
1067
|
+
for (const group of bindingGroups) {
|
|
1068
|
+
for (const [bindingName, tool] of Object.entries(group.bindings)) {
|
|
1069
|
+
toolMap.set(`${group.name}:${bindingName}`, tool);
|
|
1072
1070
|
}
|
|
1073
1071
|
}
|
|
1074
1072
|
return toolMap;
|
|
@@ -1090,33 +1088,33 @@ function parseHostCommandCallbackInput(input) {
|
|
|
1090
1088
|
};
|
|
1091
1089
|
}
|
|
1092
1090
|
async function handleHostCommandCallback(command, context) {
|
|
1093
|
-
const directToolKit = context.
|
|
1091
|
+
const directToolKit = context.bindings.find((group) => `agentos-${group.name}` === command.command);
|
|
1094
1092
|
if (command.command === "agentos") {
|
|
1095
|
-
return
|
|
1093
|
+
return handleAgentOSRegistryCommand(command, context);
|
|
1096
1094
|
}
|
|
1097
1095
|
if (directToolKit) {
|
|
1098
|
-
return
|
|
1096
|
+
return handleAgentOSToolkitCommand(command, context, directToolKit);
|
|
1099
1097
|
}
|
|
1100
1098
|
throw new Error(`Unknown host callback command "${command.command}"`);
|
|
1101
1099
|
}
|
|
1102
|
-
async function
|
|
1100
|
+
async function handleAgentOSRegistryCommand(command, context) {
|
|
1103
1101
|
const [subcommand, toolkitName, toolName, ...toolArgs] = command.args;
|
|
1104
1102
|
if (!subcommand || isHelpFlag(subcommand)) {
|
|
1105
1103
|
return {
|
|
1106
|
-
usage: "agentos <command>: list-tools [
|
|
1104
|
+
usage: "agentos <command>: list-tools [bindings], <bindings> --help, or <bindings> <binding> ...",
|
|
1107
1105
|
};
|
|
1108
1106
|
}
|
|
1109
1107
|
if (subcommand === "list-tools") {
|
|
1110
1108
|
return toolkitName
|
|
1111
|
-
? describeToolkitPayload(context.
|
|
1112
|
-
: listToolkitsPayload(context.
|
|
1109
|
+
? describeToolkitPayload(context.bindings, toolkitName)
|
|
1110
|
+
: listToolkitsPayload(context.bindings);
|
|
1113
1111
|
}
|
|
1114
|
-
const toolKit = context.
|
|
1112
|
+
const toolKit = context.bindings.find((kit) => kit.name === subcommand);
|
|
1115
1113
|
if (!toolKit) {
|
|
1116
|
-
throw new Error(`No
|
|
1114
|
+
throw new Error(`No bindings "${subcommand}". Available: ${toolkitNames(context.bindings)}`);
|
|
1117
1115
|
}
|
|
1118
1116
|
if (!toolkitName || isHelpFlag(toolkitName)) {
|
|
1119
|
-
return describeToolkitPayload(context.
|
|
1117
|
+
return describeToolkitPayload(context.bindings, subcommand);
|
|
1120
1118
|
}
|
|
1121
1119
|
if (toolName && isHelpFlag(toolName)) {
|
|
1122
1120
|
return describeToolPayload(toolKit, toolkitName);
|
|
@@ -1129,10 +1127,10 @@ async function handleAgentOsRegistryCommand(command, context) {
|
|
|
1129
1127
|
context,
|
|
1130
1128
|
});
|
|
1131
1129
|
}
|
|
1132
|
-
async function
|
|
1130
|
+
async function handleAgentOSToolkitCommand(command, context, toolKit) {
|
|
1133
1131
|
const [toolName, helpOrFirstArg, ...rest] = command.args;
|
|
1134
1132
|
if (!toolName || isHelpFlag(toolName)) {
|
|
1135
|
-
return describeToolkitPayload(context.
|
|
1133
|
+
return describeToolkitPayload(context.bindings, toolKit.name);
|
|
1136
1134
|
}
|
|
1137
1135
|
if (helpOrFirstArg && isHelpFlag(helpOrFirstArg)) {
|
|
1138
1136
|
return describeToolPayload(toolKit, toolName);
|
|
@@ -1146,14 +1144,14 @@ async function handleAgentOsToolkitCommand(command, context, toolKit) {
|
|
|
1146
1144
|
});
|
|
1147
1145
|
}
|
|
1148
1146
|
async function invokeHostTool({ toolKit, toolName, args, cwd, context, }) {
|
|
1149
|
-
const tool = toolKit.
|
|
1147
|
+
const tool = toolKit.bindings[toolName];
|
|
1150
1148
|
if (!tool) {
|
|
1151
|
-
throw new Error(`No
|
|
1149
|
+
throw new Error(`No binding "${toolName}" in bindings "${toolKit.name}". Available: ${toolNames(toolKit)}`);
|
|
1152
1150
|
}
|
|
1153
1151
|
const callbackKey = `${toolKit.name}:${toolName}`;
|
|
1154
1152
|
const permissionMode = toolPermissionMode(context.permissions, callbackKey);
|
|
1155
1153
|
if (permissionMode !== "allow") {
|
|
1156
|
-
throw new Error(`EACCES: blocked by
|
|
1154
|
+
throw new Error(`EACCES: blocked by binding.invoke policy for ${callbackKey}`);
|
|
1157
1155
|
}
|
|
1158
1156
|
const input = await parseHostToolInput(tool, args, cwd, context.readFile);
|
|
1159
1157
|
return executeHostTool(tool, callbackKey, input);
|
|
@@ -1266,25 +1264,25 @@ function parseToolArgv(schema, argv) {
|
|
|
1266
1264
|
}
|
|
1267
1265
|
return input;
|
|
1268
1266
|
}
|
|
1269
|
-
function listToolkitsPayload(
|
|
1267
|
+
function listToolkitsPayload(bindingGroups) {
|
|
1270
1268
|
return {
|
|
1271
|
-
|
|
1272
|
-
name:
|
|
1273
|
-
description:
|
|
1274
|
-
|
|
1269
|
+
bindings: bindingGroups.map((group) => ({
|
|
1270
|
+
name: group.name,
|
|
1271
|
+
description: group.description,
|
|
1272
|
+
bindings: Object.keys(group.bindings),
|
|
1275
1273
|
})),
|
|
1276
1274
|
};
|
|
1277
1275
|
}
|
|
1278
|
-
function describeToolkitPayload(
|
|
1279
|
-
const toolKit =
|
|
1276
|
+
function describeToolkitPayload(bindingGroups, toolkitName) {
|
|
1277
|
+
const toolKit = bindingGroups.find((kit) => kit.name === toolkitName);
|
|
1280
1278
|
if (!toolKit) {
|
|
1281
|
-
throw new Error(`No
|
|
1279
|
+
throw new Error(`No bindings "${toolkitName}". Available: ${toolkitNames(bindingGroups)}`);
|
|
1282
1280
|
}
|
|
1283
1281
|
return {
|
|
1284
1282
|
name: toolKit.name,
|
|
1285
1283
|
description: toolKit.description,
|
|
1286
|
-
|
|
1287
|
-
|
|
1284
|
+
bindings: Object.fromEntries(Object.entries(toolKit.bindings).map(([bindingName, tool]) => [
|
|
1285
|
+
bindingName,
|
|
1288
1286
|
{
|
|
1289
1287
|
description: tool.description,
|
|
1290
1288
|
flags: describeToolFlags(toolToSidecarDefinition(tool).inputSchema),
|
|
@@ -1293,13 +1291,13 @@ function describeToolkitPayload(toolKits, toolkitName) {
|
|
|
1293
1291
|
};
|
|
1294
1292
|
}
|
|
1295
1293
|
function describeToolPayload(toolKit, toolName) {
|
|
1296
|
-
const tool = toolKit.
|
|
1294
|
+
const tool = toolKit.bindings[toolName];
|
|
1297
1295
|
if (!tool) {
|
|
1298
|
-
throw new Error(`No
|
|
1296
|
+
throw new Error(`No binding "${toolName}" in bindings "${toolKit.name}". Available: ${toolNames(toolKit)}`);
|
|
1299
1297
|
}
|
|
1300
1298
|
return {
|
|
1301
|
-
|
|
1302
|
-
|
|
1299
|
+
bindings: toolKit.name,
|
|
1300
|
+
binding: toolName,
|
|
1303
1301
|
description: tool.description,
|
|
1304
1302
|
flags: describeToolFlags(toolToSidecarDefinition(tool).inputSchema),
|
|
1305
1303
|
examples: tool.examples?.map((example) => ({
|
|
@@ -1309,7 +1307,7 @@ function describeToolPayload(toolKit, toolName) {
|
|
|
1309
1307
|
};
|
|
1310
1308
|
}
|
|
1311
1309
|
function toolPermissionMode(permissions, callbackKey) {
|
|
1312
|
-
const scope = permissions.
|
|
1310
|
+
const scope = permissions.binding;
|
|
1313
1311
|
if (!scope) {
|
|
1314
1312
|
return "deny";
|
|
1315
1313
|
}
|
|
@@ -1343,11 +1341,11 @@ function permissionPatternMatches(pattern, value) {
|
|
|
1343
1341
|
.join("");
|
|
1344
1342
|
return new RegExp(`^${source}$`).test(value);
|
|
1345
1343
|
}
|
|
1346
|
-
function toolkitNames(
|
|
1347
|
-
return
|
|
1344
|
+
function toolkitNames(bindingGroups) {
|
|
1345
|
+
return bindingGroups.map((group) => group.name).join(", ");
|
|
1348
1346
|
}
|
|
1349
1347
|
function toolNames(toolKit) {
|
|
1350
|
-
return Object.keys(toolKit.
|
|
1348
|
+
return Object.keys(toolKit.bindings).join(", ");
|
|
1351
1349
|
}
|
|
1352
1350
|
function isHelpFlag(value) {
|
|
1353
1351
|
return value === "--help" || value === "-h";
|
|
@@ -1356,25 +1354,25 @@ function jsonSchemaType(schema) {
|
|
|
1356
1354
|
const schemaObject = asRecord(schema);
|
|
1357
1355
|
return typeof schemaObject.type === "string" ? schemaObject.type : undefined;
|
|
1358
1356
|
}
|
|
1359
|
-
async function registerToolkitsOnSidecar(client, session, vm,
|
|
1360
|
-
if (
|
|
1357
|
+
async function registerToolkitsOnSidecar(client, session, vm, bindingGroups) {
|
|
1358
|
+
if (bindingGroups.length === 0) {
|
|
1361
1359
|
return "";
|
|
1362
1360
|
}
|
|
1363
|
-
for (const
|
|
1361
|
+
for (const group of bindingGroups) {
|
|
1364
1362
|
await client.registerHostCallbacks(session, vm, {
|
|
1365
|
-
name:
|
|
1366
|
-
description:
|
|
1367
|
-
commandAliases: [`agentos-${
|
|
1363
|
+
name: group.name,
|
|
1364
|
+
description: group.description,
|
|
1365
|
+
commandAliases: [`agentos-${group.name}`],
|
|
1368
1366
|
registryCommandAliases: ["agentos"],
|
|
1369
|
-
callbacks: Object.fromEntries(Object.entries(
|
|
1370
|
-
|
|
1367
|
+
callbacks: Object.fromEntries(Object.entries(group.bindings).map(([bindingName, tool]) => [
|
|
1368
|
+
bindingName,
|
|
1371
1369
|
toolToSidecarDefinition(tool),
|
|
1372
1370
|
])),
|
|
1373
1371
|
});
|
|
1374
1372
|
}
|
|
1375
|
-
return buildHostToolReference(
|
|
1373
|
+
return buildHostToolReference(bindingGroups);
|
|
1376
1374
|
}
|
|
1377
|
-
export class
|
|
1375
|
+
export class AgentOS {
|
|
1378
1376
|
#kernel;
|
|
1379
1377
|
sidecar;
|
|
1380
1378
|
_sessions = new Map();
|
|
@@ -1391,7 +1389,7 @@ export class AgentOs {
|
|
|
1391
1389
|
_softwareRoots;
|
|
1392
1390
|
_softwareAgentConfigs;
|
|
1393
1391
|
_cronManager;
|
|
1394
|
-
|
|
1392
|
+
_bindings = [];
|
|
1395
1393
|
_toolReference = "";
|
|
1396
1394
|
_permissions = allowAll;
|
|
1397
1395
|
_hostMounts;
|
|
@@ -1416,7 +1414,7 @@ export class AgentOs {
|
|
|
1416
1414
|
this._disposeSidecarEventListener = this._sidecarClient.onEvent((event) => {
|
|
1417
1415
|
this._handleSidecarEvent(event);
|
|
1418
1416
|
});
|
|
1419
|
-
|
|
1417
|
+
agentOSRuntimeAdmins.set(this, {
|
|
1420
1418
|
kernel,
|
|
1421
1419
|
rootView: rootFilesystem,
|
|
1422
1420
|
env,
|
|
@@ -1424,21 +1422,28 @@ export class AgentOs {
|
|
|
1424
1422
|
});
|
|
1425
1423
|
}
|
|
1426
1424
|
static async createSidecar(options = {}) {
|
|
1427
|
-
return
|
|
1425
|
+
return createAgentOSSidecarInternal(options);
|
|
1428
1426
|
}
|
|
1429
1427
|
static async getSharedSidecar(options = {}) {
|
|
1430
|
-
return
|
|
1428
|
+
return getSharedAgentOSSidecarInternal(options);
|
|
1431
1429
|
}
|
|
1432
1430
|
static async create(options) {
|
|
1433
|
-
|
|
1431
|
+
// Prepend the default common software set, skipping any descriptors the
|
|
1432
|
+
// caller already passed (so an explicit `software: [common, ...]` is safe).
|
|
1433
|
+
const userSoftware = options?.software ?? [];
|
|
1434
|
+
const software = [
|
|
1435
|
+
...defaultCommonSoftware.filter((pkg) => !userSoftware.includes(pkg)),
|
|
1436
|
+
...userSoftware,
|
|
1437
|
+
];
|
|
1438
|
+
const processed = processSoftware(software);
|
|
1434
1439
|
const localMounts = await resolveCompatLocalMounts(options?.mounts);
|
|
1435
|
-
const
|
|
1436
|
-
if (
|
|
1437
|
-
|
|
1440
|
+
const bindingGroups = options?.bindings;
|
|
1441
|
+
if (bindingGroups && bindingGroups.length > 0) {
|
|
1442
|
+
validateBindings(bindingGroups);
|
|
1438
1443
|
}
|
|
1439
1444
|
const createVmAdmin = async () => {
|
|
1440
1445
|
const preparedCommandDirs = prepareCommandDirs(processed.commandPackages);
|
|
1441
|
-
const toolBootstrapCommands = collectToolkitBootstrapCommands(
|
|
1446
|
+
const toolBootstrapCommands = collectToolkitBootstrapCommands(bindingGroups ?? []);
|
|
1442
1447
|
const bootstrapLower = createKernelBootstrapLower(options?.rootFilesystem, [
|
|
1443
1448
|
...collectBootstrapWasmCommands(preparedCommandDirs.commandDirs),
|
|
1444
1449
|
...NODE_RUNTIME_BOOTSTRAP_COMMANDS,
|
|
@@ -1463,8 +1468,8 @@ export class AgentOs {
|
|
|
1463
1468
|
};
|
|
1464
1469
|
try {
|
|
1465
1470
|
const env = getBaseEnvironment();
|
|
1466
|
-
if (
|
|
1467
|
-
toolShimDir = materializeToolShimDir(
|
|
1471
|
+
if (bindingGroups && bindingGroups.length > 0) {
|
|
1472
|
+
toolShimDir = materializeToolShimDir(bindingGroups);
|
|
1468
1473
|
}
|
|
1469
1474
|
const commandGuestPaths = collectGuestCommandPaths(preparedCommandDirs.commandDirs);
|
|
1470
1475
|
const requestedMounts = options?.moduleAccessCwd
|
|
@@ -1486,7 +1491,7 @@ export class AgentOs {
|
|
|
1486
1491
|
commandDirs: preparedCommandDirs.commandDirs,
|
|
1487
1492
|
shimDir: toolShimDir,
|
|
1488
1493
|
});
|
|
1489
|
-
client =
|
|
1494
|
+
client = NativeSidecarProcessClient.spawn({
|
|
1490
1495
|
cwd: REPO_ROOT,
|
|
1491
1496
|
command: ensureNativeSidecarBinary(),
|
|
1492
1497
|
args: [],
|
|
@@ -1495,7 +1500,7 @@ export class AgentOs {
|
|
|
1495
1500
|
const session = await client.authenticateAndOpenSession();
|
|
1496
1501
|
const hostPermissions = options?.permissions ?? {
|
|
1497
1502
|
...allowAll,
|
|
1498
|
-
|
|
1503
|
+
binding: "allow",
|
|
1499
1504
|
};
|
|
1500
1505
|
const sidecarPermissions = serializePermissionsForSidecar(hostPermissions);
|
|
1501
1506
|
const createVmConfig = {
|
|
@@ -1532,11 +1537,11 @@ export class AgentOs {
|
|
|
1532
1537
|
commandPermissions: processed.commandPermissions,
|
|
1533
1538
|
loopbackExemptPorts: options?.loopbackExemptPorts,
|
|
1534
1539
|
});
|
|
1535
|
-
if (
|
|
1536
|
-
toolReference = await registerToolkitsOnSidecar(client, session, nativeVm,
|
|
1540
|
+
if (bindingGroups && bindingGroups.length > 0) {
|
|
1541
|
+
toolReference = await registerToolkitsOnSidecar(client, session, nativeVm, bindingGroups);
|
|
1537
1542
|
commandGuestPaths.set("agentos", "/bin/agentos");
|
|
1538
|
-
for (const
|
|
1539
|
-
commandGuestPaths.set(`agentos-${
|
|
1543
|
+
for (const group of bindingGroups) {
|
|
1544
|
+
commandGuestPaths.set(`agentos-${group.name}`, `/bin/agentos-${group.name}`);
|
|
1540
1545
|
}
|
|
1541
1546
|
}
|
|
1542
1547
|
rootBridge = new NativeSidecarKernelProxy({
|
|
@@ -1544,7 +1549,7 @@ export class AgentOs {
|
|
|
1544
1549
|
session,
|
|
1545
1550
|
vm: nativeVm,
|
|
1546
1551
|
env,
|
|
1547
|
-
cwd: "/
|
|
1552
|
+
cwd: "/workspace",
|
|
1548
1553
|
localMounts,
|
|
1549
1554
|
commandGuestPaths,
|
|
1550
1555
|
onDispose: cleanup,
|
|
@@ -1562,7 +1567,7 @@ export class AgentOs {
|
|
|
1562
1567
|
sidecarVm: nativeVm,
|
|
1563
1568
|
permissions: hostPermissions,
|
|
1564
1569
|
snapshotRootFilesystem: async () => createSnapshotExport(convertSidecarRootSnapshotEntries(await snapshotClient.snapshotRootFilesystem(session, nativeVm))),
|
|
1565
|
-
|
|
1570
|
+
bindings: bindingGroups ?? [],
|
|
1566
1571
|
toolReference,
|
|
1567
1572
|
async dispose() {
|
|
1568
1573
|
if (kernel) {
|
|
@@ -1594,16 +1599,16 @@ export class AgentOs {
|
|
|
1594
1599
|
throw error;
|
|
1595
1600
|
}
|
|
1596
1601
|
};
|
|
1597
|
-
const sidecar =
|
|
1602
|
+
const sidecar = resolveAgentOSSidecar(options?.sidecar);
|
|
1598
1603
|
let sidecarLease = null;
|
|
1599
1604
|
try {
|
|
1600
|
-
sidecarLease = await
|
|
1605
|
+
sidecarLease = await leaseAgentOSSidecarVm(sidecar, {
|
|
1601
1606
|
createVm: async () => createVmAdmin(),
|
|
1602
1607
|
});
|
|
1603
1608
|
const vmAdmin = sidecarLease.admin;
|
|
1604
|
-
const vm = new
|
|
1609
|
+
const vm = new AgentOS(vmAdmin.kernel, sidecar, processed.softwareRoots, processed.agentConfigs, vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm);
|
|
1605
1610
|
vm._sidecarLease = sidecarLease;
|
|
1606
|
-
vm.
|
|
1611
|
+
vm._bindings = vmAdmin.bindings;
|
|
1607
1612
|
vm._toolReference = vmAdmin.toolReference;
|
|
1608
1613
|
vm._permissions = vmAdmin.permissions;
|
|
1609
1614
|
vm._installSidecarRequestHandler();
|
|
@@ -2524,7 +2529,7 @@ export class AgentOs {
|
|
|
2524
2529
|
// skipOsInstructions plus the agent's static launch args and env.
|
|
2525
2530
|
const launchArgs = [...(config.launchArgs ?? [])];
|
|
2526
2531
|
let launchEnv = { ...config.defaultEnv, ...options?.env };
|
|
2527
|
-
const sessionCwd = options?.cwd ?? "/
|
|
2532
|
+
const sessionCwd = options?.cwd ?? "/workspace";
|
|
2528
2533
|
const adapterEntrypoint = this._resolveAdapterBin(config.acpAdapter);
|
|
2529
2534
|
if ((agentType === "pi" || agentType === "pi-cli") &&
|
|
2530
2535
|
!launchEnv.PI_ACP_PI_COMMAND) {
|
|
@@ -2580,70 +2585,6 @@ export class AgentOs {
|
|
|
2580
2585
|
}
|
|
2581
2586
|
return { sessionId: created.sessionId };
|
|
2582
2587
|
}
|
|
2583
|
-
/**
|
|
2584
|
-
* Resume a session that exists in durable storage but is not live in this VM
|
|
2585
|
-
* (e.g. after a Rivet actor slept and woke with a fresh VM). Thin forwarder:
|
|
2586
|
-
* resolves the agent config + adapter entrypoint exactly as {@link createSession}
|
|
2587
|
-
* does, then forwards a single `AcpResumeSessionRequest` to the sidecar, which
|
|
2588
|
-
* owns the resume state machine (native `session/load` when the agent supports
|
|
2589
|
-
* it, else `session/new` + a transcript-continuation preamble). The returned
|
|
2590
|
-
* `sessionId` is the live id in this VM (equal to the requested id for native
|
|
2591
|
-
* loads, freshly assigned for the fallback); the caller remaps `external -> live`.
|
|
2592
|
-
* The new live session is registered + hydrated locally so subsequent prompts
|
|
2593
|
-
* route to it.
|
|
2594
|
-
*
|
|
2595
|
-
* Resume depends on a durable root; on a non-durable (default in-memory) root
|
|
2596
|
-
* there is no surviving store and the fallback tier always runs.
|
|
2597
|
-
*/
|
|
2598
|
-
async resumeSession(sessionId, agentType, options) {
|
|
2599
|
-
const config = this._resolveAgentConfig(agentType);
|
|
2600
|
-
if (!config) {
|
|
2601
|
-
throw new Error(`Unknown agent type: ${agentType}`);
|
|
2602
|
-
}
|
|
2603
|
-
const adapterEntrypoint = this._resolveAdapterBin(config.acpAdapter);
|
|
2604
|
-
let launchEnv = { ...config.defaultEnv, ...options?.env };
|
|
2605
|
-
const sessionCwd = options?.cwd ?? "/home/user";
|
|
2606
|
-
if ((agentType === "pi" || agentType === "pi-cli") &&
|
|
2607
|
-
!launchEnv.PI_ACP_PI_COMMAND) {
|
|
2608
|
-
launchEnv = {
|
|
2609
|
-
...launchEnv,
|
|
2610
|
-
PI_ACP_PI_COMMAND: this._resolvePackageBin(config.agentPackage, "pi"),
|
|
2611
|
-
};
|
|
2612
|
-
}
|
|
2613
|
-
// The resume wire request has no dedicated `adapterEntrypoint` field; carry
|
|
2614
|
-
// the resolved entrypoint through env under the sidecar's reserved key. The
|
|
2615
|
-
// sidecar reads it and strips it before launching the adapter.
|
|
2616
|
-
launchEnv = {
|
|
2617
|
-
...launchEnv,
|
|
2618
|
-
[RESUME_ADAPTER_ENTRYPOINT_ENV]: adapterEntrypoint,
|
|
2619
|
-
};
|
|
2620
|
-
const response = await this._sendAcpRequest({
|
|
2621
|
-
tag: "AcpResumeSessionRequest",
|
|
2622
|
-
val: {
|
|
2623
|
-
sessionId,
|
|
2624
|
-
agentType: String(agentType),
|
|
2625
|
-
transcriptPath: options?.transcriptPath ?? null,
|
|
2626
|
-
cwd: sessionCwd,
|
|
2627
|
-
env: new Map(Object.entries(launchEnv)),
|
|
2628
|
-
},
|
|
2629
|
-
});
|
|
2630
|
-
if (response.tag !== "AcpSessionResumedResponse") {
|
|
2631
|
-
throw new Error(`unexpected resume_session response: ${response.tag}`);
|
|
2632
|
-
}
|
|
2633
|
-
const { sessionId: liveSessionId, mode } = response.val;
|
|
2634
|
-
// Register + hydrate the live session so subsequent prompts route to it.
|
|
2635
|
-
const session = sessionEntryFromInit(liveSessionId, String(agentType), {});
|
|
2636
|
-
this._closedSessionIds.delete(liveSessionId);
|
|
2637
|
-
this._sessions.set(liveSessionId, session);
|
|
2638
|
-
try {
|
|
2639
|
-
await this._hydrateSessionState(session);
|
|
2640
|
-
}
|
|
2641
|
-
catch (error) {
|
|
2642
|
-
this._removeSession(liveSessionId);
|
|
2643
|
-
throw error;
|
|
2644
|
-
}
|
|
2645
|
-
return { sessionId: liveSessionId, mode };
|
|
2646
|
-
}
|
|
2647
2588
|
/**
|
|
2648
2589
|
* Resolve the VM bin entry point of an ACP adapter package.
|
|
2649
2590
|
* Reads from the host filesystem since kernel.readFile() resolves through
|
|
@@ -2683,7 +2624,7 @@ export class AgentOs {
|
|
|
2683
2624
|
if (!nodeModulesRoot) {
|
|
2684
2625
|
throw new Error(`Cannot resolve package "${packageName}": no software root provides it and ` +
|
|
2685
2626
|
`no /root/node_modules mount was supplied. Pass ` +
|
|
2686
|
-
`mounts: [nodeModulesMount("<host>/node_modules")] to
|
|
2627
|
+
`mounts: [nodeModulesMount("<host>/node_modules")] to AgentOS.create().`);
|
|
2687
2628
|
}
|
|
2688
2629
|
hostPkgJsonPath = join(resolvePackageDir(nodeModulesRoot, packageName), "package.json");
|
|
2689
2630
|
}
|
|
@@ -2705,8 +2646,8 @@ export class AgentOs {
|
|
|
2705
2646
|
}
|
|
2706
2647
|
_installSidecarRequestHandler() {
|
|
2707
2648
|
const context = {
|
|
2708
|
-
|
|
2709
|
-
toolMap: buildToolMap(this.
|
|
2649
|
+
bindings: this._bindings,
|
|
2650
|
+
toolMap: buildToolMap(this._bindings),
|
|
2710
2651
|
permissions: this._permissions,
|
|
2711
2652
|
readFile: (path) => this.readFile(path),
|
|
2712
2653
|
};
|
|
@@ -3417,26 +3358,26 @@ export class AgentOs {
|
|
|
3417
3358
|
return this.#kernel.dispose();
|
|
3418
3359
|
}
|
|
3419
3360
|
}
|
|
3420
|
-
const
|
|
3421
|
-
export function
|
|
3422
|
-
const admin =
|
|
3361
|
+
const agentOSRuntimeAdmins = new WeakMap();
|
|
3362
|
+
export function getAgentOSRuntimeAdmin(vm) {
|
|
3363
|
+
const admin = agentOSRuntimeAdmins.get(vm);
|
|
3423
3364
|
if (!admin) {
|
|
3424
3365
|
throw new Error("Agent OS runtime admin is not available for this VM");
|
|
3425
3366
|
}
|
|
3426
3367
|
return admin;
|
|
3427
3368
|
}
|
|
3428
|
-
export function
|
|
3429
|
-
return
|
|
3369
|
+
export function getAgentOSKernel(vm) {
|
|
3370
|
+
return getAgentOSRuntimeAdmin(vm).kernel;
|
|
3430
3371
|
}
|
|
3431
|
-
function
|
|
3372
|
+
function resolveAgentOSSidecar(config) {
|
|
3432
3373
|
if (!config || config.kind === "shared") {
|
|
3433
|
-
return
|
|
3374
|
+
return getSharedAgentOSSidecarInternal(config?.kind === "shared" ? { pool: config.pool } : undefined);
|
|
3434
3375
|
}
|
|
3435
3376
|
return config.handle;
|
|
3436
3377
|
}
|
|
3437
3378
|
const sidecarStates = new WeakMap();
|
|
3438
3379
|
const sharedSidecars = new Map();
|
|
3439
|
-
export class
|
|
3380
|
+
export class AgentOSSidecar {
|
|
3440
3381
|
constructor(sidecarId, placement, sharedPool) {
|
|
3441
3382
|
sidecarStates.set(this, {
|
|
3442
3383
|
description: {
|
|
@@ -3479,9 +3420,9 @@ export class AgentOsSidecar {
|
|
|
3479
3420
|
}
|
|
3480
3421
|
}
|
|
3481
3422
|
}
|
|
3482
|
-
function
|
|
3423
|
+
function createAgentOSSidecarInternal(options = {}) {
|
|
3483
3424
|
const sidecarId = options.sidecarId ?? `agentos-sidecar-${randomUUID()}`;
|
|
3484
|
-
return new
|
|
3425
|
+
return new AgentOSSidecar(sidecarId, {
|
|
3485
3426
|
kind: "explicit",
|
|
3486
3427
|
sidecarId,
|
|
3487
3428
|
});
|
|
@@ -3489,7 +3430,7 @@ function createAgentOsSidecarInternal(options = {}) {
|
|
|
3489
3430
|
/**
|
|
3490
3431
|
* Test-only escape hatch: dispose every cached shared sidecar so vitest
|
|
3491
3432
|
* workers can exit cleanly. The shared sidecar is normally process-global and
|
|
3492
|
-
* keeps its native subprocess alive across `
|
|
3433
|
+
* keeps its native subprocess alive across `AgentOS.create()` calls; without
|
|
3493
3434
|
* this hook the vitest worker can hold open piped stdio handles after the
|
|
3494
3435
|
* test suite finishes and stall `pnpm test` indefinitely.
|
|
3495
3436
|
*/
|
|
@@ -3509,23 +3450,23 @@ export async function __disposeAllSharedSidecarsForTesting() {
|
|
|
3509
3450
|
throw new Error(`failed to dispose shared sidecars: ${errors.map((error) => error.message).join("; ")}`);
|
|
3510
3451
|
}
|
|
3511
3452
|
}
|
|
3512
|
-
function
|
|
3453
|
+
function getSharedAgentOSSidecarInternal(options = {}) {
|
|
3513
3454
|
const pool = options.pool ?? "default";
|
|
3514
3455
|
const existing = sharedSidecars.get(pool);
|
|
3515
3456
|
if (existing && existing.describe().state !== "disposed") {
|
|
3516
3457
|
return existing;
|
|
3517
3458
|
}
|
|
3518
|
-
const sidecar = new
|
|
3459
|
+
const sidecar = new AgentOSSidecar(`agentos-shared-sidecar:${pool}`, { kind: "shared", ...(pool ? { pool } : {}) }, pool);
|
|
3519
3460
|
sharedSidecars.set(pool, sidecar);
|
|
3520
3461
|
return sidecar;
|
|
3521
3462
|
}
|
|
3522
|
-
async function
|
|
3463
|
+
async function leaseAgentOSSidecarVm(sidecar, options) {
|
|
3523
3464
|
const state = getSidecarState(sidecar);
|
|
3524
3465
|
if (state.description.state !== "ready") {
|
|
3525
3466
|
throw new Error(`Cannot lease VM from sidecar ${state.description.sidecarId} while it is ${state.description.state}`);
|
|
3526
3467
|
}
|
|
3527
3468
|
let transport;
|
|
3528
|
-
const client =
|
|
3469
|
+
const client = createAgentOSSidecarClient({
|
|
3529
3470
|
async createSessionTransport(sessionBootstrap) {
|
|
3530
3471
|
transport = await createInProcessSidecarTransport(sessionBootstrap, options);
|
|
3531
3472
|
return transport;
|
package/dist/agents.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export declare const AGENT_CONFIGS: {
|
|
|
42
42
|
defaultEnv: {
|
|
43
43
|
CLAUDE_AGENT_SDK_CLIENT_APP: string;
|
|
44
44
|
CLAUDE_CODE_SIMPLE: string;
|
|
45
|
-
|
|
45
|
+
CLAUDE_CODE_FORCE_AGENTOS_RIPGREP: string;
|
|
46
46
|
CLAUDE_CODE_DEFER_GROWTHBOOK_INIT: string;
|
|
47
47
|
CLAUDE_CODE_DISABLE_CWD_PERSIST: string;
|
|
48
48
|
CLAUDE_CODE_DISABLE_DEV_NULL_REDIRECT: string;
|