@rivet-dev/agentos-runtime-core 0.2.20 → 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.
@@ -85,6 +85,21 @@ const SIDECAR_BUILD_INPUTS = [
85
85
  path.join(REPO_ROOT, "pnpm-lock.yaml"),
86
86
  ];
87
87
  let ensuredSidecarBinary = null;
88
+ /**
89
+ * A host-side function that guest code can invoke as a shell command. The guest
90
+ * runs the host function by name and the invocation round-trips back to the host JS
91
+ * `handler`, whose return value is passed back to the guest. Host functions never run
92
+ * inside the guest: they execute on the host, so they are the bridge for giving
93
+ * sandboxed guest code controlled, named capabilities (the kind AI agents call
94
+ * as tools).
95
+ */
96
+ import { hostFunctionDescription, resolveHostFunctions, } from "./host-functions.js";
97
+ import { zodToJsonSchema } from "./host-functions-zod.js";
98
+ /** The description the agent sees, taken from the input schema. */
99
+ function jsonSchemaDescription(inputSchema) {
100
+ const description = inputSchema.description;
101
+ return typeof description === "string" ? description : "";
102
+ }
88
103
  export class KernelError extends Error {
89
104
  code;
90
105
  constructor(code, message) {
@@ -677,7 +692,7 @@ function normalizePermissionsPolicy(permissions) {
677
692
  childProcess: normalizePatternPermissionScope(permissions.childProcess),
678
693
  process: normalizePatternPermissionScope(permissions.process),
679
694
  env: normalizePatternPermissionScope(permissions.env),
680
- binding: normalizePatternPermissionScope(permissions.binding),
695
+ hostFunction: normalizePatternPermissionScope(permissions.hostFunction),
681
696
  };
682
697
  }
683
698
  export function filterEnv(env, permissions) {
@@ -1788,11 +1803,11 @@ class NativeKernel {
1788
1803
  mountedRuntimeDrivers = [];
1789
1804
  runtimeDriverCommandDirStarts = new Map();
1790
1805
  loopbackExemptPorts;
1791
- // Bindings registered with the VM, keyed by the callback key the sidecar
1792
- // sends back on a host_callback request (the binding name). Installed lazily
1793
- // on the first registerBindings call.
1794
- bindingHandlers = new Map();
1795
- bindingRequestHandlerInstalled = false;
1806
+ // Host functions registered with the VM, keyed by the callback key the sidecar
1807
+ // sends back on a host_callback request (the host-function name). Installed lazily
1808
+ // on the first registerHostFunctions call.
1809
+ hostFunctionHandlers = new Map();
1810
+ hostFunctionRequestHandlerInstalled = false;
1796
1811
  constructor(options) {
1797
1812
  this.options = options;
1798
1813
  this.env = { ...(options.env ?? {}) };
@@ -2017,7 +2032,7 @@ class NativeKernel {
2017
2032
  await this.ensureReady();
2018
2033
  return this.proxy.vmFetch(request);
2019
2034
  }
2020
- async registerBindings(bindings) {
2035
+ async registerHostFunctions(hostFunctions) {
2021
2036
  await this.ensureReady();
2022
2037
  if (!this.client || !this.session || !this.vm) {
2023
2038
  throw new Error("kernel is not ready");
@@ -2025,64 +2040,58 @@ class NativeKernel {
2025
2040
  // Install the dispatcher once. It routes every host_callback request the
2026
2041
  // sidecar emits to the matching registered handler and replies with a
2027
2042
  // host_callback_result frame.
2028
- if (!this.bindingRequestHandlerInstalled) {
2029
- this.client.setSidecarRequestHandler((request) => this.dispatchBindingRequest(request));
2030
- this.bindingRequestHandlerInstalled = true;
2031
- }
2032
- for (const [name, binding] of Object.entries(bindings)) {
2033
- this.bindingHandlers.set(name, binding.handler);
2034
- const definition = {
2035
- description: binding.description,
2036
- inputSchema: binding.inputSchema,
2037
- ...(binding.timeoutMs !== undefined
2038
- ? { timeoutMs: binding.timeoutMs }
2039
- : {}),
2040
- ...(binding.examples && binding.examples.length > 0
2041
- ? {
2042
- examples: binding.examples.map((example) => ({
2043
- description: example.description,
2044
- input: example.input,
2045
- })),
2046
- }
2047
- : {}),
2048
- };
2049
- // Register each binding as its own single-callback binding collection so the guest
2050
- // can invoke it directly by name (or by any caller-provided alias). The
2051
- // sidecar exposes the binding collection name as a guest command; the single
2052
- // callback carries the binding's schema and gates the `binding`
2053
- // permission.
2043
+ if (!this.hostFunctionRequestHandlerInstalled) {
2044
+ this.client.setSidecarRequestHandler((request) => this.dispatchHostFunctionRequest(request));
2045
+ this.hostFunctionRequestHandlerInstalled = true;
2046
+ }
2047
+ for (const collection of resolveHostFunctions(hostFunctions)) {
2048
+ const callbacks = {};
2049
+ for (const [functionName, definition] of Object.entries(collection.functions)) {
2050
+ this.hostFunctionHandlers.set(`${collection.name}:${functionName}`, definition.execute);
2051
+ callbacks[functionName] = {
2052
+ description: hostFunctionDescription(definition),
2053
+ inputSchema: zodToJsonSchema(definition.inputSchema),
2054
+ ...(definition.timeout !== undefined
2055
+ ? { timeoutMs: definition.timeout }
2056
+ : {}),
2057
+ ...(definition.examples && definition.examples.length > 0
2058
+ ? {
2059
+ examples: definition.examples.map((example) => ({
2060
+ description: example.description,
2061
+ input: example.input,
2062
+ })),
2063
+ }
2064
+ : {}),
2065
+ };
2066
+ }
2067
+ // One registration per collection, exposed to the guest as the command
2068
+ // `agentos-<collection>` with each function as a subcommand. This is the
2069
+ // same shape `AgentOs.create()` registers.
2070
+ const command = `agentos-${collection.name}`;
2054
2071
  await this.client.registerHostCallbacks(this.session, this.vm, {
2055
- name,
2056
- description: binding.description,
2057
- commandAliases: [name, ...(binding.commandAliases ?? [])],
2058
- callbacks: { [name]: definition },
2072
+ name: collection.name,
2073
+ description: "",
2074
+ commandAliases: [command],
2075
+ registryCommandAliases: ["agentos"],
2076
+ callbacks,
2059
2077
  });
2060
- this.commands.set(name, "wasmvm");
2061
- for (const alias of binding.commandAliases ?? []) {
2062
- this.commands.set(alias, "wasmvm");
2063
- }
2078
+ this.commands.set(command, "wasmvm");
2064
2079
  }
2065
2080
  }
2066
- async dispatchBindingRequest(request) {
2081
+ async dispatchHostFunctionRequest(request) {
2067
2082
  const { payload } = request;
2068
2083
  if (payload.type !== "host_callback") {
2069
- throw new Error(`unsupported sidecar request for bindings: ${payload.type}`);
2084
+ throw new Error(`unsupported sidecar request for host functions: ${payload.type}`);
2070
2085
  }
2071
- // Callback keys arrive as `${collection}:${binding}` for collection invocations
2072
- // and as the bare command name otherwise. The collection and binding name are
2073
- // the same here, so the registered binding name is the segment after the last
2074
- // colon (or the whole key when no colon is present).
2086
+ // Callback keys arrive as `<collection>:<function>`, the key each handler
2087
+ // was registered under.
2075
2088
  const callbackKey = payload.callback_key;
2076
- const bindingName = callbackKey.includes(":")
2077
- ? callbackKey.slice(callbackKey.lastIndexOf(":") + 1)
2078
- : callbackKey;
2079
- const handler = this.bindingHandlers.get(bindingName) ??
2080
- this.bindingHandlers.get(callbackKey);
2089
+ const handler = this.hostFunctionHandlers.get(callbackKey);
2081
2090
  if (!handler) {
2082
2091
  return {
2083
2092
  type: "host_callback_result",
2084
2093
  invocation_id: payload.invocation_id,
2085
- error: `no binding registered for ${callbackKey}`,
2094
+ error: `no host function registered for ${callbackKey}`,
2086
2095
  };
2087
2096
  }
2088
2097
  try {
@@ -28,7 +28,7 @@ export type { RootFilesystemEntryEncoding } from "./generated/RootFilesystemEntr
28
28
  export type { RootFilesystemEntryKind } from "./generated/RootFilesystemEntryKind.js";
29
29
  export type { RootFilesystemLowerDescriptor } from "./generated/RootFilesystemLowerDescriptor.js";
30
30
  export type { RootFilesystemMode } from "./generated/RootFilesystemMode.js";
31
- export type { BindingLimitsConfig } from "./generated/BindingLimitsConfig.js";
31
+ export type { HostFunctionLimitsConfig } from "./generated/HostFunctionLimitsConfig.js";
32
32
  export type { VmDnsConfig } from "./generated/VmDnsConfig.js";
33
33
  export type { VmLimitsConfig } from "./generated/VmLimitsConfig.js";
34
34
  export type { VmListenPolicyConfig } from "./generated/VmListenPolicyConfig.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivet-dev/agentos-runtime-core",
3
- "version": "0.2.20",
3
+ "version": "0.2.21",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -21,6 +21,16 @@
21
21
  "import": "./dist/generated-protocol.js",
22
22
  "default": "./dist/generated-protocol.js"
23
23
  },
24
+ "./host-functions": {
25
+ "types": "./dist/host-functions.d.ts",
26
+ "import": "./dist/host-functions.js",
27
+ "default": "./dist/host-functions.js"
28
+ },
29
+ "./host-functions-zod": {
30
+ "types": "./dist/host-functions-zod.d.ts",
31
+ "import": "./dist/host-functions-zod.js",
32
+ "default": "./dist/host-functions-zod.js"
33
+ },
24
34
  "./vm-config": {
25
35
  "types": "./dist/vm-config.d.ts",
26
36
  "import": "./dist/vm-config.js",
@@ -197,9 +207,10 @@
197
207
  "test:npm-workflows": "AGENTOS_NPM_WORKFLOWS_E2E=1 vitest run tests/integration/e2e-npm-*.nightly.test.ts tests/integration/e2e-npx-and-pipes.nightly.test.ts tests/integration/e2e-concurrently.nightly.test.ts tests/integration/e2e-nextjs-build.nightly.test.ts --reporter=verbose"
198
208
  },
199
209
  "dependencies": {
200
- "@rivet-dev/agentos-runtime-sidecar": "0.2.20",
210
+ "@rivet-dev/agentos-runtime-sidecar": "0.2.21",
201
211
  "@rivetkit/bare-ts": "^0.6.2",
202
- "zod": "^4.1.11"
212
+ "zod": "^4.1.11",
213
+ "zod-to-json-schema": "^3.25.2"
203
214
  },
204
215
  "devDependencies": {
205
216
  "@types/node": "^22.10.2",
@@ -1,10 +0,0 @@
1
- export type BindingLimitsConfig = {
2
- defaultBindingTimeoutMs?: number;
3
- maxBindingTimeoutMs?: number;
4
- maxRegisteredCollections?: number;
5
- maxRegisteredBindingsPerVm?: number;
6
- maxBindingsPerCollection?: number;
7
- maxBindingSchemaBytes?: number;
8
- maxExamplesPerBinding?: number;
9
- maxBindingExampleInputBytes?: number;
10
- };