@rivet-dev/agentos-core 0.0.0-nathan-binding-workspace.4640d5c → 0.0.0-nathan-binding-workspace.abc7ec9
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 +13 -13
- package/dist/{agentos.d.ts → agent-os.d.ts} +85 -30
- package/dist/{agentos.js → agent-os.js} +185 -126
- package/dist/agents.d.ts +1 -1
- package/dist/agents.js +5 -5
- 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/{bindings-zod.d.ts → host-tools-zod.d.ts} +1 -1
- package/dist/{bindings-zod.js → host-tools-zod.js} +16 -16
- package/dist/host-tools.d.ts +45 -0
- package/dist/host-tools.js +26 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/json-rpc.d.ts +17 -1
- package/dist/json-rpc.js +8 -0
- package/dist/packages.js +1 -1
- package/dist/runtime-compat.d.ts +2 -2
- package/dist/runtime-compat.js +5 -6
- package/dist/runtime.d.ts +2 -2
- package/dist/sidecar/agentos-protocol.d.ts +36 -0
- package/dist/sidecar/agentos-protocol.js +41 -1
- package/dist/sidecar/native-process-client.d.ts +2 -2
- package/dist/sidecar/native-process-client.js +1 -1
- package/dist/sidecar/permissions.js +3 -3
- 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 +8 -8
- package/dist/bindings.d.ts +0 -45
- package/dist/bindings.js +0 -26
|
@@ -4,14 +4,22 @@ 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 { validateToolkits } from "./host-tools.js";
|
|
8
|
+
import { zodToJsonSchema } from "./host-tools-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.agent-os.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";
|
|
15
23
|
function defaultAcpClientCapabilities() {
|
|
16
24
|
return {
|
|
17
25
|
fs: {
|
|
@@ -41,15 +49,10 @@ import { createHostDirBackend } from "./host-dir-mount.js";
|
|
|
41
49
|
import { serializeMountConfigForSidecar, } from "./js-bridge.js";
|
|
42
50
|
import { createSnapshotExport, } from "./layers.js";
|
|
43
51
|
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";
|
|
49
52
|
import { allowAll } from "./runtime-compat.js";
|
|
50
53
|
import { AcpRuntimeKind, decodeAcpCallback, decodeAcpEvent, decodeAcpResponse, encodeAcpCallbackResponse, encodeAcpRequest, } from "./sidecar/agentos-protocol.js";
|
|
51
54
|
import { serializePermissionsForSidecar } from "./sidecar/permissions.js";
|
|
52
|
-
import {
|
|
55
|
+
import { createAgentOsSidecarClient, NATIVE_SIDECAR_FRAME_TIMEOUT_MS, NativeSidecarKernelProxy, SidecarProcess, serializeRootFilesystemForSidecar, } from "./sidecar/rpc-client.js";
|
|
53
56
|
const LEGACY_PERMISSION_METHOD = "request/permission";
|
|
54
57
|
const ACP_PERMISSION_METHOD = "session/request_permission";
|
|
55
58
|
class AcpDispatchError extends Error {
|
|
@@ -364,7 +367,6 @@ const KERNEL_POSIX_BOOTSTRAP_DIRS = [
|
|
|
364
367
|
"/media",
|
|
365
368
|
"/home",
|
|
366
369
|
"/home/user",
|
|
367
|
-
"/workspace",
|
|
368
370
|
"/usr",
|
|
369
371
|
"/usr/bin",
|
|
370
372
|
"/usr/games",
|
|
@@ -832,19 +834,19 @@ function collectSidecarMountPlan(options) {
|
|
|
832
834
|
hostPathMappings.sort((left, right) => right.vmPath.length - left.vmPath.length);
|
|
833
835
|
return { sidecarMounts, hostMounts, hostPathMappings };
|
|
834
836
|
}
|
|
835
|
-
function materializeToolShimDir(
|
|
836
|
-
const shimDir = mkdtempSync(join(tmpdir(), "agentos-
|
|
837
|
+
function materializeToolShimDir(toolKits) {
|
|
838
|
+
const shimDir = mkdtempSync(join(tmpdir(), "agentos-host-tools-shims-"));
|
|
837
839
|
writeFileSync(join(shimDir, "agentos"), KERNEL_COMMAND_STUB, { mode: 0o755 });
|
|
838
|
-
for (const
|
|
839
|
-
writeFileSync(join(shimDir, `agentos-${
|
|
840
|
+
for (const toolKit of toolKits) {
|
|
841
|
+
writeFileSync(join(shimDir, `agentos-${toolKit.name}`), KERNEL_COMMAND_STUB, { mode: 0o755 });
|
|
840
842
|
}
|
|
841
843
|
return shimDir;
|
|
842
844
|
}
|
|
843
|
-
function collectToolkitBootstrapCommands(
|
|
844
|
-
if (
|
|
845
|
+
function collectToolkitBootstrapCommands(toolKits) {
|
|
846
|
+
if (toolKits.length === 0) {
|
|
845
847
|
return [];
|
|
846
848
|
}
|
|
847
|
-
return ["agentos", ...
|
|
849
|
+
return ["agentos", ...toolKits.map((toolKit) => `agentos-${toolKit.name}`)];
|
|
848
850
|
}
|
|
849
851
|
function validationMessage(error) {
|
|
850
852
|
if (typeof error === "object" &&
|
|
@@ -886,42 +888,42 @@ function combineInstructions(additionalInstructions, toolReference) {
|
|
|
886
888
|
}
|
|
887
889
|
return parts.join("\n\n");
|
|
888
890
|
}
|
|
889
|
-
function buildHostToolReference(
|
|
890
|
-
if (
|
|
891
|
+
function buildHostToolReference(toolKits) {
|
|
892
|
+
if (toolKits.length === 0) {
|
|
891
893
|
return "";
|
|
892
894
|
}
|
|
893
895
|
const lines = [
|
|
894
|
-
"## Available
|
|
896
|
+
"## Available Host Tools",
|
|
895
897
|
"",
|
|
896
|
-
"Run `agentos list-tools` to see all available
|
|
898
|
+
"Run `agentos list-tools` to see all available tools.",
|
|
897
899
|
"",
|
|
898
900
|
];
|
|
899
|
-
for (const
|
|
900
|
-
lines.push(`### ${
|
|
901
|
+
for (const toolKit of toolKits) {
|
|
902
|
+
lines.push(`### ${toolKit.name}`);
|
|
901
903
|
lines.push("");
|
|
902
|
-
lines.push(
|
|
904
|
+
lines.push(toolKit.description);
|
|
903
905
|
lines.push("");
|
|
904
|
-
for (const [
|
|
906
|
+
for (const [toolName, tool] of Object.entries(toolKit.tools)) {
|
|
905
907
|
const sidecarTool = toolToSidecarDefinition(tool);
|
|
906
908
|
const signature = buildToolFlagSignature(sidecarTool.inputSchema);
|
|
907
909
|
const suffix = signature.length > 0 ? ` ${signature}` : "";
|
|
908
|
-
lines.push(`- \`agentos-${
|
|
910
|
+
lines.push(`- \`agentos-${toolKit.name} ${toolName}${suffix}\` — ${tool.description}`);
|
|
909
911
|
}
|
|
910
912
|
lines.push("");
|
|
911
|
-
const toolsWithExamples = Object.entries(
|
|
913
|
+
const toolsWithExamples = Object.entries(toolKit.tools).filter(([, tool]) => tool.examples && tool.examples.length > 0);
|
|
912
914
|
if (toolsWithExamples.length > 0) {
|
|
913
915
|
lines.push("**Examples:**");
|
|
914
916
|
lines.push("");
|
|
915
|
-
for (const [
|
|
917
|
+
for (const [toolName, tool] of toolsWithExamples) {
|
|
916
918
|
for (const example of tool.examples ?? []) {
|
|
917
919
|
const args = inputToToolFlags(example.input);
|
|
918
920
|
const suffix = args.length > 0 ? ` ${args}` : "";
|
|
919
|
-
lines.push(`- ${example.description}: \`agentos-${
|
|
921
|
+
lines.push(`- ${example.description}: \`agentos-${toolKit.name} ${toolName}${suffix}\``);
|
|
920
922
|
}
|
|
921
923
|
}
|
|
922
924
|
lines.push("");
|
|
923
925
|
}
|
|
924
|
-
lines.push(`Run \`agentos-${
|
|
926
|
+
lines.push(`Run \`agentos-${toolKit.name} <tool> --help\` for details.`);
|
|
925
927
|
lines.push("");
|
|
926
928
|
}
|
|
927
929
|
return lines.join("\n");
|
|
@@ -1062,11 +1064,11 @@ async function handleHostCallback(request, context) {
|
|
|
1062
1064
|
};
|
|
1063
1065
|
}
|
|
1064
1066
|
}
|
|
1065
|
-
function buildToolMap(
|
|
1067
|
+
function buildToolMap(toolKits) {
|
|
1066
1068
|
const toolMap = new Map();
|
|
1067
|
-
for (const
|
|
1068
|
-
for (const [
|
|
1069
|
-
toolMap.set(`${
|
|
1069
|
+
for (const toolKit of toolKits) {
|
|
1070
|
+
for (const [toolName, tool] of Object.entries(toolKit.tools)) {
|
|
1071
|
+
toolMap.set(`${toolKit.name}:${toolName}`, tool);
|
|
1070
1072
|
}
|
|
1071
1073
|
}
|
|
1072
1074
|
return toolMap;
|
|
@@ -1088,33 +1090,33 @@ function parseHostCommandCallbackInput(input) {
|
|
|
1088
1090
|
};
|
|
1089
1091
|
}
|
|
1090
1092
|
async function handleHostCommandCallback(command, context) {
|
|
1091
|
-
const directToolKit = context.
|
|
1093
|
+
const directToolKit = context.toolKits.find((toolKit) => `agentos-${toolKit.name}` === command.command);
|
|
1092
1094
|
if (command.command === "agentos") {
|
|
1093
|
-
return
|
|
1095
|
+
return handleAgentOsRegistryCommand(command, context);
|
|
1094
1096
|
}
|
|
1095
1097
|
if (directToolKit) {
|
|
1096
|
-
return
|
|
1098
|
+
return handleAgentOsToolkitCommand(command, context, directToolKit);
|
|
1097
1099
|
}
|
|
1098
1100
|
throw new Error(`Unknown host callback command "${command.command}"`);
|
|
1099
1101
|
}
|
|
1100
|
-
async function
|
|
1102
|
+
async function handleAgentOsRegistryCommand(command, context) {
|
|
1101
1103
|
const [subcommand, toolkitName, toolName, ...toolArgs] = command.args;
|
|
1102
1104
|
if (!subcommand || isHelpFlag(subcommand)) {
|
|
1103
1105
|
return {
|
|
1104
|
-
usage: "agentos <command>: list-tools [
|
|
1106
|
+
usage: "agentos <command>: list-tools [toolkit], <toolkit> --help, or <toolkit> <tool> ...",
|
|
1105
1107
|
};
|
|
1106
1108
|
}
|
|
1107
1109
|
if (subcommand === "list-tools") {
|
|
1108
1110
|
return toolkitName
|
|
1109
|
-
? describeToolkitPayload(context.
|
|
1110
|
-
: listToolkitsPayload(context.
|
|
1111
|
+
? describeToolkitPayload(context.toolKits, toolkitName)
|
|
1112
|
+
: listToolkitsPayload(context.toolKits);
|
|
1111
1113
|
}
|
|
1112
|
-
const toolKit = context.
|
|
1114
|
+
const toolKit = context.toolKits.find((kit) => kit.name === subcommand);
|
|
1113
1115
|
if (!toolKit) {
|
|
1114
|
-
throw new Error(`No
|
|
1116
|
+
throw new Error(`No toolkit "${subcommand}". Available: ${toolkitNames(context.toolKits)}`);
|
|
1115
1117
|
}
|
|
1116
1118
|
if (!toolkitName || isHelpFlag(toolkitName)) {
|
|
1117
|
-
return describeToolkitPayload(context.
|
|
1119
|
+
return describeToolkitPayload(context.toolKits, subcommand);
|
|
1118
1120
|
}
|
|
1119
1121
|
if (toolName && isHelpFlag(toolName)) {
|
|
1120
1122
|
return describeToolPayload(toolKit, toolkitName);
|
|
@@ -1127,10 +1129,10 @@ async function handleAgentOSRegistryCommand(command, context) {
|
|
|
1127
1129
|
context,
|
|
1128
1130
|
});
|
|
1129
1131
|
}
|
|
1130
|
-
async function
|
|
1132
|
+
async function handleAgentOsToolkitCommand(command, context, toolKit) {
|
|
1131
1133
|
const [toolName, helpOrFirstArg, ...rest] = command.args;
|
|
1132
1134
|
if (!toolName || isHelpFlag(toolName)) {
|
|
1133
|
-
return describeToolkitPayload(context.
|
|
1135
|
+
return describeToolkitPayload(context.toolKits, toolKit.name);
|
|
1134
1136
|
}
|
|
1135
1137
|
if (helpOrFirstArg && isHelpFlag(helpOrFirstArg)) {
|
|
1136
1138
|
return describeToolPayload(toolKit, toolName);
|
|
@@ -1144,14 +1146,14 @@ async function handleAgentOSToolkitCommand(command, context, toolKit) {
|
|
|
1144
1146
|
});
|
|
1145
1147
|
}
|
|
1146
1148
|
async function invokeHostTool({ toolKit, toolName, args, cwd, context, }) {
|
|
1147
|
-
const tool = toolKit.
|
|
1149
|
+
const tool = toolKit.tools[toolName];
|
|
1148
1150
|
if (!tool) {
|
|
1149
|
-
throw new Error(`No
|
|
1151
|
+
throw new Error(`No tool "${toolName}" in toolkit "${toolKit.name}". Available: ${toolNames(toolKit)}`);
|
|
1150
1152
|
}
|
|
1151
1153
|
const callbackKey = `${toolKit.name}:${toolName}`;
|
|
1152
1154
|
const permissionMode = toolPermissionMode(context.permissions, callbackKey);
|
|
1153
1155
|
if (permissionMode !== "allow") {
|
|
1154
|
-
throw new Error(`EACCES: blocked by
|
|
1156
|
+
throw new Error(`EACCES: blocked by tool.invoke policy for ${callbackKey}`);
|
|
1155
1157
|
}
|
|
1156
1158
|
const input = await parseHostToolInput(tool, args, cwd, context.readFile);
|
|
1157
1159
|
return executeHostTool(tool, callbackKey, input);
|
|
@@ -1264,25 +1266,25 @@ function parseToolArgv(schema, argv) {
|
|
|
1264
1266
|
}
|
|
1265
1267
|
return input;
|
|
1266
1268
|
}
|
|
1267
|
-
function listToolkitsPayload(
|
|
1269
|
+
function listToolkitsPayload(toolKits) {
|
|
1268
1270
|
return {
|
|
1269
|
-
|
|
1270
|
-
name:
|
|
1271
|
-
description:
|
|
1272
|
-
|
|
1271
|
+
toolkits: toolKits.map((toolKit) => ({
|
|
1272
|
+
name: toolKit.name,
|
|
1273
|
+
description: toolKit.description,
|
|
1274
|
+
tools: Object.keys(toolKit.tools),
|
|
1273
1275
|
})),
|
|
1274
1276
|
};
|
|
1275
1277
|
}
|
|
1276
|
-
function describeToolkitPayload(
|
|
1277
|
-
const toolKit =
|
|
1278
|
+
function describeToolkitPayload(toolKits, toolkitName) {
|
|
1279
|
+
const toolKit = toolKits.find((kit) => kit.name === toolkitName);
|
|
1278
1280
|
if (!toolKit) {
|
|
1279
|
-
throw new Error(`No
|
|
1281
|
+
throw new Error(`No toolkit "${toolkitName}". Available: ${toolkitNames(toolKits)}`);
|
|
1280
1282
|
}
|
|
1281
1283
|
return {
|
|
1282
1284
|
name: toolKit.name,
|
|
1283
1285
|
description: toolKit.description,
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
+
tools: Object.fromEntries(Object.entries(toolKit.tools).map(([toolName, tool]) => [
|
|
1287
|
+
toolName,
|
|
1286
1288
|
{
|
|
1287
1289
|
description: tool.description,
|
|
1288
1290
|
flags: describeToolFlags(toolToSidecarDefinition(tool).inputSchema),
|
|
@@ -1291,13 +1293,13 @@ function describeToolkitPayload(bindingGroups, toolkitName) {
|
|
|
1291
1293
|
};
|
|
1292
1294
|
}
|
|
1293
1295
|
function describeToolPayload(toolKit, toolName) {
|
|
1294
|
-
const tool = toolKit.
|
|
1296
|
+
const tool = toolKit.tools[toolName];
|
|
1295
1297
|
if (!tool) {
|
|
1296
|
-
throw new Error(`No
|
|
1298
|
+
throw new Error(`No tool "${toolName}" in toolkit "${toolKit.name}". Available: ${toolNames(toolKit)}`);
|
|
1297
1299
|
}
|
|
1298
1300
|
return {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
+
toolkit: toolKit.name,
|
|
1302
|
+
tool: toolName,
|
|
1301
1303
|
description: tool.description,
|
|
1302
1304
|
flags: describeToolFlags(toolToSidecarDefinition(tool).inputSchema),
|
|
1303
1305
|
examples: tool.examples?.map((example) => ({
|
|
@@ -1307,7 +1309,7 @@ function describeToolPayload(toolKit, toolName) {
|
|
|
1307
1309
|
};
|
|
1308
1310
|
}
|
|
1309
1311
|
function toolPermissionMode(permissions, callbackKey) {
|
|
1310
|
-
const scope = permissions.
|
|
1312
|
+
const scope = permissions.tool;
|
|
1311
1313
|
if (!scope) {
|
|
1312
1314
|
return "deny";
|
|
1313
1315
|
}
|
|
@@ -1341,11 +1343,11 @@ function permissionPatternMatches(pattern, value) {
|
|
|
1341
1343
|
.join("");
|
|
1342
1344
|
return new RegExp(`^${source}$`).test(value);
|
|
1343
1345
|
}
|
|
1344
|
-
function toolkitNames(
|
|
1345
|
-
return
|
|
1346
|
+
function toolkitNames(toolKits) {
|
|
1347
|
+
return toolKits.map((toolKit) => toolKit.name).join(", ");
|
|
1346
1348
|
}
|
|
1347
1349
|
function toolNames(toolKit) {
|
|
1348
|
-
return Object.keys(toolKit.
|
|
1350
|
+
return Object.keys(toolKit.tools).join(", ");
|
|
1349
1351
|
}
|
|
1350
1352
|
function isHelpFlag(value) {
|
|
1351
1353
|
return value === "--help" || value === "-h";
|
|
@@ -1354,25 +1356,25 @@ function jsonSchemaType(schema) {
|
|
|
1354
1356
|
const schemaObject = asRecord(schema);
|
|
1355
1357
|
return typeof schemaObject.type === "string" ? schemaObject.type : undefined;
|
|
1356
1358
|
}
|
|
1357
|
-
async function registerToolkitsOnSidecar(client, session, vm,
|
|
1358
|
-
if (
|
|
1359
|
+
async function registerToolkitsOnSidecar(client, session, vm, toolKits) {
|
|
1360
|
+
if (toolKits.length === 0) {
|
|
1359
1361
|
return "";
|
|
1360
1362
|
}
|
|
1361
|
-
for (const
|
|
1363
|
+
for (const toolKit of toolKits) {
|
|
1362
1364
|
await client.registerHostCallbacks(session, vm, {
|
|
1363
|
-
name:
|
|
1364
|
-
description:
|
|
1365
|
-
commandAliases: [`agentos-${
|
|
1365
|
+
name: toolKit.name,
|
|
1366
|
+
description: toolKit.description,
|
|
1367
|
+
commandAliases: [`agentos-${toolKit.name}`],
|
|
1366
1368
|
registryCommandAliases: ["agentos"],
|
|
1367
|
-
callbacks: Object.fromEntries(Object.entries(
|
|
1368
|
-
|
|
1369
|
+
callbacks: Object.fromEntries(Object.entries(toolKit.tools).map(([toolName, tool]) => [
|
|
1370
|
+
toolName,
|
|
1369
1371
|
toolToSidecarDefinition(tool),
|
|
1370
1372
|
])),
|
|
1371
1373
|
});
|
|
1372
1374
|
}
|
|
1373
|
-
return buildHostToolReference(
|
|
1375
|
+
return buildHostToolReference(toolKits);
|
|
1374
1376
|
}
|
|
1375
|
-
export class
|
|
1377
|
+
export class AgentOs {
|
|
1376
1378
|
#kernel;
|
|
1377
1379
|
sidecar;
|
|
1378
1380
|
_sessions = new Map();
|
|
@@ -1389,7 +1391,7 @@ export class AgentOS {
|
|
|
1389
1391
|
_softwareRoots;
|
|
1390
1392
|
_softwareAgentConfigs;
|
|
1391
1393
|
_cronManager;
|
|
1392
|
-
|
|
1394
|
+
_toolKits = [];
|
|
1393
1395
|
_toolReference = "";
|
|
1394
1396
|
_permissions = allowAll;
|
|
1395
1397
|
_hostMounts;
|
|
@@ -1414,7 +1416,7 @@ export class AgentOS {
|
|
|
1414
1416
|
this._disposeSidecarEventListener = this._sidecarClient.onEvent((event) => {
|
|
1415
1417
|
this._handleSidecarEvent(event);
|
|
1416
1418
|
});
|
|
1417
|
-
|
|
1419
|
+
agentOsRuntimeAdmins.set(this, {
|
|
1418
1420
|
kernel,
|
|
1419
1421
|
rootView: rootFilesystem,
|
|
1420
1422
|
env,
|
|
@@ -1422,28 +1424,21 @@ export class AgentOS {
|
|
|
1422
1424
|
});
|
|
1423
1425
|
}
|
|
1424
1426
|
static async createSidecar(options = {}) {
|
|
1425
|
-
return
|
|
1427
|
+
return createAgentOsSidecarInternal(options);
|
|
1426
1428
|
}
|
|
1427
1429
|
static async getSharedSidecar(options = {}) {
|
|
1428
|
-
return
|
|
1430
|
+
return getSharedAgentOsSidecarInternal(options);
|
|
1429
1431
|
}
|
|
1430
1432
|
static async create(options) {
|
|
1431
|
-
|
|
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);
|
|
1433
|
+
const processed = processSoftware(options?.software ?? []);
|
|
1439
1434
|
const localMounts = await resolveCompatLocalMounts(options?.mounts);
|
|
1440
|
-
const
|
|
1441
|
-
if (
|
|
1442
|
-
|
|
1435
|
+
const toolKits = options?.toolKits;
|
|
1436
|
+
if (toolKits && toolKits.length > 0) {
|
|
1437
|
+
validateToolkits(toolKits);
|
|
1443
1438
|
}
|
|
1444
1439
|
const createVmAdmin = async () => {
|
|
1445
1440
|
const preparedCommandDirs = prepareCommandDirs(processed.commandPackages);
|
|
1446
|
-
const toolBootstrapCommands = collectToolkitBootstrapCommands(
|
|
1441
|
+
const toolBootstrapCommands = collectToolkitBootstrapCommands(toolKits ?? []);
|
|
1447
1442
|
const bootstrapLower = createKernelBootstrapLower(options?.rootFilesystem, [
|
|
1448
1443
|
...collectBootstrapWasmCommands(preparedCommandDirs.commandDirs),
|
|
1449
1444
|
...NODE_RUNTIME_BOOTSTRAP_COMMANDS,
|
|
@@ -1468,8 +1463,8 @@ export class AgentOS {
|
|
|
1468
1463
|
};
|
|
1469
1464
|
try {
|
|
1470
1465
|
const env = getBaseEnvironment();
|
|
1471
|
-
if (
|
|
1472
|
-
toolShimDir = materializeToolShimDir(
|
|
1466
|
+
if (toolKits && toolKits.length > 0) {
|
|
1467
|
+
toolShimDir = materializeToolShimDir(toolKits);
|
|
1473
1468
|
}
|
|
1474
1469
|
const commandGuestPaths = collectGuestCommandPaths(preparedCommandDirs.commandDirs);
|
|
1475
1470
|
const requestedMounts = options?.moduleAccessCwd
|
|
@@ -1491,7 +1486,7 @@ export class AgentOS {
|
|
|
1491
1486
|
commandDirs: preparedCommandDirs.commandDirs,
|
|
1492
1487
|
shimDir: toolShimDir,
|
|
1493
1488
|
});
|
|
1494
|
-
client =
|
|
1489
|
+
client = SidecarProcess.spawn({
|
|
1495
1490
|
cwd: REPO_ROOT,
|
|
1496
1491
|
command: ensureNativeSidecarBinary(),
|
|
1497
1492
|
args: [],
|
|
@@ -1500,7 +1495,7 @@ export class AgentOS {
|
|
|
1500
1495
|
const session = await client.authenticateAndOpenSession();
|
|
1501
1496
|
const hostPermissions = options?.permissions ?? {
|
|
1502
1497
|
...allowAll,
|
|
1503
|
-
|
|
1498
|
+
tool: "allow",
|
|
1504
1499
|
};
|
|
1505
1500
|
const sidecarPermissions = serializePermissionsForSidecar(hostPermissions);
|
|
1506
1501
|
const createVmConfig = {
|
|
@@ -1537,11 +1532,11 @@ export class AgentOS {
|
|
|
1537
1532
|
commandPermissions: processed.commandPermissions,
|
|
1538
1533
|
loopbackExemptPorts: options?.loopbackExemptPorts,
|
|
1539
1534
|
});
|
|
1540
|
-
if (
|
|
1541
|
-
toolReference = await registerToolkitsOnSidecar(client, session, nativeVm,
|
|
1535
|
+
if (toolKits && toolKits.length > 0) {
|
|
1536
|
+
toolReference = await registerToolkitsOnSidecar(client, session, nativeVm, toolKits);
|
|
1542
1537
|
commandGuestPaths.set("agentos", "/bin/agentos");
|
|
1543
|
-
for (const
|
|
1544
|
-
commandGuestPaths.set(`agentos-${
|
|
1538
|
+
for (const toolKit of toolKits) {
|
|
1539
|
+
commandGuestPaths.set(`agentos-${toolKit.name}`, `/bin/agentos-${toolKit.name}`);
|
|
1545
1540
|
}
|
|
1546
1541
|
}
|
|
1547
1542
|
rootBridge = new NativeSidecarKernelProxy({
|
|
@@ -1549,7 +1544,7 @@ export class AgentOS {
|
|
|
1549
1544
|
session,
|
|
1550
1545
|
vm: nativeVm,
|
|
1551
1546
|
env,
|
|
1552
|
-
cwd: "/
|
|
1547
|
+
cwd: "/home/user",
|
|
1553
1548
|
localMounts,
|
|
1554
1549
|
commandGuestPaths,
|
|
1555
1550
|
onDispose: cleanup,
|
|
@@ -1567,7 +1562,7 @@ export class AgentOS {
|
|
|
1567
1562
|
sidecarVm: nativeVm,
|
|
1568
1563
|
permissions: hostPermissions,
|
|
1569
1564
|
snapshotRootFilesystem: async () => createSnapshotExport(convertSidecarRootSnapshotEntries(await snapshotClient.snapshotRootFilesystem(session, nativeVm))),
|
|
1570
|
-
|
|
1565
|
+
toolKits: toolKits ?? [],
|
|
1571
1566
|
toolReference,
|
|
1572
1567
|
async dispose() {
|
|
1573
1568
|
if (kernel) {
|
|
@@ -1599,16 +1594,16 @@ export class AgentOS {
|
|
|
1599
1594
|
throw error;
|
|
1600
1595
|
}
|
|
1601
1596
|
};
|
|
1602
|
-
const sidecar =
|
|
1597
|
+
const sidecar = resolveAgentOsSidecar(options?.sidecar);
|
|
1603
1598
|
let sidecarLease = null;
|
|
1604
1599
|
try {
|
|
1605
|
-
sidecarLease = await
|
|
1600
|
+
sidecarLease = await leaseAgentOsSidecarVm(sidecar, {
|
|
1606
1601
|
createVm: async () => createVmAdmin(),
|
|
1607
1602
|
});
|
|
1608
1603
|
const vmAdmin = sidecarLease.admin;
|
|
1609
|
-
const vm = new
|
|
1604
|
+
const vm = new AgentOs(vmAdmin.kernel, sidecar, processed.softwareRoots, processed.agentConfigs, vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm);
|
|
1610
1605
|
vm._sidecarLease = sidecarLease;
|
|
1611
|
-
vm.
|
|
1606
|
+
vm._toolKits = vmAdmin.toolKits;
|
|
1612
1607
|
vm._toolReference = vmAdmin.toolReference;
|
|
1613
1608
|
vm._permissions = vmAdmin.permissions;
|
|
1614
1609
|
vm._installSidecarRequestHandler();
|
|
@@ -2529,7 +2524,7 @@ export class AgentOS {
|
|
|
2529
2524
|
// skipOsInstructions plus the agent's static launch args and env.
|
|
2530
2525
|
const launchArgs = [...(config.launchArgs ?? [])];
|
|
2531
2526
|
let launchEnv = { ...config.defaultEnv, ...options?.env };
|
|
2532
|
-
const sessionCwd = options?.cwd ?? "/
|
|
2527
|
+
const sessionCwd = options?.cwd ?? "/home/user";
|
|
2533
2528
|
const adapterEntrypoint = this._resolveAdapterBin(config.acpAdapter);
|
|
2534
2529
|
if ((agentType === "pi" || agentType === "pi-cli") &&
|
|
2535
2530
|
!launchEnv.PI_ACP_PI_COMMAND) {
|
|
@@ -2585,6 +2580,70 @@ export class AgentOS {
|
|
|
2585
2580
|
}
|
|
2586
2581
|
return { sessionId: created.sessionId };
|
|
2587
2582
|
}
|
|
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
|
+
}
|
|
2588
2647
|
/**
|
|
2589
2648
|
* Resolve the VM bin entry point of an ACP adapter package.
|
|
2590
2649
|
* Reads from the host filesystem since kernel.readFile() resolves through
|
|
@@ -2624,7 +2683,7 @@ export class AgentOS {
|
|
|
2624
2683
|
if (!nodeModulesRoot) {
|
|
2625
2684
|
throw new Error(`Cannot resolve package "${packageName}": no software root provides it and ` +
|
|
2626
2685
|
`no /root/node_modules mount was supplied. Pass ` +
|
|
2627
|
-
`mounts: [nodeModulesMount("<host>/node_modules")] to
|
|
2686
|
+
`mounts: [nodeModulesMount("<host>/node_modules")] to AgentOs.create().`);
|
|
2628
2687
|
}
|
|
2629
2688
|
hostPkgJsonPath = join(resolvePackageDir(nodeModulesRoot, packageName), "package.json");
|
|
2630
2689
|
}
|
|
@@ -2646,8 +2705,8 @@ export class AgentOS {
|
|
|
2646
2705
|
}
|
|
2647
2706
|
_installSidecarRequestHandler() {
|
|
2648
2707
|
const context = {
|
|
2649
|
-
|
|
2650
|
-
toolMap: buildToolMap(this.
|
|
2708
|
+
toolKits: this._toolKits,
|
|
2709
|
+
toolMap: buildToolMap(this._toolKits),
|
|
2651
2710
|
permissions: this._permissions,
|
|
2652
2711
|
readFile: (path) => this.readFile(path),
|
|
2653
2712
|
};
|
|
@@ -3358,26 +3417,26 @@ export class AgentOS {
|
|
|
3358
3417
|
return this.#kernel.dispose();
|
|
3359
3418
|
}
|
|
3360
3419
|
}
|
|
3361
|
-
const
|
|
3362
|
-
export function
|
|
3363
|
-
const admin =
|
|
3420
|
+
const agentOsRuntimeAdmins = new WeakMap();
|
|
3421
|
+
export function getAgentOsRuntimeAdmin(vm) {
|
|
3422
|
+
const admin = agentOsRuntimeAdmins.get(vm);
|
|
3364
3423
|
if (!admin) {
|
|
3365
3424
|
throw new Error("Agent OS runtime admin is not available for this VM");
|
|
3366
3425
|
}
|
|
3367
3426
|
return admin;
|
|
3368
3427
|
}
|
|
3369
|
-
export function
|
|
3370
|
-
return
|
|
3428
|
+
export function getAgentOsKernel(vm) {
|
|
3429
|
+
return getAgentOsRuntimeAdmin(vm).kernel;
|
|
3371
3430
|
}
|
|
3372
|
-
function
|
|
3431
|
+
function resolveAgentOsSidecar(config) {
|
|
3373
3432
|
if (!config || config.kind === "shared") {
|
|
3374
|
-
return
|
|
3433
|
+
return getSharedAgentOsSidecarInternal(config?.kind === "shared" ? { pool: config.pool } : undefined);
|
|
3375
3434
|
}
|
|
3376
3435
|
return config.handle;
|
|
3377
3436
|
}
|
|
3378
3437
|
const sidecarStates = new WeakMap();
|
|
3379
3438
|
const sharedSidecars = new Map();
|
|
3380
|
-
export class
|
|
3439
|
+
export class AgentOsSidecar {
|
|
3381
3440
|
constructor(sidecarId, placement, sharedPool) {
|
|
3382
3441
|
sidecarStates.set(this, {
|
|
3383
3442
|
description: {
|
|
@@ -3420,9 +3479,9 @@ export class AgentOSSidecar {
|
|
|
3420
3479
|
}
|
|
3421
3480
|
}
|
|
3422
3481
|
}
|
|
3423
|
-
function
|
|
3482
|
+
function createAgentOsSidecarInternal(options = {}) {
|
|
3424
3483
|
const sidecarId = options.sidecarId ?? `agentos-sidecar-${randomUUID()}`;
|
|
3425
|
-
return new
|
|
3484
|
+
return new AgentOsSidecar(sidecarId, {
|
|
3426
3485
|
kind: "explicit",
|
|
3427
3486
|
sidecarId,
|
|
3428
3487
|
});
|
|
@@ -3430,7 +3489,7 @@ function createAgentOSSidecarInternal(options = {}) {
|
|
|
3430
3489
|
/**
|
|
3431
3490
|
* Test-only escape hatch: dispose every cached shared sidecar so vitest
|
|
3432
3491
|
* workers can exit cleanly. The shared sidecar is normally process-global and
|
|
3433
|
-
* keeps its native subprocess alive across `
|
|
3492
|
+
* keeps its native subprocess alive across `AgentOs.create()` calls; without
|
|
3434
3493
|
* this hook the vitest worker can hold open piped stdio handles after the
|
|
3435
3494
|
* test suite finishes and stall `pnpm test` indefinitely.
|
|
3436
3495
|
*/
|
|
@@ -3450,23 +3509,23 @@ export async function __disposeAllSharedSidecarsForTesting() {
|
|
|
3450
3509
|
throw new Error(`failed to dispose shared sidecars: ${errors.map((error) => error.message).join("; ")}`);
|
|
3451
3510
|
}
|
|
3452
3511
|
}
|
|
3453
|
-
function
|
|
3512
|
+
function getSharedAgentOsSidecarInternal(options = {}) {
|
|
3454
3513
|
const pool = options.pool ?? "default";
|
|
3455
3514
|
const existing = sharedSidecars.get(pool);
|
|
3456
3515
|
if (existing && existing.describe().state !== "disposed") {
|
|
3457
3516
|
return existing;
|
|
3458
3517
|
}
|
|
3459
|
-
const sidecar = new
|
|
3518
|
+
const sidecar = new AgentOsSidecar(`agentos-shared-sidecar:${pool}`, { kind: "shared", ...(pool ? { pool } : {}) }, pool);
|
|
3460
3519
|
sharedSidecars.set(pool, sidecar);
|
|
3461
3520
|
return sidecar;
|
|
3462
3521
|
}
|
|
3463
|
-
async function
|
|
3522
|
+
async function leaseAgentOsSidecarVm(sidecar, options) {
|
|
3464
3523
|
const state = getSidecarState(sidecar);
|
|
3465
3524
|
if (state.description.state !== "ready") {
|
|
3466
3525
|
throw new Error(`Cannot lease VM from sidecar ${state.description.sidecarId} while it is ${state.description.state}`);
|
|
3467
3526
|
}
|
|
3468
3527
|
let transport;
|
|
3469
|
-
const client =
|
|
3528
|
+
const client = createAgentOsSidecarClient({
|
|
3470
3529
|
async createSessionTransport(sessionBootstrap) {
|
|
3471
3530
|
transport = await createInProcessSidecarTransport(sessionBootstrap, options);
|
|
3472
3531
|
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_AGENT_OS_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;
|