@rivet-dev/agentos-core 0.2.20-rc.1 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/agent-os.js CHANGED
@@ -5,8 +5,8 @@ import { join, posix as posixPath, resolve as resolveHostPath, } from "node:path
5
5
  import { fileURLToPath } from "node:url";
6
6
  import * as executionProtocol from "@rivet-dev/agentos-runtime-core/protocol";
7
7
  import { SidecarRejectedError } from "@rivet-dev/agentos-runtime-core/sidecar-errors";
8
- import { validateBindings } from "./bindings.js";
9
- import { zodToJsonSchema } from "./bindings-zod.js";
8
+ import { hostFunctionDescription, resolveHostFunctions, } from "@rivet-dev/agentos-runtime-core/host-functions";
9
+ import { zodToJsonSchema } from "@rivet-dev/agentos-runtime-core/host-functions-zod";
10
10
  import { parseAgentOsOptions } from "./options-schema.js";
11
11
  import { getSandboxDisposeHooks, resolveSandboxOptions, } from "./sandbox.js";
12
12
  import { resolvePublishedSidecarBinary } from "./sidecar/binary.js";
@@ -168,7 +168,6 @@ import { resolveDefaultSoftware } from "./default-software.js";
168
168
  import { snapshotVirtualFilesystem, sortFilesystemEntries, } from "./filesystem-snapshot.js";
169
169
  import { serializeMountConfigForSidecar, } from "./js-bridge.js";
170
170
  import { createSnapshotExport, } from "./layers.js";
171
- import { allowAll } from "./runtime-compat.js";
172
171
  import { decodeAcpCallback, decodeAcpEvent, decodeAcpResponse, encodeAcpCallbackResponse, encodeAcpRequest, } from "./sidecar/agentos-protocol.js";
173
172
  import { serializePermissionsForSidecar } from "./sidecar/permissions.js";
174
173
  import { createAgentOsSidecarClient, NativeSidecarKernelProxy, SidecarProcess, serializeRootFilesystemForSidecar, } from "./sidecar/rpc-client.js";
@@ -773,13 +772,13 @@ function collectSidecarMountPlan(options) {
773
772
  hostPathMappings.sort((left, right) => right.vmPath.length - left.vmPath.length);
774
773
  return { sidecarMounts, hostMounts, hostPathMappings };
775
774
  }
776
- function collectBindingBootstrapCommands(bindings) {
777
- if (bindings.length === 0) {
775
+ function collectHostFunctionBootstrapCommands(hostFunctions) {
776
+ if (hostFunctions.length === 0) {
778
777
  return [];
779
778
  }
780
779
  return [
781
780
  "agentos",
782
- ...bindings.map((bindingCollection) => `agentos-${bindingCollection.name}`),
781
+ ...hostFunctions.map((hostFunctionCollection) => `agentos-${hostFunctionCollection.name}`),
783
782
  ];
784
783
  }
785
784
  function validationMessage(error) {
@@ -798,9 +797,9 @@ function validationMessage(error) {
798
797
  }
799
798
  return error instanceof Error ? error.message : String(error);
800
799
  }
801
- function bindingToSidecarDefinition(definition) {
800
+ function hostFunctionToSidecarDefinition(definition) {
802
801
  return {
803
- description: definition.description,
802
+ description: hostFunctionDescription(definition),
804
803
  inputSchema: zodToJsonSchema(definition.inputSchema),
805
804
  ...(definition.timeout !== undefined
806
805
  ? { timeoutMs: definition.timeout }
@@ -815,8 +814,8 @@ function bindingToSidecarDefinition(definition) {
815
814
  : {}),
816
815
  };
817
816
  }
818
- function combineInstructions(additionalInstructions, bindingReference) {
819
- const parts = [additionalInstructions, bindingReference]
817
+ function combineInstructions(additionalInstructions, hostFunctionReference) {
818
+ const parts = [additionalInstructions, hostFunctionReference]
820
819
  .map((part) => part?.trim())
821
820
  .filter((part) => Boolean(part));
822
821
  if (parts.length === 0) {
@@ -824,48 +823,49 @@ function combineInstructions(additionalInstructions, bindingReference) {
824
823
  }
825
824
  return parts.join("\n\n");
826
825
  }
827
- function buildBindingReference(bindings) {
828
- if (bindings.length === 0) {
826
+ function buildHostFunctionReference(hostFunctions) {
827
+ if (hostFunctions.length === 0) {
829
828
  return "";
830
829
  }
831
830
  const lines = [
832
- "## Available Host Bindings",
831
+ "## Available Host Functions",
833
832
  "",
834
- "Run `agentos list-bindings` to see all available bindings.",
833
+ "Run `agentos list-host-functions` to see all available host functions.",
835
834
  "",
836
835
  ];
837
- for (const bindingCollection of bindings) {
838
- lines.push(`### ${bindingCollection.name}`);
836
+ for (const hostFunctionCollection of hostFunctions) {
837
+ lines.push(`### ${hostFunctionCollection.name}`);
839
838
  lines.push("");
840
- lines.push(bindingCollection.description);
841
- lines.push("");
842
- for (const [bindingName, definition] of Object.entries(bindingCollection.bindings)) {
843
- const sidecarBinding = bindingToSidecarDefinition(definition);
844
- const signature = buildBindingFlagSignature(sidecarBinding.inputSchema);
839
+ for (const [functionName, definition] of Object.entries(hostFunctionCollection.functions)) {
840
+ const sidecarHostFunction = hostFunctionToSidecarDefinition(definition);
841
+ const signature = buildHostFunctionFlagSignature(sidecarHostFunction.inputSchema);
845
842
  const suffix = signature.length > 0 ? ` ${signature}` : "";
846
- lines.push(`- \`agentos-${bindingCollection.name} ${bindingName}${suffix}\` — ${definition.description}`);
843
+ const description = hostFunctionDescription(definition);
844
+ lines.push(description.length > 0
845
+ ? `- \`agentos-${hostFunctionCollection.name} ${functionName}${suffix}\` - ${description}`
846
+ : `- \`agentos-${hostFunctionCollection.name} ${functionName}${suffix}\``);
847
847
  }
848
848
  lines.push("");
849
- const bindingsWithExamples = Object.entries(bindingCollection.bindings).filter(([, definition]) => definition.examples && definition.examples.length > 0);
850
- if (bindingsWithExamples.length > 0) {
849
+ const functionsWithExamples = Object.entries(hostFunctionCollection.functions).filter(([, definition]) => definition.examples && definition.examples.length > 0);
850
+ if (functionsWithExamples.length > 0) {
851
851
  lines.push("**Examples:**");
852
852
  lines.push("");
853
- for (const [bindingName, definition] of bindingsWithExamples) {
853
+ for (const [functionName, definition] of functionsWithExamples) {
854
854
  for (const example of definition.examples ?? []) {
855
- const args = inputToBindingFlags(example.input);
855
+ const args = inputToHostFunctionFlags(example.input);
856
856
  const suffix = args.length > 0 ? ` ${args}` : "";
857
- lines.push(`- ${example.description}: \`agentos-${bindingCollection.name} ${bindingName}${suffix}\``);
857
+ lines.push(`- ${example.description}: \`agentos-${hostFunctionCollection.name} ${functionName}${suffix}\``);
858
858
  }
859
859
  }
860
860
  lines.push("");
861
861
  }
862
- lines.push(`Run \`agentos-${bindingCollection.name} <binding> --help\` for details.`);
862
+ lines.push(`Run \`agentos-${hostFunctionCollection.name} <function> --help\` for details.`);
863
863
  lines.push("");
864
864
  }
865
865
  return lines.join("\n");
866
866
  }
867
- function buildBindingFlagSignature(schema) {
868
- return describeBindingFlags(schema)
867
+ function buildHostFunctionFlagSignature(schema) {
868
+ return describeHostFunctionFlags(schema)
869
869
  .map((flag) => {
870
870
  if (flag.required) {
871
871
  return `${flag.name} <${flag.type}>`;
@@ -874,7 +874,7 @@ function buildBindingFlagSignature(schema) {
874
874
  })
875
875
  .join(" ");
876
876
  }
877
- function describeBindingFlags(schema) {
877
+ function describeHostFunctionFlags(schema) {
878
878
  const schemaObject = asRecord(schema);
879
879
  const properties = asRecord(schemaObject.properties);
880
880
  const required = Array.isArray(schemaObject.required)
@@ -882,11 +882,11 @@ function describeBindingFlags(schema) {
882
882
  : new Set();
883
883
  return Object.entries(properties).map(([fieldName, fieldSchema]) => ({
884
884
  name: `--${camelToKebab(fieldName)}`,
885
- type: describeBindingFlagType(fieldSchema),
885
+ type: describeHostFunctionFlagType(fieldSchema),
886
886
  required: required.has(fieldName),
887
887
  }));
888
888
  }
889
- function describeBindingFlagType(schema) {
889
+ function describeHostFunctionFlagType(schema) {
890
890
  const schemaObject = asRecord(schema);
891
891
  const type = typeof schemaObject.type === "string" ? schemaObject.type : undefined;
892
892
  if (type === "array") {
@@ -905,7 +905,7 @@ function describeJsonSchemaScalarType(schema) {
905
905
  const schemaObject = asRecord(schema);
906
906
  return typeof schemaObject.type === "string" ? schemaObject.type : "string";
907
907
  }
908
- function inputToBindingFlags(input) {
908
+ function inputToHostFunctionFlags(input) {
909
909
  const inputObject = asRecord(input);
910
910
  return Object.entries(inputObject)
911
911
  .flatMap(([key, value]) => {
@@ -917,13 +917,13 @@ function inputToBindingFlags(input) {
917
917
  return [`--no-${camelToKebab(key)}`];
918
918
  }
919
919
  if (Array.isArray(value)) {
920
- return value.map((item) => `${flag} ${bindingCliString(item)}`);
920
+ return value.map((item) => `${flag} ${hostFunctionCliString(item)}`);
921
921
  }
922
- return [`${flag} ${bindingCliString(value)}`];
922
+ return [`${flag} ${hostFunctionCliString(value)}`];
923
923
  })
924
924
  .join(" ");
925
925
  }
926
- function bindingCliString(value) {
926
+ function hostFunctionCliString(value) {
927
927
  return typeof value === "string" ? value : (JSON.stringify(value) ?? "null");
928
928
  }
929
929
  function camelToKebab(value) {
@@ -961,22 +961,16 @@ async function handleHostCallback(request, context) {
961
961
  };
962
962
  }
963
963
  }
964
- const definition = context.bindingMap.get(payload.callback_key);
964
+ const definition = context.hostFunctionMap.get(payload.callback_key);
965
965
  if (!definition) {
966
966
  return {
967
967
  type: "host_callback_result",
968
968
  invocation_id: payload.invocation_id,
969
- error: `Unknown binding "${payload.callback_key}"`,
970
- };
971
- }
972
- const permissionMode = bindingPermissionMode(context.permissions, payload.callback_key);
973
- if (permissionMode !== "allow") {
974
- return {
975
- type: "host_callback_result",
976
- invocation_id: payload.invocation_id,
977
- error: `EACCES: blocked by binding.invoke policy for ${payload.callback_key}`,
969
+ error: `Unknown host function "${payload.callback_key}"`,
978
970
  };
979
971
  }
972
+ // The sidecar checks the `hostFunction` permission scope before it forwards a
973
+ // host function call, so a call that reaches the host is already permitted.
980
974
  const parsed = definition.inputSchema.safeParse(payload.input);
981
975
  if (!parsed.success) {
982
976
  return {
@@ -989,7 +983,7 @@ async function handleHostCallback(request, context) {
989
983
  return {
990
984
  type: "host_callback_result",
991
985
  invocation_id: payload.invocation_id,
992
- result: await executeBinding(definition, payload.callback_key, parsed.data),
986
+ result: await executeHostFunction(definition, payload.callback_key, parsed.data),
993
987
  };
994
988
  }
995
989
  catch (error) {
@@ -1000,14 +994,14 @@ async function handleHostCallback(request, context) {
1000
994
  };
1001
995
  }
1002
996
  }
1003
- function buildBindingMap(bindings) {
1004
- const bindingMap = new Map();
1005
- for (const bindingCollection of bindings) {
1006
- for (const [bindingName, definition] of Object.entries(bindingCollection.bindings)) {
1007
- bindingMap.set(`${bindingCollection.name}:${bindingName}`, definition);
997
+ function buildHostFunctionMap(hostFunctions) {
998
+ const hostFunctionMap = new Map();
999
+ for (const hostFunctionCollection of hostFunctions) {
1000
+ for (const [functionName, definition] of Object.entries(hostFunctionCollection.functions)) {
1001
+ hostFunctionMap.set(`${hostFunctionCollection.name}:${functionName}`, definition);
1008
1002
  }
1009
1003
  }
1010
- return bindingMap;
1004
+ return hostFunctionMap;
1011
1005
  }
1012
1006
  function bridgeErrorMessage(error) {
1013
1007
  return error instanceof Error ? error.message : String(error);
@@ -1154,75 +1148,73 @@ function parseHostCommandCallbackInput(input) {
1154
1148
  };
1155
1149
  }
1156
1150
  async function handleHostCommandCallback(command, context) {
1157
- const directBindings = context.bindings.find((bindingCollection) => `agentos-${bindingCollection.name}` === command.command);
1151
+ const directHostFunctions = context.hostFunctions.find((hostFunctionCollection) => `agentos-${hostFunctionCollection.name}` === command.command);
1158
1152
  if (command.command === "agentos") {
1159
1153
  return handleAgentOsRegistryCommand(command, context);
1160
1154
  }
1161
- if (directBindings) {
1162
- return handleAgentOsBindingCommand(command, context, directBindings);
1155
+ if (directHostFunctions) {
1156
+ return handleAgentOsHostFunctionCommand(command, context, directHostFunctions);
1163
1157
  }
1164
1158
  throw new Error(`Unknown host callback command "${command.command}"`);
1165
1159
  }
1166
1160
  async function handleAgentOsRegistryCommand(command, context) {
1167
- const [subcommand, collectionName, bindingName, ...bindingArgs] = command.args;
1161
+ const [subcommand, collectionName, functionName, ...functionArgs] = command.args;
1168
1162
  if (!subcommand || isHelpFlag(subcommand)) {
1169
1163
  return {
1170
- usage: "agentos <command>: list-bindings [collection], <collection> --help, or <collection> <binding> ...",
1164
+ usage: "agentos <command>: list-host-functions [collection], <collection> --help, or <collection> <function> ...",
1171
1165
  };
1172
1166
  }
1173
- if (subcommand === "list-bindings") {
1167
+ if (subcommand === "list-host-functions" || subcommand === "list-bindings") {
1174
1168
  return collectionName
1175
- ? describeBindingsPayload(context.bindings, collectionName)
1176
- : listBindingsPayload(context.bindings);
1169
+ ? describeHostFunctionsPayload(context.hostFunctions, collectionName)
1170
+ : listHostFunctionsPayload(context.hostFunctions);
1177
1171
  }
1178
- const bindingCollection = context.bindings.find((collection) => collection.name === subcommand);
1179
- if (!bindingCollection) {
1180
- throw new Error(`No binding collection "${subcommand}". Available: ${bindingsNames(context.bindings)}`);
1172
+ const hostFunctionCollection = context.hostFunctions.find((collection) => collection.name === subcommand);
1173
+ if (!hostFunctionCollection) {
1174
+ throw new Error(`No host function collection "${subcommand}". Available: ${hostFunctionsNames(context.hostFunctions)}`);
1181
1175
  }
1182
1176
  if (!collectionName || isHelpFlag(collectionName)) {
1183
- return describeBindingsPayload(context.bindings, subcommand);
1177
+ return describeHostFunctionsPayload(context.hostFunctions, subcommand);
1184
1178
  }
1185
- if (bindingName && isHelpFlag(bindingName)) {
1186
- return describeBindingPayload(bindingCollection, collectionName);
1179
+ if (functionName && isHelpFlag(functionName)) {
1180
+ return describeHostFunctionPayload(hostFunctionCollection, collectionName);
1187
1181
  }
1188
- return invokeBinding({
1189
- bindingCollection,
1190
- bindingName: collectionName,
1191
- args: [bindingName, ...bindingArgs].filter((value) => typeof value === "string"),
1182
+ return invokeHostFunction({
1183
+ hostFunctionCollection,
1184
+ functionName: collectionName,
1185
+ args: [functionName, ...functionArgs].filter((value) => typeof value === "string"),
1192
1186
  cwd: command.cwd,
1193
1187
  context,
1194
1188
  });
1195
1189
  }
1196
- async function handleAgentOsBindingCommand(command, context, bindingCollection) {
1197
- const [bindingName, helpOrFirstArg, ...rest] = command.args;
1198
- if (!bindingName || isHelpFlag(bindingName)) {
1199
- return describeBindingsPayload(context.bindings, bindingCollection.name);
1190
+ async function handleAgentOsHostFunctionCommand(command, context, hostFunctionCollection) {
1191
+ const [functionName, helpOrFirstArg, ...rest] = command.args;
1192
+ if (!functionName || isHelpFlag(functionName)) {
1193
+ return describeHostFunctionsPayload(context.hostFunctions, hostFunctionCollection.name);
1200
1194
  }
1201
1195
  if (helpOrFirstArg && isHelpFlag(helpOrFirstArg)) {
1202
- return describeBindingPayload(bindingCollection, bindingName);
1196
+ return describeHostFunctionPayload(hostFunctionCollection, functionName);
1203
1197
  }
1204
- return invokeBinding({
1205
- bindingCollection,
1206
- bindingName,
1198
+ return invokeHostFunction({
1199
+ hostFunctionCollection,
1200
+ functionName,
1207
1201
  args: [helpOrFirstArg, ...rest].filter((value) => typeof value === "string"),
1208
1202
  cwd: command.cwd,
1209
1203
  context,
1210
1204
  });
1211
1205
  }
1212
- async function invokeBinding({ bindingCollection, bindingName, args, cwd, context, }) {
1213
- const definition = bindingCollection.bindings[bindingName];
1206
+ async function invokeHostFunction({ hostFunctionCollection, functionName, args, cwd, context, }) {
1207
+ const definition = hostFunctionCollection.functions[functionName];
1214
1208
  if (!definition) {
1215
- throw new Error(`No binding "${bindingName}" in collection "${bindingCollection.name}". Available: ${bindingNames(bindingCollection)}`);
1216
- }
1217
- const callbackKey = `${bindingCollection.name}:${bindingName}`;
1218
- const permissionMode = bindingPermissionMode(context.permissions, callbackKey);
1219
- if (permissionMode !== "allow") {
1220
- throw new Error(`EACCES: blocked by binding.invoke policy for ${callbackKey}`);
1209
+ throw new Error(`No host function "${functionName}" in collection "${hostFunctionCollection.name}". Available: ${hostFunctionNames(hostFunctionCollection)}`);
1221
1210
  }
1222
- const input = await parseBindingInput(definition, args, cwd, context.readFile);
1223
- return executeBinding(definition, callbackKey, input);
1211
+ // The sidecar checks the `hostFunction` permission scope for registry commands
1212
+ // before forwarding them, the same as for collection commands.
1213
+ const callbackKey = `${hostFunctionCollection.name}:${functionName}`;
1214
+ const input = await parseHostFunctionInput(definition, args, cwd, context.readFile);
1215
+ return executeHostFunction(definition, callbackKey, input);
1224
1216
  }
1225
- async function executeBinding(definition, callbackKey, input) {
1217
+ async function executeHostFunction(definition, callbackKey, input) {
1226
1218
  const parsed = definition.inputSchema.safeParse(input);
1227
1219
  if (!parsed.success) {
1228
1220
  throw new Error(validationMessage(parsed.error));
@@ -1233,11 +1225,11 @@ async function executeBinding(definition, callbackKey, input) {
1233
1225
  if (definition.timeout === undefined) {
1234
1226
  return;
1235
1227
  }
1236
- setTimeout(() => reject(new Error(`Binding "${callbackKey}" timed out after ${definition.timeout}ms`)), definition.timeout);
1228
+ setTimeout(() => reject(new Error(`Host function "${callbackKey}" timed out after ${definition.timeout}ms`)), definition.timeout);
1237
1229
  }),
1238
1230
  ]);
1239
1231
  }
1240
- async function parseBindingInput(definition, args, cwd, readFile) {
1232
+ async function parseHostFunctionInput(definition, args, cwd, readFile) {
1241
1233
  if (args[0] === "--json") {
1242
1234
  const value = args[1];
1243
1235
  if (value === undefined) {
@@ -1256,9 +1248,9 @@ async function parseBindingInput(definition, args, cwd, readFile) {
1256
1248
  const text = new TextDecoder().decode(await readFile(guestPath));
1257
1249
  return JSON.parse(text);
1258
1250
  }
1259
- return parseBindingArgv(bindingToSidecarDefinition(definition).inputSchema, args);
1251
+ return parseHostFunctionArgv(hostFunctionToSidecarDefinition(definition).inputSchema, args);
1260
1252
  }
1261
- function parseBindingArgv(schema, argv) {
1253
+ function parseHostFunctionArgv(schema, argv) {
1262
1254
  const schemaObject = asRecord(schema);
1263
1255
  const properties = asRecord(schemaObject.properties);
1264
1256
  const required = Array.isArray(schemaObject.required)
@@ -1330,88 +1322,53 @@ function parseBindingArgv(schema, argv) {
1330
1322
  }
1331
1323
  return input;
1332
1324
  }
1333
- function listBindingsPayload(bindings) {
1325
+ function listHostFunctionsPayload(hostFunctions) {
1334
1326
  return {
1335
- bindings: bindings.map((bindingCollection) => ({
1336
- name: bindingCollection.name,
1337
- description: bindingCollection.description,
1338
- bindings: Object.keys(bindingCollection.bindings),
1327
+ hostFunctions: hostFunctions.map((hostFunctionCollection) => ({
1328
+ name: hostFunctionCollection.name,
1329
+ functions: Object.keys(hostFunctionCollection.functions),
1339
1330
  })),
1340
1331
  };
1341
1332
  }
1342
- function describeBindingsPayload(bindings, collectionName) {
1343
- const bindingCollection = bindings.find((collection) => collection.name === collectionName);
1344
- if (!bindingCollection) {
1345
- throw new Error(`No binding collection "${collectionName}". Available: ${bindingsNames(bindings)}`);
1333
+ function describeHostFunctionsPayload(hostFunctions, collectionName) {
1334
+ const hostFunctionCollection = hostFunctions.find((collection) => collection.name === collectionName);
1335
+ if (!hostFunctionCollection) {
1336
+ throw new Error(`No host function collection "${collectionName}". Available: ${hostFunctionsNames(hostFunctions)}`);
1346
1337
  }
1347
1338
  return {
1348
- name: bindingCollection.name,
1349
- description: bindingCollection.description,
1350
- bindings: Object.fromEntries(Object.entries(bindingCollection.bindings).map(([bindingName, definition]) => [
1351
- bindingName,
1339
+ name: hostFunctionCollection.name,
1340
+ functions: Object.fromEntries(Object.entries(hostFunctionCollection.functions).map(([functionName, definition]) => [
1341
+ functionName,
1352
1342
  {
1353
- description: definition.description,
1354
- flags: describeBindingFlags(bindingToSidecarDefinition(definition).inputSchema),
1343
+ description: hostFunctionDescription(definition),
1344
+ flags: describeHostFunctionFlags(hostFunctionToSidecarDefinition(definition).inputSchema),
1355
1345
  },
1356
1346
  ])),
1357
1347
  };
1358
1348
  }
1359
- function describeBindingPayload(bindingCollection, bindingName) {
1360
- const definition = bindingCollection.bindings[bindingName];
1349
+ function describeHostFunctionPayload(hostFunctionCollection, functionName) {
1350
+ const definition = hostFunctionCollection.functions[functionName];
1361
1351
  if (!definition) {
1362
- throw new Error(`No binding "${bindingName}" in collection "${bindingCollection.name}". Available: ${bindingNames(bindingCollection)}`);
1352
+ throw new Error(`No host function "${functionName}" in collection "${hostFunctionCollection.name}". Available: ${hostFunctionNames(hostFunctionCollection)}`);
1363
1353
  }
1364
1354
  return {
1365
- collection: bindingCollection.name,
1366
- binding: bindingName,
1367
- description: definition.description,
1368
- flags: describeBindingFlags(bindingToSidecarDefinition(definition).inputSchema),
1355
+ collection: hostFunctionCollection.name,
1356
+ function: functionName,
1357
+ description: hostFunctionDescription(definition),
1358
+ flags: describeHostFunctionFlags(hostFunctionToSidecarDefinition(definition).inputSchema),
1369
1359
  examples: definition.examples?.map((example) => ({
1370
1360
  description: example.description,
1371
1361
  input: example.input,
1372
1362
  })) ?? [],
1373
1363
  };
1374
1364
  }
1375
- function bindingPermissionMode(permissions, callbackKey) {
1376
- const scope = permissions.binding;
1377
- if (!scope) {
1378
- return "deny";
1379
- }
1380
- if (typeof scope === "string") {
1381
- return scope;
1382
- }
1383
- let mode = scope.default ?? "deny";
1384
- for (const rule of scope.rules) {
1385
- const operations = rule.operations ?? ["*"];
1386
- const patterns = rule.patterns ?? ["**"];
1387
- if (operations.some((operation) => operation === "*" || operation === "invoke") &&
1388
- patterns.some((pattern) => permissionPatternMatches(pattern, callbackKey))) {
1389
- mode = rule.mode;
1390
- }
1391
- }
1392
- return mode;
1393
- }
1394
- function permissionPatternMatches(pattern, value) {
1395
- if (pattern === "*" || pattern === "**" || pattern === value) {
1396
- return true;
1397
- }
1398
- const parts = pattern.split(/(\*\*|\*)/u);
1399
- const source = parts
1400
- .map((part) => {
1401
- if (part === "**")
1402
- return ".*";
1403
- if (part === "*")
1404
- return "[^:]*";
1405
- return part.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
1406
- })
1407
- .join("");
1408
- return new RegExp(`^${source}$`).test(value);
1365
+ function hostFunctionsNames(hostFunctions) {
1366
+ return hostFunctions
1367
+ .map((hostFunctionCollection) => hostFunctionCollection.name)
1368
+ .join(", ");
1409
1369
  }
1410
- function bindingsNames(bindings) {
1411
- return bindings.map((bindingCollection) => bindingCollection.name).join(", ");
1412
- }
1413
- function bindingNames(bindingCollection) {
1414
- return Object.keys(bindingCollection.bindings).join(", ");
1370
+ function hostFunctionNames(hostFunctionCollection) {
1371
+ return Object.keys(hostFunctionCollection.functions).join(", ");
1415
1372
  }
1416
1373
  function isHelpFlag(value) {
1417
1374
  return value === "--help" || value === "-h";
@@ -1420,23 +1377,23 @@ function jsonSchemaType(schema) {
1420
1377
  const schemaObject = asRecord(schema);
1421
1378
  return typeof schemaObject.type === "string" ? schemaObject.type : undefined;
1422
1379
  }
1423
- async function registerBindingsOnSidecar(client, session, vm, bindings) {
1424
- if (bindings.length === 0) {
1380
+ async function registerHostFunctionsOnSidecar(client, session, vm, hostFunctions) {
1381
+ if (hostFunctions.length === 0) {
1425
1382
  return "";
1426
1383
  }
1427
- for (const bindingCollection of bindings) {
1384
+ for (const hostFunctionCollection of hostFunctions) {
1428
1385
  await client.registerHostCallbacks(session, vm, {
1429
- name: bindingCollection.name,
1430
- description: bindingCollection.description,
1431
- commandAliases: [`agentos-${bindingCollection.name}`],
1386
+ name: hostFunctionCollection.name,
1387
+ description: "",
1388
+ commandAliases: [`agentos-${hostFunctionCollection.name}`],
1432
1389
  registryCommandAliases: ["agentos"],
1433
- callbacks: Object.fromEntries(Object.entries(bindingCollection.bindings).map(([bindingName, definition]) => [
1434
- bindingName,
1435
- bindingToSidecarDefinition(definition),
1390
+ callbacks: Object.fromEntries(Object.entries(hostFunctionCollection.functions).map(([functionName, definition]) => [
1391
+ functionName,
1392
+ hostFunctionToSidecarDefinition(definition),
1436
1393
  ])),
1437
1394
  });
1438
1395
  }
1439
- return buildBindingReference(bindings);
1396
+ return buildHostFunctionReference(hostFunctions);
1440
1397
  }
1441
1398
  function executionIdentity(options) {
1442
1399
  return {
@@ -1654,9 +1611,8 @@ export class AgentOs {
1654
1611
  _acpTerminalCounter = 0;
1655
1612
  _softwareRoots;
1656
1613
  _cronManager;
1657
- _bindings = [];
1658
- _bindingReference = "";
1659
- _permissions = allowAll;
1614
+ _hostFunctions = [];
1615
+ _hostFunctionReference = "";
1660
1616
  _hostMounts;
1661
1617
  _env;
1662
1618
  _rootFilesystem;
@@ -1811,8 +1767,11 @@ export class AgentOs {
1811
1767
  static async getSharedSidecar(options = {}) {
1812
1768
  return getSharedAgentOsSidecarInternal(options);
1813
1769
  }
1814
- static async create(options) {
1815
- options = parseAgentOsOptions(options);
1770
+ static async create(callerOptions) {
1771
+ // The generic exists only so each `execute` infers its input from its own
1772
+ // `inputSchema`. Past this point the concrete schemas carry no meaning, so
1773
+ // the rest of `create()` works with the plain option type.
1774
+ let options = parseAgentOsOptions(callerOptions);
1816
1775
  // Default software is FULLY DYNAMIC: this package's own NON-agent
1817
1776
  // @agentos-software/* dependencies (e.g. common), each default-exporting
1818
1777
  // its registry-built descriptor. Agent packages are NOT projected here —
@@ -1847,27 +1806,29 @@ export class AgentOs {
1847
1806
  // sidecar owns agent resolution, agent enumeration, and agent snapshot
1848
1807
  // bundle loading from the projected package dirs.
1849
1808
  const localMounts = await resolveCompatLocalMounts(options?.mounts);
1850
- if (options?.bindings && options.bindings.length > 0) {
1851
- validateBindings(options.bindings);
1852
- }
1809
+ // Keys become command names, so resolve and check them before anything
1810
+ // else in `create()` allocates a sidecar or a sandbox.
1811
+ const resolvedHostFunctions = options?.hostFunctions
1812
+ ? resolveHostFunctions(options.hostFunctions)
1813
+ : [];
1853
1814
  // Resolve the sidecar handle before starting an external sandbox so option
1854
1815
  // validation failures cannot leak provider resources.
1855
1816
  const sidecar = resolveAgentOsSidecar(options?.sidecar);
1856
1817
  options = await resolveSandboxOptions(options);
1857
1818
  const sandboxDisposeHooks = getSandboxDisposeHooks(options);
1858
- const bindings = options.bindings;
1819
+ const hostFunctions = resolvedHostFunctions;
1859
1820
  const createVmAdmin = async () => {
1860
1821
  // The `/opt/agentos` projection is built by the sidecar from the
1861
1822
  // forwarded `packages` (it owns the staging dir + read-only mount, and
1862
1823
  // runtime `linkSoftware` appends to that live dir). The client no longer
1863
1824
  // stages packages host-side.
1864
- const bindingBootstrapCommands = collectBindingBootstrapCommands(bindings ?? []);
1825
+ const hostFunctionBootstrapCommands = collectHostFunctionBootstrapCommands(hostFunctions);
1865
1826
  const bootstrapCommands = [
1866
1827
  ...RUNTIME_BOOTSTRAP_COMMANDS,
1867
- ...bindingBootstrapCommands,
1828
+ ...hostFunctionBootstrapCommands,
1868
1829
  ];
1869
1830
  const bootstrapLower = createKernelBootstrapLower(options?.rootFilesystem);
1870
- let bindingReference = "";
1831
+ let hostFunctionReference = "";
1871
1832
  let rootBridge = null;
1872
1833
  let kernel = null;
1873
1834
  let client = null;
@@ -1884,7 +1845,7 @@ export class AgentOs {
1884
1845
  const env = getBaseEnvironment();
1885
1846
  // Guest command paths. The sidecar owns the `/opt/agentos` projection and
1886
1847
  // reports the exact projected package commands after `configureVm`.
1887
- // Binding-shim commands are added below.
1848
+ // HostFunction-shim commands are added below.
1888
1849
  const commandGuestPaths = new Map();
1889
1850
  const { sidecarMounts, hostMounts, hostPathMappings } = collectSidecarMountPlan({
1890
1851
  mounts: options?.mounts,
@@ -1895,11 +1856,7 @@ export class AgentOs {
1895
1856
  client = shared.client;
1896
1857
  const session = shared.session;
1897
1858
  nativeSession = session;
1898
- const hostPermissions = options?.permissions ?? {
1899
- ...allowAll,
1900
- binding: "allow",
1901
- };
1902
- const sidecarPermissions = serializePermissionsForSidecar(hostPermissions);
1859
+ const sidecarPermissions = serializePermissionsForSidecar(options?.permissions);
1903
1860
  const createVmConfig = {
1904
1861
  env,
1905
1862
  database: options?.database,
@@ -1960,16 +1917,16 @@ export class AgentOs {
1960
1917
  loopbackExemptPorts: options?.loopbackExemptPorts,
1961
1918
  packages: sidecarPackages,
1962
1919
  packagesMountAt: OPT_AGENTOS_ROOT,
1963
- bindingShimCommands: bindingBootstrapCommands,
1920
+ hostFunctionShimCommands: hostFunctionBootstrapCommands,
1964
1921
  });
1965
1922
  for (const command of configuredVm.projectedCommands) {
1966
1923
  commandGuestPaths.set(command.name, command.guestPath);
1967
1924
  }
1968
- if (bindings && bindings.length > 0) {
1969
- bindingReference = await registerBindingsOnSidecar(client, session, nativeVm, bindings);
1925
+ if (hostFunctions.length > 0) {
1926
+ hostFunctionReference = await registerHostFunctionsOnSidecar(client, session, nativeVm, hostFunctions);
1970
1927
  commandGuestPaths.set("agentos", "/bin/agentos");
1971
- for (const bindingCollection of bindings) {
1972
- commandGuestPaths.set(`agentos-${bindingCollection.name}`, `/bin/agentos-${bindingCollection.name}`);
1928
+ for (const hostFunctionCollection of hostFunctions) {
1929
+ commandGuestPaths.set(`agentos-${hostFunctionCollection.name}`, `/bin/agentos-${hostFunctionCollection.name}`);
1973
1930
  }
1974
1931
  }
1975
1932
  rootBridge = new NativeSidecarKernelProxy({
@@ -1985,10 +1942,10 @@ export class AgentOs {
1985
1942
  loopbackExemptPorts: options?.loopbackExemptPorts,
1986
1943
  // Retained for runtime mount reconfigures: `configure_vm` is
1987
1944
  // replace-on-write for the whole payload, so post-boot mountFs
1988
- // must resend the boot packages and binding shims.
1945
+ // must resend the boot packages and host-function shims.
1989
1946
  packages: sidecarPackages,
1990
1947
  packagesMountAt: OPT_AGENTOS_ROOT,
1991
- bindingShimCommands: bindingBootstrapCommands,
1948
+ hostFunctionShimCommands: hostFunctionBootstrapCommands,
1992
1949
  commandGuestPaths,
1993
1950
  onDispose: cleanup,
1994
1951
  // The native process is owned by the AgentOsSidecar handle and
@@ -2012,10 +1969,9 @@ export class AgentOs {
2012
1969
  sidecarClient: client,
2013
1970
  sidecarSession: session,
2014
1971
  sidecarVm: nativeVm,
2015
- permissions: hostPermissions,
2016
1972
  snapshotRootFilesystem: async (maxBytes) => createSnapshotExport(convertSidecarRootSnapshotEntries(await snapshotClient.snapshotRootFilesystem(session, nativeVm, maxBytes))),
2017
- bindings: bindings ?? [],
2018
- bindingReference,
1973
+ hostFunctions,
1974
+ hostFunctionReference,
2019
1975
  async dispose() {
2020
1976
  if (kernel) {
2021
1977
  const currentKernel = kernel;
@@ -2060,9 +2016,8 @@ export class AgentOs {
2060
2016
  const vmAdmin = sidecarLease.admin;
2061
2017
  const vm = new AgentOs(vmAdmin.kernel, sidecar, [], vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm, options?.onAgentStderr ?? defaultAgentStderrHandler, options?.onAgentExit ?? defaultAgentExitHandler, options?.onLimitWarning);
2062
2018
  vm._sidecarLease = sidecarLease;
2063
- vm._bindings = vmAdmin.bindings;
2064
- vm._bindingReference = vmAdmin.bindingReference;
2065
- vm._permissions = vmAdmin.permissions;
2019
+ vm._hostFunctions = vmAdmin.hostFunctions;
2020
+ vm._hostFunctionReference = vmAdmin.hostFunctionReference;
2066
2021
  vm._disposeHooks.push(...sandboxDisposeHooks);
2067
2022
  vm._installSidecarRequestHandler();
2068
2023
  vm._cronManager = new CronManager(vm, options?.scheduleDriver ?? new TimerScheduleDriver());
@@ -3568,7 +3523,7 @@ export class AgentOs {
3568
3523
  : JSON.stringify(input.mcpServers),
3569
3524
  permissionPolicy: input.permissionPolicy ?? null,
3570
3525
  skipOsInstructions: input.skipOsInstructions ?? null,
3571
- additionalInstructions: combineInstructions(input.additionalInstructions, this._bindingReference) ?? null,
3526
+ additionalInstructions: combineInstructions(input.additionalInstructions, this._hostFunctionReference) ?? null,
3572
3527
  },
3573
3528
  });
3574
3529
  if (response.tag !== "AcpOpenSessionResponse") {
@@ -4089,9 +4044,8 @@ export class AgentOs {
4089
4044
  }
4090
4045
  _installSidecarRequestHandler() {
4091
4046
  const context = {
4092
- bindings: this._bindings,
4093
- bindingMap: buildBindingMap(this._bindings),
4094
- permissions: this._permissions,
4047
+ hostFunctions: this._hostFunctions,
4048
+ hostFunctionMap: buildHostFunctionMap(this._hostFunctions),
4095
4049
  readFile: (path) => this.readFile(path),
4096
4050
  };
4097
4051
  this._sidecarClient.setSidecarRequestHandler((request) => {