@rivet-dev/agentos-core 0.0.0-agentos-dylib-plugin.473700e
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 +204 -0
- package/dist/agent-os.d.ts +560 -0
- package/dist/agent-os.js +3624 -0
- package/dist/agent-session-types.d.ts +67 -0
- package/dist/agent-session-types.js +1 -0
- package/dist/agents.d.ts +63 -0
- package/dist/agents.js +42 -0
- package/dist/base-filesystem.d.ts +34 -0
- package/dist/base-filesystem.js +173 -0
- package/dist/cron/cron-manager.d.ts +22 -0
- package/dist/cron/cron-manager.js +160 -0
- package/dist/cron/index.d.ts +5 -0
- package/dist/cron/index.js +3 -0
- package/dist/cron/parse-schedule.d.ts +25 -0
- package/dist/cron/parse-schedule.js +66 -0
- package/dist/cron/schedule-driver.d.ts +19 -0
- package/dist/cron/schedule-driver.js +1 -0
- package/dist/cron/timer-driver.d.ts +17 -0
- package/dist/cron/timer-driver.js +61 -0
- package/dist/cron/types.d.ts +55 -0
- package/dist/cron/types.js +1 -0
- package/dist/filesystem-snapshot.d.ts +14 -0
- package/dist/filesystem-snapshot.js +105 -0
- package/dist/host-dir-mount.d.ts +38 -0
- package/dist/host-dir-mount.js +34 -0
- package/dist/host-tools-zod.d.ts +7 -0
- package/dist/host-tools-zod.js +243 -0
- package/dist/host-tools.d.ts +45 -0
- package/dist/host-tools.js +26 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/js-bridge.d.ts +3 -0
- package/dist/js-bridge.js +2 -0
- package/dist/json-rpc.d.ts +50 -0
- package/dist/json-rpc.js +22 -0
- package/dist/layers.d.ts +51 -0
- package/dist/layers.js +185 -0
- package/dist/overlay-filesystem.d.ts +19 -0
- package/dist/overlay-filesystem.js +645 -0
- package/dist/packages.d.ts +127 -0
- package/dist/packages.js +335 -0
- package/dist/runtime-compat.d.ts +471 -0
- package/dist/runtime-compat.js +2009 -0
- package/dist/runtime.d.ts +336 -0
- package/dist/runtime.js +1 -0
- package/dist/sidecar/agent-os-protocol.d.ts +219 -0
- package/dist/sidecar/agent-os-protocol.js +594 -0
- package/dist/sidecar/binary.d.ts +9 -0
- package/dist/sidecar/binary.js +30 -0
- package/dist/sidecar/cargo.d.ts +2 -0
- package/dist/sidecar/cargo.js +142 -0
- package/dist/sidecar/native-process-client.d.ts +2 -0
- package/dist/sidecar/native-process-client.js +1 -0
- package/dist/sidecar/permissions.d.ts +3 -0
- package/dist/sidecar/permissions.js +54 -0
- package/dist/sidecar/process.d.ts +6 -0
- package/dist/sidecar/process.js +8 -0
- package/dist/sidecar/rpc-client.d.ts +244 -0
- package/dist/sidecar/rpc-client.js +2028 -0
- package/dist/test/docker.d.ts +133 -0
- package/dist/test/docker.js +336 -0
- package/dist/test/file-system.d.ts +39 -0
- package/dist/test/file-system.js +562 -0
- package/dist/test/mock-s3.d.ts +42 -0
- package/dist/test/mock-s3.js +292 -0
- package/dist/test/runtime.d.ts +11 -0
- package/dist/test/runtime.js +9 -0
- package/dist/test/sandbox-agent.d.ts +9 -0
- package/dist/test/sandbox-agent.js +395 -0
- package/dist/test/terminal-harness.d.ts +27 -0
- package/dist/test/terminal-harness.js +122 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.js +1 -0
- package/fixtures/AGENTOS_SYSTEM_PROMPT.md +21 -0
- package/package.json +111 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
const DEFAULT_BUCKET = "test-bucket";
|
|
4
|
+
const DEFAULT_ACCESS_KEY_ID = "minioadmin";
|
|
5
|
+
const DEFAULT_SECRET_ACCESS_KEY = "minioadmin";
|
|
6
|
+
const EMPTY_PAYLOAD_HASH = sha256Hex("");
|
|
7
|
+
const SUPPORTED_METHODS = new Set(["GET", "PUT", "DELETE"]);
|
|
8
|
+
function decodePath(pathname) {
|
|
9
|
+
try {
|
|
10
|
+
return decodeURIComponent(pathname.replace(/\+/g, " "));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return pathname;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function sha256Hex(data) {
|
|
17
|
+
return createHash("sha256").update(data).digest("hex");
|
|
18
|
+
}
|
|
19
|
+
function hmac(key, data) {
|
|
20
|
+
return createHmac("sha256", key).update(data).digest();
|
|
21
|
+
}
|
|
22
|
+
function normalizeHeaderValue(value) {
|
|
23
|
+
if (value == null) {
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
return (Array.isArray(value) ? value.join(",") : value)
|
|
27
|
+
.trim()
|
|
28
|
+
.replace(/\s+/g, " ");
|
|
29
|
+
}
|
|
30
|
+
function encodeAwsComponent(value) {
|
|
31
|
+
return encodeURIComponent(value).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
32
|
+
}
|
|
33
|
+
function canonicalQueryString(searchParams) {
|
|
34
|
+
return [...searchParams.entries()]
|
|
35
|
+
.sort(([aKey, aValue], [bKey, bValue]) => aKey === bKey ? aValue.localeCompare(bValue) : aKey.localeCompare(bKey))
|
|
36
|
+
.map(([key, value]) => `${encodeAwsComponent(key)}=${encodeAwsComponent(value)}`)
|
|
37
|
+
.join("&");
|
|
38
|
+
}
|
|
39
|
+
function parseAuthorization(authorization) {
|
|
40
|
+
if (!authorization) {
|
|
41
|
+
throw new Error("missing Authorization header");
|
|
42
|
+
}
|
|
43
|
+
const [algorithm, ...parts] = authorization.split(/\s+/);
|
|
44
|
+
if (algorithm !== "AWS4-HMAC-SHA256") {
|
|
45
|
+
throw new Error(`unsupported authorization algorithm: ${algorithm}`);
|
|
46
|
+
}
|
|
47
|
+
const kv = new Map();
|
|
48
|
+
for (const part of parts.join(" ").split(",")) {
|
|
49
|
+
const [rawKey, rawValue] = part.trim().split("=");
|
|
50
|
+
if (rawKey && rawValue) {
|
|
51
|
+
kv.set(rawKey, rawValue);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const credential = kv.get("Credential");
|
|
55
|
+
const signedHeaders = kv.get("SignedHeaders");
|
|
56
|
+
const signature = kv.get("Signature");
|
|
57
|
+
if (!credential || !signedHeaders || !signature) {
|
|
58
|
+
throw new Error("missing SigV4 credential components");
|
|
59
|
+
}
|
|
60
|
+
const credentialParts = credential.split("/");
|
|
61
|
+
if (credentialParts.length !== 5) {
|
|
62
|
+
throw new Error(`invalid credential scope: ${credential}`);
|
|
63
|
+
}
|
|
64
|
+
const [accessKeyId, date, region, service, terminal] = credentialParts;
|
|
65
|
+
return {
|
|
66
|
+
accessKeyId,
|
|
67
|
+
date,
|
|
68
|
+
region,
|
|
69
|
+
service,
|
|
70
|
+
terminal,
|
|
71
|
+
signedHeaders: signedHeaders.split(";").filter(Boolean),
|
|
72
|
+
signature,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function buildCanonicalHeaders(headers, signedHeaders) {
|
|
76
|
+
return signedHeaders
|
|
77
|
+
.map((headerName) => {
|
|
78
|
+
const value = normalizeHeaderValue(headers[headerName]);
|
|
79
|
+
if (!value) {
|
|
80
|
+
throw new Error(`missing signed header: ${headerName}`);
|
|
81
|
+
}
|
|
82
|
+
return `${headerName}:${value}\n`;
|
|
83
|
+
})
|
|
84
|
+
.join("");
|
|
85
|
+
}
|
|
86
|
+
function canonicalPath(pathname) {
|
|
87
|
+
return pathname
|
|
88
|
+
.split("/")
|
|
89
|
+
.map((segment) => encodeAwsComponent(decodeURIComponent(segment)))
|
|
90
|
+
.join("/");
|
|
91
|
+
}
|
|
92
|
+
function verifySigV4(options) {
|
|
93
|
+
const parsed = parseAuthorization(normalizeHeaderValue(options.headers.authorization));
|
|
94
|
+
if (parsed.accessKeyId !== options.accessKeyId) {
|
|
95
|
+
throw new Error(`unexpected access key id: ${parsed.accessKeyId} (expected ${options.accessKeyId})`);
|
|
96
|
+
}
|
|
97
|
+
if (parsed.service !== "s3" || parsed.terminal !== "aws4_request") {
|
|
98
|
+
throw new Error(`unexpected credential scope: ${parsed.service}/${parsed.terminal}`);
|
|
99
|
+
}
|
|
100
|
+
const payloadHash = normalizeHeaderValue(options.headers["x-amz-content-sha256"]);
|
|
101
|
+
if (!payloadHash) {
|
|
102
|
+
throw new Error("missing x-amz-content-sha256 header");
|
|
103
|
+
}
|
|
104
|
+
const expectedPayloadHash = sha256Hex(options.body);
|
|
105
|
+
if (payloadHash !== "UNSIGNED-PAYLOAD" &&
|
|
106
|
+
payloadHash !== expectedPayloadHash) {
|
|
107
|
+
throw new Error(`payload hash mismatch: expected ${expectedPayloadHash}, got ${payloadHash}`);
|
|
108
|
+
}
|
|
109
|
+
const xAmzDate = normalizeHeaderValue(options.headers["x-amz-date"]);
|
|
110
|
+
if (!xAmzDate) {
|
|
111
|
+
throw new Error("missing x-amz-date header");
|
|
112
|
+
}
|
|
113
|
+
if (!xAmzDate.startsWith(parsed.date)) {
|
|
114
|
+
throw new Error(`x-amz-date ${xAmzDate} does not match credential date ${parsed.date}`);
|
|
115
|
+
}
|
|
116
|
+
const canonicalRequest = [
|
|
117
|
+
options.method,
|
|
118
|
+
canonicalPath(options.pathname),
|
|
119
|
+
options.query,
|
|
120
|
+
buildCanonicalHeaders(options.headers, parsed.signedHeaders),
|
|
121
|
+
parsed.signedHeaders.join(";"),
|
|
122
|
+
payloadHash,
|
|
123
|
+
].join("\n");
|
|
124
|
+
const stringToSign = [
|
|
125
|
+
"AWS4-HMAC-SHA256",
|
|
126
|
+
xAmzDate,
|
|
127
|
+
`${parsed.date}/${parsed.region}/${parsed.service}/${parsed.terminal}`,
|
|
128
|
+
sha256Hex(canonicalRequest),
|
|
129
|
+
].join("\n");
|
|
130
|
+
const signingKey = hmac(hmac(hmac(hmac(`AWS4${options.secretAccessKey}`, parsed.date), parsed.region), parsed.service), parsed.terminal);
|
|
131
|
+
const expectedSignature = createHmac("sha256", signingKey)
|
|
132
|
+
.update(stringToSign)
|
|
133
|
+
.digest("hex");
|
|
134
|
+
const actual = Buffer.from(parsed.signature, "hex");
|
|
135
|
+
const expected = Buffer.from(expectedSignature, "hex");
|
|
136
|
+
if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) {
|
|
137
|
+
throw new Error(`signature mismatch: expected ${expectedSignature}, got ${parsed.signature}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function xmlError(code, message) {
|
|
141
|
+
return Buffer.from(`<Error><Code>${code}</Code><Message>${message}</Message></Error>`);
|
|
142
|
+
}
|
|
143
|
+
export async function startMockS3Server() {
|
|
144
|
+
const objects = new Map();
|
|
145
|
+
const requestLog = [];
|
|
146
|
+
const protocolViolations = [];
|
|
147
|
+
const server = createServer(async (request, response) => {
|
|
148
|
+
const method = request.method ?? "GET";
|
|
149
|
+
const target = new URL(request.url ?? "/", "http://127.0.0.1");
|
|
150
|
+
const pathname = target.pathname;
|
|
151
|
+
const decodedPath = decodePath(pathname);
|
|
152
|
+
const pathWithoutLeadingSlash = decodedPath.replace(/^\/+/, "");
|
|
153
|
+
const [bucket, ...keyParts] = pathWithoutLeadingSlash.split("/");
|
|
154
|
+
const key = keyParts.join("/");
|
|
155
|
+
const query = canonicalQueryString(target.searchParams);
|
|
156
|
+
const targetSummary = `${method} ${target.pathname}${target.search}`;
|
|
157
|
+
const fail = (status, code, message) => {
|
|
158
|
+
protocolViolations.push(`${targetSummary}: ${message}`);
|
|
159
|
+
const body = xmlError(code, message);
|
|
160
|
+
response.writeHead(status, {
|
|
161
|
+
"Content-Type": "application/xml",
|
|
162
|
+
"Content-Length": String(body.length),
|
|
163
|
+
"x-amz-request-id": "test",
|
|
164
|
+
});
|
|
165
|
+
response.end(body);
|
|
166
|
+
};
|
|
167
|
+
if (!SUPPORTED_METHODS.has(method)) {
|
|
168
|
+
fail(501, "NotImplemented", `unsupported S3 method ${method}; update the local harness before adding new protocol calls`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const expectedOperationId = method === "GET"
|
|
172
|
+
? "GetObject"
|
|
173
|
+
: method === "PUT"
|
|
174
|
+
? "PutObject"
|
|
175
|
+
: "DeleteObject";
|
|
176
|
+
if (query && query !== `x-id=${expectedOperationId}`) {
|
|
177
|
+
fail(501, "NotImplemented", `unsupported S3 query string '${query}'; only x-id=${expectedOperationId} is allowed for ${method}`);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (bucket !== DEFAULT_BUCKET || !key) {
|
|
181
|
+
fail(400, "InvalidURI", `expected path-style /${DEFAULT_BUCKET}/<key> request, got ${decodedPath}`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const chunks = [];
|
|
185
|
+
for await (const chunk of request) {
|
|
186
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
187
|
+
}
|
|
188
|
+
const body = Buffer.concat(chunks);
|
|
189
|
+
try {
|
|
190
|
+
verifySigV4({
|
|
191
|
+
accessKeyId: DEFAULT_ACCESS_KEY_ID,
|
|
192
|
+
body,
|
|
193
|
+
headers: request.headers,
|
|
194
|
+
method,
|
|
195
|
+
pathname,
|
|
196
|
+
query,
|
|
197
|
+
secretAccessKey: DEFAULT_SECRET_ACCESS_KEY,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
202
|
+
fail(403, "SignatureDoesNotMatch", message);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
requestLog.push({ method, path: decodedPath, query, key });
|
|
206
|
+
switch (method) {
|
|
207
|
+
case "GET": {
|
|
208
|
+
const stored = objects.get(key);
|
|
209
|
+
if (!stored) {
|
|
210
|
+
const body = xmlError("NoSuchKey", "missing");
|
|
211
|
+
response.writeHead(404, {
|
|
212
|
+
"Content-Type": "application/xml",
|
|
213
|
+
"Content-Length": String(body.length),
|
|
214
|
+
"x-amz-request-id": "test",
|
|
215
|
+
});
|
|
216
|
+
response.end(body);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
response.writeHead(200, {
|
|
220
|
+
"Content-Type": "application/octet-stream",
|
|
221
|
+
"Content-Length": String(stored.length),
|
|
222
|
+
"x-amz-request-id": "test",
|
|
223
|
+
});
|
|
224
|
+
response.end(stored);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
case "PUT": {
|
|
228
|
+
objects.set(key, body);
|
|
229
|
+
response.writeHead(200, {
|
|
230
|
+
"Content-Type": "application/xml",
|
|
231
|
+
"Content-Length": "0",
|
|
232
|
+
"x-amz-request-id": "test",
|
|
233
|
+
});
|
|
234
|
+
response.end();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
case "DELETE": {
|
|
238
|
+
objects.delete(key);
|
|
239
|
+
response.writeHead(204, {
|
|
240
|
+
"Content-Type": "application/xml",
|
|
241
|
+
"Content-Length": "0",
|
|
242
|
+
"x-amz-request-id": "test",
|
|
243
|
+
});
|
|
244
|
+
response.end();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
await new Promise((resolve, reject) => {
|
|
250
|
+
server.once("error", reject);
|
|
251
|
+
server.listen(0, "127.0.0.1", () => {
|
|
252
|
+
server.off("error", reject);
|
|
253
|
+
resolve();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
const address = server.address();
|
|
257
|
+
if (!address || typeof address === "string") {
|
|
258
|
+
throw new Error("Mock S3 server did not expose a TCP address.");
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
accessKeyId: DEFAULT_ACCESS_KEY_ID,
|
|
262
|
+
bucket: DEFAULT_BUCKET,
|
|
263
|
+
endpoint: `http://127.0.0.1:${address.port}`,
|
|
264
|
+
secretAccessKey: DEFAULT_SECRET_ACCESS_KEY,
|
|
265
|
+
objectKeys() {
|
|
266
|
+
return [...objects.keys()].sort();
|
|
267
|
+
},
|
|
268
|
+
requests() {
|
|
269
|
+
return [...requestLog];
|
|
270
|
+
},
|
|
271
|
+
stop() {
|
|
272
|
+
return new Promise((resolve, reject) => {
|
|
273
|
+
server.close((error) => {
|
|
274
|
+
if (error) {
|
|
275
|
+
reject(error);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
if (protocolViolations.length > 0) {
|
|
279
|
+
reject(new Error(`Strict mock S3 server saw unsupported protocol usage:\n- ${protocolViolations.join("\n- ")}`));
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
resolve();
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
export const __mockS3Internals = {
|
|
289
|
+
EMPTY_PAYLOAD_HASH,
|
|
290
|
+
parseAuthorization,
|
|
291
|
+
verifySigV4,
|
|
292
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal test-only runtime exports for cross-package integration suites.
|
|
3
|
+
*
|
|
4
|
+
* This keeps repo-owned tests pointed at an Agent OS package surface even
|
|
5
|
+
* while the public SDK removes the raw vm.kernel escape hatch.
|
|
6
|
+
*/
|
|
7
|
+
export { type AgentOsRuntimeAdmin, getAgentOsKernel, getAgentOsRuntimeAdmin, } from "../agent-os.js";
|
|
8
|
+
export type { PermissionTier, WasmVmRuntimeOptions, } from "../runtime.js";
|
|
9
|
+
export type { DriverProcess, Kernel, KernelInterface, KernelRuntimeDriver, ProcessContext, VirtualFileSystem, } from "../runtime-compat.js";
|
|
10
|
+
export { AF_INET, AF_UNIX, allowAll, createInMemoryFileSystem, createKernel, createNodeHostNetworkAdapter, createNodeRuntime, createWasmVmRuntime, DEFAULT_FIRST_PARTY_TIERS, NodeFileSystem, SIGTERM, SOCK_DGRAM, SOCK_STREAM, WASMVM_COMMANDS, } from "../runtime-compat.js";
|
|
11
|
+
export { TerminalHarness } from "./terminal-harness.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal test-only runtime exports for cross-package integration suites.
|
|
3
|
+
*
|
|
4
|
+
* This keeps repo-owned tests pointed at an Agent OS package surface even
|
|
5
|
+
* while the public SDK removes the raw vm.kernel escape hatch.
|
|
6
|
+
*/
|
|
7
|
+
export { getAgentOsKernel, getAgentOsRuntimeAdmin, } from "../agent-os.js";
|
|
8
|
+
export { AF_INET, AF_UNIX, allowAll, createInMemoryFileSystem, createKernel, createNodeHostNetworkAdapter, createNodeRuntime, createWasmVmRuntime, DEFAULT_FIRST_PARTY_TIERS, NodeFileSystem, SIGTERM, SOCK_DGRAM, SOCK_STREAM, WASMVM_COMMANDS, } from "../runtime-compat.js";
|
|
9
|
+
export { TerminalHarness } from "./terminal-harness.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SandboxAgent } from "sandbox-agent";
|
|
2
|
+
export interface MockSandboxAgentHandle {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
client: SandboxAgent;
|
|
5
|
+
path(...segments: string[]): string;
|
|
6
|
+
rootDir: string;
|
|
7
|
+
stop(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export declare function startMockSandboxAgent(): Promise<MockSandboxAgentHandle>;
|