@rivet-dev/agentos-core 0.0.0-codex-darwin-ci-publish.61a7af3 → 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.
Files changed (40) hide show
  1. package/README.md +15 -15
  2. package/dist/{agent-os.d.ts → agentos.d.ts} +37 -86
  3. package/dist/{agent-os.js → agentos.js} +146 -188
  4. package/dist/agents.d.ts +1 -1
  5. package/dist/agents.js +2 -2
  6. package/dist/{host-tools-zod.d.ts → bindings-zod.d.ts} +1 -1
  7. package/dist/{host-tools-zod.js → bindings-zod.js} +16 -16
  8. package/dist/bindings.d.ts +45 -0
  9. package/dist/bindings.js +26 -0
  10. package/dist/cron/cron-manager.d.ts +3 -3
  11. package/dist/cron/cron-manager.js +2 -5
  12. package/dist/cron/types.d.ts +1 -1
  13. package/dist/host-dir-mount.d.ts +1 -1
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.js +4 -4
  16. package/dist/json-rpc.d.ts +1 -17
  17. package/dist/json-rpc.js +0 -8
  18. package/dist/layers.d.ts +1 -1
  19. package/dist/layers.js +3 -3
  20. package/dist/packages.d.ts +1 -1
  21. package/dist/packages.js +1 -1
  22. package/dist/runtime-compat.d.ts +6 -2
  23. package/dist/runtime-compat.js +6 -5
  24. package/dist/runtime.d.ts +2 -2
  25. package/dist/sidecar/{agent-os-protocol.d.ts → agentos-protocol.d.ts} +0 -36
  26. package/dist/sidecar/{agent-os-protocol.js → agentos-protocol.js} +2 -42
  27. package/dist/sidecar/native-process-client.d.ts +3 -2
  28. package/dist/sidecar/native-process-client.js +6 -1
  29. package/dist/sidecar/permissions.js +3 -3
  30. package/dist/sidecar/process.d.ts +4 -4
  31. package/dist/sidecar/process.js +3 -3
  32. package/dist/sidecar/rpc-client.d.ts +41 -40
  33. package/dist/sidecar/rpc-client.js +53 -8
  34. package/dist/test/runtime.d.ts +1 -1
  35. package/dist/test/runtime.js +1 -1
  36. package/dist/test/sandbox-agent.js +1 -1
  37. package/dist/types.d.ts +3 -3
  38. package/package.json +25 -25
  39. package/dist/host-tools.d.ts +0 -45
  40. 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 { validateToolkits } from "./host-tools.js";
8
- import { zodToJsonSchema } from "./host-tools-zod.js";
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.agent-os.acp";
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
- import { AcpRuntimeKind, decodeAcpCallback, decodeAcpEvent, decodeAcpResponse, encodeAcpCallbackResponse, encodeAcpRequest, } from "./sidecar/agent-os-protocol.js";
50
+ import { AcpRuntimeKind, decodeAcpCallback, decodeAcpEvent, decodeAcpResponse, encodeAcpCallbackResponse, encodeAcpRequest, } from "./sidecar/agentos-protocol.js";
54
51
  import { serializePermissionsForSidecar } from "./sidecar/permissions.js";
55
- import { createAgentOsSidecarClient, NATIVE_SIDECAR_FRAME_TIMEOUT_MS, NativeSidecarKernelProxy, SidecarProcess, serializeRootFilesystemForSidecar, } from "./sidecar/rpc-client.js";
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",
@@ -488,7 +486,7 @@ function prepareCommandDirs(commandPackages) {
488
486
  if (aliasEntries.length === 0) {
489
487
  continue;
490
488
  }
491
- const aliasDir = mkdtempSync(join(tmpdir(), "agent-os-command-aliases-"));
489
+ const aliasDir = mkdtempSync(join(tmpdir(), "agentos-command-aliases-"));
492
490
  for (const [aliasName, sourcePath] of aliasEntries) {
493
491
  writeFileSync(join(aliasDir, aliasName), readFileSync(sourcePath));
494
492
  }
@@ -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(toolKits) {
838
- const shimDir = mkdtempSync(join(tmpdir(), "agent-os-host-tools-shims-"));
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 toolKit of toolKits) {
841
- writeFileSync(join(shimDir, `agentos-${toolKit.name}`), KERNEL_COMMAND_STUB, { mode: 0o755 });
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(toolKits) {
846
- if (toolKits.length === 0) {
843
+ function collectToolkitBootstrapCommands(bindingGroups) {
844
+ if (bindingGroups.length === 0) {
847
845
  return [];
848
846
  }
849
- return ["agentos", ...toolKits.map((toolKit) => `agentos-${toolKit.name}`)];
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(toolKits) {
892
- if (toolKits.length === 0) {
889
+ function buildHostToolReference(bindingGroups) {
890
+ if (bindingGroups.length === 0) {
893
891
  return "";
894
892
  }
895
893
  const lines = [
896
- "## Available Host Tools",
894
+ "## Available Bindings",
897
895
  "",
898
- "Run `agentos list-tools` to see all available tools.",
896
+ "Run `agentos list-tools` to see all available bindings.",
899
897
  "",
900
898
  ];
901
- for (const toolKit of toolKits) {
902
- lines.push(`### ${toolKit.name}`);
899
+ for (const group of bindingGroups) {
900
+ lines.push(`### ${group.name}`);
903
901
  lines.push("");
904
- lines.push(toolKit.description);
902
+ lines.push(group.description);
905
903
  lines.push("");
906
- for (const [toolName, tool] of Object.entries(toolKit.tools)) {
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-${toolKit.name} ${toolName}${suffix}\` — ${tool.description}`);
908
+ lines.push(`- \`agentos-${group.name} ${bindingName}${suffix}\` — ${tool.description}`);
911
909
  }
912
910
  lines.push("");
913
- const toolsWithExamples = Object.entries(toolKit.tools).filter(([, tool]) => tool.examples && tool.examples.length > 0);
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 [toolName, tool] of toolsWithExamples) {
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-${toolKit.name} ${toolName}${suffix}\``);
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-${toolKit.name} <tool> --help\` for details.`);
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(toolKits) {
1065
+ function buildToolMap(bindingGroups) {
1068
1066
  const toolMap = new Map();
1069
- for (const toolKit of toolKits) {
1070
- for (const [toolName, tool] of Object.entries(toolKit.tools)) {
1071
- toolMap.set(`${toolKit.name}:${toolName}`, tool);
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.toolKits.find((toolKit) => `agentos-${toolKit.name}` === command.command);
1091
+ const directToolKit = context.bindings.find((group) => `agentos-${group.name}` === command.command);
1094
1092
  if (command.command === "agentos") {
1095
- return handleAgentOsRegistryCommand(command, context);
1093
+ return handleAgentOSRegistryCommand(command, context);
1096
1094
  }
1097
1095
  if (directToolKit) {
1098
- return handleAgentOsToolkitCommand(command, context, directToolKit);
1096
+ return handleAgentOSToolkitCommand(command, context, directToolKit);
1099
1097
  }
1100
1098
  throw new Error(`Unknown host callback command "${command.command}"`);
1101
1099
  }
1102
- async function handleAgentOsRegistryCommand(command, context) {
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 [toolkit], <toolkit> --help, or <toolkit> <tool> ...",
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.toolKits, toolkitName)
1112
- : listToolkitsPayload(context.toolKits);
1109
+ ? describeToolkitPayload(context.bindings, toolkitName)
1110
+ : listToolkitsPayload(context.bindings);
1113
1111
  }
1114
- const toolKit = context.toolKits.find((kit) => kit.name === subcommand);
1112
+ const toolKit = context.bindings.find((kit) => kit.name === subcommand);
1115
1113
  if (!toolKit) {
1116
- throw new Error(`No toolkit "${subcommand}". Available: ${toolkitNames(context.toolKits)}`);
1114
+ throw new Error(`No bindings "${subcommand}". Available: ${toolkitNames(context.bindings)}`);
1117
1115
  }
1118
1116
  if (!toolkitName || isHelpFlag(toolkitName)) {
1119
- return describeToolkitPayload(context.toolKits, subcommand);
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 handleAgentOsToolkitCommand(command, context, toolKit) {
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.toolKits, toolKit.name);
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.tools[toolName];
1147
+ const tool = toolKit.bindings[toolName];
1150
1148
  if (!tool) {
1151
- throw new Error(`No tool "${toolName}" in toolkit "${toolKit.name}". Available: ${toolNames(toolKit)}`);
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 tool.invoke policy for ${callbackKey}`);
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(toolKits) {
1267
+ function listToolkitsPayload(bindingGroups) {
1270
1268
  return {
1271
- toolkits: toolKits.map((toolKit) => ({
1272
- name: toolKit.name,
1273
- description: toolKit.description,
1274
- tools: Object.keys(toolKit.tools),
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(toolKits, toolkitName) {
1279
- const toolKit = toolKits.find((kit) => kit.name === toolkitName);
1276
+ function describeToolkitPayload(bindingGroups, toolkitName) {
1277
+ const toolKit = bindingGroups.find((kit) => kit.name === toolkitName);
1280
1278
  if (!toolKit) {
1281
- throw new Error(`No toolkit "${toolkitName}". Available: ${toolkitNames(toolKits)}`);
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
- tools: Object.fromEntries(Object.entries(toolKit.tools).map(([toolName, tool]) => [
1287
- toolName,
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.tools[toolName];
1294
+ const tool = toolKit.bindings[toolName];
1297
1295
  if (!tool) {
1298
- throw new Error(`No tool "${toolName}" in toolkit "${toolKit.name}". Available: ${toolNames(toolKit)}`);
1296
+ throw new Error(`No binding "${toolName}" in bindings "${toolKit.name}". Available: ${toolNames(toolKit)}`);
1299
1297
  }
1300
1298
  return {
1301
- toolkit: toolKit.name,
1302
- tool: toolName,
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.tool;
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(toolKits) {
1347
- return toolKits.map((toolKit) => toolKit.name).join(", ");
1344
+ function toolkitNames(bindingGroups) {
1345
+ return bindingGroups.map((group) => group.name).join(", ");
1348
1346
  }
1349
1347
  function toolNames(toolKit) {
1350
- return Object.keys(toolKit.tools).join(", ");
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, toolKits) {
1360
- if (toolKits.length === 0) {
1357
+ async function registerToolkitsOnSidecar(client, session, vm, bindingGroups) {
1358
+ if (bindingGroups.length === 0) {
1361
1359
  return "";
1362
1360
  }
1363
- for (const toolKit of toolKits) {
1361
+ for (const group of bindingGroups) {
1364
1362
  await client.registerHostCallbacks(session, vm, {
1365
- name: toolKit.name,
1366
- description: toolKit.description,
1367
- commandAliases: [`agentos-${toolKit.name}`],
1363
+ name: group.name,
1364
+ description: group.description,
1365
+ commandAliases: [`agentos-${group.name}`],
1368
1366
  registryCommandAliases: ["agentos"],
1369
- callbacks: Object.fromEntries(Object.entries(toolKit.tools).map(([toolName, tool]) => [
1370
- toolName,
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(toolKits);
1373
+ return buildHostToolReference(bindingGroups);
1376
1374
  }
1377
- export class AgentOs {
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
- _toolKits = [];
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
- agentOsRuntimeAdmins.set(this, {
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 createAgentOsSidecarInternal(options);
1425
+ return createAgentOSSidecarInternal(options);
1428
1426
  }
1429
1427
  static async getSharedSidecar(options = {}) {
1430
- return getSharedAgentOsSidecarInternal(options);
1428
+ return getSharedAgentOSSidecarInternal(options);
1431
1429
  }
1432
1430
  static async create(options) {
1433
- const processed = processSoftware(options?.software ?? []);
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 toolKits = options?.toolKits;
1436
- if (toolKits && toolKits.length > 0) {
1437
- validateToolkits(toolKits);
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(toolKits ?? []);
1446
+ const toolBootstrapCommands = collectToolkitBootstrapCommands(bindingGroups ?? []);
1442
1447
  const bootstrapLower = createKernelBootstrapLower(options?.rootFilesystem, [
1443
1448
  ...collectBootstrapWasmCommands(preparedCommandDirs.commandDirs),
1444
1449
  ...NODE_RUNTIME_BOOTSTRAP_COMMANDS,
@@ -1463,17 +1468,30 @@ export class AgentOs {
1463
1468
  };
1464
1469
  try {
1465
1470
  const env = getBaseEnvironment();
1466
- if (toolKits && toolKits.length > 0) {
1467
- toolShimDir = materializeToolShimDir(toolKits);
1471
+ if (bindingGroups && bindingGroups.length > 0) {
1472
+ toolShimDir = materializeToolShimDir(bindingGroups);
1468
1473
  }
1469
1474
  const commandGuestPaths = collectGuestCommandPaths(preparedCommandDirs.commandDirs);
1475
+ const requestedMounts = options?.moduleAccessCwd
1476
+ ? [
1477
+ ...(options.mounts ?? []),
1478
+ {
1479
+ path: "/root/node_modules",
1480
+ plugin: createHostDirBackend({
1481
+ hostPath: join(options.moduleAccessCwd, "node_modules"),
1482
+ readOnly: true,
1483
+ }),
1484
+ readOnly: true,
1485
+ },
1486
+ ]
1487
+ : options?.mounts;
1470
1488
  const { sidecarMounts, hostMounts, hostPathMappings } = collectSidecarMountPlan({
1471
- mounts: options?.mounts,
1489
+ mounts: requestedMounts,
1472
1490
  softwareRoots: processed.softwareRoots,
1473
1491
  commandDirs: preparedCommandDirs.commandDirs,
1474
1492
  shimDir: toolShimDir,
1475
1493
  });
1476
- client = SidecarProcess.spawn({
1494
+ client = NativeSidecarProcessClient.spawn({
1477
1495
  cwd: REPO_ROOT,
1478
1496
  command: ensureNativeSidecarBinary(),
1479
1497
  args: [],
@@ -1482,7 +1500,7 @@ export class AgentOs {
1482
1500
  const session = await client.authenticateAndOpenSession();
1483
1501
  const hostPermissions = options?.permissions ?? {
1484
1502
  ...allowAll,
1485
- tool: "allow",
1503
+ binding: "allow",
1486
1504
  };
1487
1505
  const sidecarPermissions = serializePermissionsForSidecar(hostPermissions);
1488
1506
  const createVmConfig = {
@@ -1519,11 +1537,11 @@ export class AgentOs {
1519
1537
  commandPermissions: processed.commandPermissions,
1520
1538
  loopbackExemptPorts: options?.loopbackExemptPorts,
1521
1539
  });
1522
- if (toolKits && toolKits.length > 0) {
1523
- toolReference = await registerToolkitsOnSidecar(client, session, nativeVm, toolKits);
1540
+ if (bindingGroups && bindingGroups.length > 0) {
1541
+ toolReference = await registerToolkitsOnSidecar(client, session, nativeVm, bindingGroups);
1524
1542
  commandGuestPaths.set("agentos", "/bin/agentos");
1525
- for (const toolKit of toolKits) {
1526
- commandGuestPaths.set(`agentos-${toolKit.name}`, `/bin/agentos-${toolKit.name}`);
1543
+ for (const group of bindingGroups) {
1544
+ commandGuestPaths.set(`agentos-${group.name}`, `/bin/agentos-${group.name}`);
1527
1545
  }
1528
1546
  }
1529
1547
  rootBridge = new NativeSidecarKernelProxy({
@@ -1531,7 +1549,7 @@ export class AgentOs {
1531
1549
  session,
1532
1550
  vm: nativeVm,
1533
1551
  env,
1534
- cwd: "/home/user",
1552
+ cwd: "/workspace",
1535
1553
  localMounts,
1536
1554
  commandGuestPaths,
1537
1555
  onDispose: cleanup,
@@ -1549,7 +1567,7 @@ export class AgentOs {
1549
1567
  sidecarVm: nativeVm,
1550
1568
  permissions: hostPermissions,
1551
1569
  snapshotRootFilesystem: async () => createSnapshotExport(convertSidecarRootSnapshotEntries(await snapshotClient.snapshotRootFilesystem(session, nativeVm))),
1552
- toolKits: toolKits ?? [],
1570
+ bindings: bindingGroups ?? [],
1553
1571
  toolReference,
1554
1572
  async dispose() {
1555
1573
  if (kernel) {
@@ -1581,16 +1599,16 @@ export class AgentOs {
1581
1599
  throw error;
1582
1600
  }
1583
1601
  };
1584
- const sidecar = resolveAgentOsSidecar(options?.sidecar);
1602
+ const sidecar = resolveAgentOSSidecar(options?.sidecar);
1585
1603
  let sidecarLease = null;
1586
1604
  try {
1587
- sidecarLease = await leaseAgentOsSidecarVm(sidecar, {
1605
+ sidecarLease = await leaseAgentOSSidecarVm(sidecar, {
1588
1606
  createVm: async () => createVmAdmin(),
1589
1607
  });
1590
1608
  const vmAdmin = sidecarLease.admin;
1591
- const vm = new AgentOs(vmAdmin.kernel, sidecar, processed.softwareRoots, processed.agentConfigs, vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm);
1609
+ const vm = new AgentOS(vmAdmin.kernel, sidecar, processed.softwareRoots, processed.agentConfigs, vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm);
1592
1610
  vm._sidecarLease = sidecarLease;
1593
- vm._toolKits = vmAdmin.toolKits;
1611
+ vm._bindings = vmAdmin.bindings;
1594
1612
  vm._toolReference = vmAdmin.toolReference;
1595
1613
  vm._permissions = vmAdmin.permissions;
1596
1614
  vm._installSidecarRequestHandler();
@@ -1605,6 +1623,10 @@ export class AgentOs {
1605
1623
  async exec(command, options) {
1606
1624
  return this.#kernel.exec(command, options);
1607
1625
  }
1626
+ async execArgv(command, args = [], options) {
1627
+ const kernel = this.#kernel;
1628
+ return kernel.execArgv(command, args, options);
1629
+ }
1608
1630
  _trackProcess(proc, command, args, stdoutHandlers, stderrHandlers, exitHandlers) {
1609
1631
  const entry = {
1610
1632
  proc,
@@ -2507,7 +2529,7 @@ export class AgentOs {
2507
2529
  // skipOsInstructions plus the agent's static launch args and env.
2508
2530
  const launchArgs = [...(config.launchArgs ?? [])];
2509
2531
  let launchEnv = { ...config.defaultEnv, ...options?.env };
2510
- const sessionCwd = options?.cwd ?? "/home/user";
2532
+ const sessionCwd = options?.cwd ?? "/workspace";
2511
2533
  const adapterEntrypoint = this._resolveAdapterBin(config.acpAdapter);
2512
2534
  if ((agentType === "pi" || agentType === "pi-cli") &&
2513
2535
  !launchEnv.PI_ACP_PI_COMMAND) {
@@ -2563,70 +2585,6 @@ export class AgentOs {
2563
2585
  }
2564
2586
  return { sessionId: created.sessionId };
2565
2587
  }
2566
- /**
2567
- * Resume a session that exists in durable storage but is not live in this VM
2568
- * (e.g. after a Rivet actor slept and woke with a fresh VM). Thin forwarder:
2569
- * resolves the agent config + adapter entrypoint exactly as {@link createSession}
2570
- * does, then forwards a single `AcpResumeSessionRequest` to the sidecar, which
2571
- * owns the resume state machine (native `session/load` when the agent supports
2572
- * it, else `session/new` + a transcript-continuation preamble). The returned
2573
- * `sessionId` is the live id in this VM (equal to the requested id for native
2574
- * loads, freshly assigned for the fallback); the caller remaps `external -> live`.
2575
- * The new live session is registered + hydrated locally so subsequent prompts
2576
- * route to it.
2577
- *
2578
- * Resume depends on a durable root; on a non-durable (default in-memory) root
2579
- * there is no surviving store and the fallback tier always runs.
2580
- */
2581
- async resumeSession(sessionId, agentType, options) {
2582
- const config = this._resolveAgentConfig(agentType);
2583
- if (!config) {
2584
- throw new Error(`Unknown agent type: ${agentType}`);
2585
- }
2586
- const adapterEntrypoint = this._resolveAdapterBin(config.acpAdapter);
2587
- let launchEnv = { ...config.defaultEnv, ...options?.env };
2588
- const sessionCwd = options?.cwd ?? "/home/user";
2589
- if ((agentType === "pi" || agentType === "pi-cli") &&
2590
- !launchEnv.PI_ACP_PI_COMMAND) {
2591
- launchEnv = {
2592
- ...launchEnv,
2593
- PI_ACP_PI_COMMAND: this._resolvePackageBin(config.agentPackage, "pi"),
2594
- };
2595
- }
2596
- // The resume wire request has no dedicated `adapterEntrypoint` field; carry
2597
- // the resolved entrypoint through env under the sidecar's reserved key. The
2598
- // sidecar reads it and strips it before launching the adapter.
2599
- launchEnv = {
2600
- ...launchEnv,
2601
- [RESUME_ADAPTER_ENTRYPOINT_ENV]: adapterEntrypoint,
2602
- };
2603
- const response = await this._sendAcpRequest({
2604
- tag: "AcpResumeSessionRequest",
2605
- val: {
2606
- sessionId,
2607
- agentType: String(agentType),
2608
- transcriptPath: options?.transcriptPath ?? null,
2609
- cwd: sessionCwd,
2610
- env: new Map(Object.entries(launchEnv)),
2611
- },
2612
- });
2613
- if (response.tag !== "AcpSessionResumedResponse") {
2614
- throw new Error(`unexpected resume_session response: ${response.tag}`);
2615
- }
2616
- const { sessionId: liveSessionId, mode } = response.val;
2617
- // Register + hydrate the live session so subsequent prompts route to it.
2618
- const session = sessionEntryFromInit(liveSessionId, String(agentType), {});
2619
- this._closedSessionIds.delete(liveSessionId);
2620
- this._sessions.set(liveSessionId, session);
2621
- try {
2622
- await this._hydrateSessionState(session);
2623
- }
2624
- catch (error) {
2625
- this._removeSession(liveSessionId);
2626
- throw error;
2627
- }
2628
- return { sessionId: liveSessionId, mode };
2629
- }
2630
2588
  /**
2631
2589
  * Resolve the VM bin entry point of an ACP adapter package.
2632
2590
  * Reads from the host filesystem since kernel.readFile() resolves through
@@ -2666,7 +2624,7 @@ export class AgentOs {
2666
2624
  if (!nodeModulesRoot) {
2667
2625
  throw new Error(`Cannot resolve package "${packageName}": no software root provides it and ` +
2668
2626
  `no /root/node_modules mount was supplied. Pass ` +
2669
- `mounts: [nodeModulesMount("<host>/node_modules")] to AgentOs.create().`);
2627
+ `mounts: [nodeModulesMount("<host>/node_modules")] to AgentOS.create().`);
2670
2628
  }
2671
2629
  hostPkgJsonPath = join(resolvePackageDir(nodeModulesRoot, packageName), "package.json");
2672
2630
  }
@@ -2688,8 +2646,8 @@ export class AgentOs {
2688
2646
  }
2689
2647
  _installSidecarRequestHandler() {
2690
2648
  const context = {
2691
- toolKits: this._toolKits,
2692
- toolMap: buildToolMap(this._toolKits),
2649
+ bindings: this._bindings,
2650
+ toolMap: buildToolMap(this._bindings),
2693
2651
  permissions: this._permissions,
2694
2652
  readFile: (path) => this.readFile(path),
2695
2653
  };
@@ -3400,26 +3358,26 @@ export class AgentOs {
3400
3358
  return this.#kernel.dispose();
3401
3359
  }
3402
3360
  }
3403
- const agentOsRuntimeAdmins = new WeakMap();
3404
- export function getAgentOsRuntimeAdmin(vm) {
3405
- const admin = agentOsRuntimeAdmins.get(vm);
3361
+ const agentOSRuntimeAdmins = new WeakMap();
3362
+ export function getAgentOSRuntimeAdmin(vm) {
3363
+ const admin = agentOSRuntimeAdmins.get(vm);
3406
3364
  if (!admin) {
3407
3365
  throw new Error("Agent OS runtime admin is not available for this VM");
3408
3366
  }
3409
3367
  return admin;
3410
3368
  }
3411
- export function getAgentOsKernel(vm) {
3412
- return getAgentOsRuntimeAdmin(vm).kernel;
3369
+ export function getAgentOSKernel(vm) {
3370
+ return getAgentOSRuntimeAdmin(vm).kernel;
3413
3371
  }
3414
- function resolveAgentOsSidecar(config) {
3372
+ function resolveAgentOSSidecar(config) {
3415
3373
  if (!config || config.kind === "shared") {
3416
- return getSharedAgentOsSidecarInternal(config?.kind === "shared" ? { pool: config.pool } : undefined);
3374
+ return getSharedAgentOSSidecarInternal(config?.kind === "shared" ? { pool: config.pool } : undefined);
3417
3375
  }
3418
3376
  return config.handle;
3419
3377
  }
3420
3378
  const sidecarStates = new WeakMap();
3421
3379
  const sharedSidecars = new Map();
3422
- export class AgentOsSidecar {
3380
+ export class AgentOSSidecar {
3423
3381
  constructor(sidecarId, placement, sharedPool) {
3424
3382
  sidecarStates.set(this, {
3425
3383
  description: {
@@ -3462,9 +3420,9 @@ export class AgentOsSidecar {
3462
3420
  }
3463
3421
  }
3464
3422
  }
3465
- function createAgentOsSidecarInternal(options = {}) {
3423
+ function createAgentOSSidecarInternal(options = {}) {
3466
3424
  const sidecarId = options.sidecarId ?? `agentos-sidecar-${randomUUID()}`;
3467
- return new AgentOsSidecar(sidecarId, {
3425
+ return new AgentOSSidecar(sidecarId, {
3468
3426
  kind: "explicit",
3469
3427
  sidecarId,
3470
3428
  });
@@ -3472,7 +3430,7 @@ function createAgentOsSidecarInternal(options = {}) {
3472
3430
  /**
3473
3431
  * Test-only escape hatch: dispose every cached shared sidecar so vitest
3474
3432
  * workers can exit cleanly. The shared sidecar is normally process-global and
3475
- * keeps its native subprocess alive across `AgentOs.create()` calls; without
3433
+ * keeps its native subprocess alive across `AgentOS.create()` calls; without
3476
3434
  * this hook the vitest worker can hold open piped stdio handles after the
3477
3435
  * test suite finishes and stall `pnpm test` indefinitely.
3478
3436
  */
@@ -3492,23 +3450,23 @@ export async function __disposeAllSharedSidecarsForTesting() {
3492
3450
  throw new Error(`failed to dispose shared sidecars: ${errors.map((error) => error.message).join("; ")}`);
3493
3451
  }
3494
3452
  }
3495
- function getSharedAgentOsSidecarInternal(options = {}) {
3453
+ function getSharedAgentOSSidecarInternal(options = {}) {
3496
3454
  const pool = options.pool ?? "default";
3497
3455
  const existing = sharedSidecars.get(pool);
3498
3456
  if (existing && existing.describe().state !== "disposed") {
3499
3457
  return existing;
3500
3458
  }
3501
- const sidecar = new AgentOsSidecar(`agent-os-shared-sidecar:${pool}`, { kind: "shared", ...(pool ? { pool } : {}) }, pool);
3459
+ const sidecar = new AgentOSSidecar(`agentos-shared-sidecar:${pool}`, { kind: "shared", ...(pool ? { pool } : {}) }, pool);
3502
3460
  sharedSidecars.set(pool, sidecar);
3503
3461
  return sidecar;
3504
3462
  }
3505
- async function leaseAgentOsSidecarVm(sidecar, options) {
3463
+ async function leaseAgentOSSidecarVm(sidecar, options) {
3506
3464
  const state = getSidecarState(sidecar);
3507
3465
  if (state.description.state !== "ready") {
3508
3466
  throw new Error(`Cannot lease VM from sidecar ${state.description.sidecarId} while it is ${state.description.state}`);
3509
3467
  }
3510
3468
  let transport;
3511
- const client = createAgentOsSidecarClient({
3469
+ const client = createAgentOSSidecarClient({
3512
3470
  async createSessionTransport(sessionBootstrap) {
3513
3471
  transport = await createInProcessSidecarTransport(sessionBootstrap, options);
3514
3472
  return transport;