@fungi.computer/computer 0.0.1 → 0.2.0
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 +38 -10
- package/dist/computer-backends.d.ts +11 -12
- package/dist/computer-backends.js +4 -7
- package/dist/exec-output.d.ts +13 -0
- package/dist/exec-output.js +24 -0
- package/dist/execution-lifecycle.d.ts +35 -0
- package/dist/execution-lifecycle.js +78 -0
- package/dist/files-patch.d.ts +12 -4
- package/dist/files-patch.js +8 -14
- package/dist/files.d.ts +65 -15
- package/dist/files.js +152 -31
- package/dist/fleet/backing.js +2 -2
- package/dist/fleet/index.d.ts +1 -1
- package/dist/fleet/index.js +1 -1
- package/dist/fleet/inventory-wire.d.ts +4 -0
- package/dist/fleet/inventory-wire.js +5 -0
- package/dist/fleet/inventory.js +4 -4
- package/dist/fleet/lifecycle.d.ts +7 -1
- package/dist/fleet/lifecycle.js +23 -6
- package/dist/fleet/wire.d.ts +28 -28
- package/dist/fleet/wire.js +9 -9
- package/dist/index.d.ts +33 -15
- package/dist/index.js +426 -109
- package/dist/internet-access.d.ts +4 -0
- package/dist/internet-access.js +14 -0
- package/dist/local-backend-replay.d.ts +10 -0
- package/dist/local-backend-replay.js +43 -0
- package/dist/local-backend.d.ts +2 -1
- package/dist/local-backend.js +4 -4
- package/dist/on-box-vm.d.ts +15 -4
- package/dist/on-box-vm.js +43 -20
- package/dist/operation-record.d.ts +1 -1
- package/dist/operation-record.js +1 -1
- package/dist/process-inventory.d.ts +3 -1
- package/dist/process-inventory.js +2 -2
- package/dist/team-candidate-builder.mjs +8428 -337
- package/package.json +17 -24
- package/dist/light-shell.d.ts +0 -44
- package/dist/light-shell.js +0 -376
- package/dist/operation-contract.d.ts +0 -456
- package/dist/operation-contract.js +0 -452
|
@@ -1,452 +0,0 @@
|
|
|
1
|
-
import { replayKey, defineIdFamily } from "@fungi.computer/cairn";
|
|
2
|
-
import * as z from "zod";
|
|
3
|
-
import { attachedBackendIdSchema } from "./computer-backends.js";
|
|
4
|
-
const utf8 = new TextEncoder();
|
|
5
|
-
export const maximumFileBytes = 128 * 1_024;
|
|
6
|
-
export const maximumListEntries = 256;
|
|
7
|
-
export const maximumPatternCharacters = 512;
|
|
8
|
-
export const maximumCommandCharacters = 16 * 1_024;
|
|
9
|
-
export const maximumStreamBytes = 64 * 1_024;
|
|
10
|
-
/** The bound for ordinary Computer commands; hosts own any admitted job budget. */
|
|
11
|
-
export const maximumExecutionTimeMs = 120_000;
|
|
12
|
-
export const genericComputerExecutionBudget = Object.freeze({ maximumTimeMs: maximumExecutionTimeMs });
|
|
13
|
-
export const computerValueSchema = z.json();
|
|
14
|
-
export const capabilityNameSchema = z
|
|
15
|
-
.string()
|
|
16
|
-
.min(1)
|
|
17
|
-
.max(128)
|
|
18
|
-
.regex(/^[A-Za-z][A-Za-z0-9_]*$/);
|
|
19
|
-
/** One valid TCP port number, used only with this Computer's container. */
|
|
20
|
-
export const computerPortSchema = z.number().int().min(1).max(65_535);
|
|
21
|
-
export const maximumExposedPorts = 64;
|
|
22
|
-
/** computerd's Workspace RPC port, pinned by the Cloudflare container backend. */
|
|
23
|
-
export const computerDaemonPort = 8080;
|
|
24
|
-
/** The Computer-owned terminal server inside the container image. */
|
|
25
|
-
export const computerTerminalPort = 7681;
|
|
26
|
-
/**
|
|
27
|
-
* Ports served by the Computer's own in-container daemons. An admitted
|
|
28
|
-
* preview must never reach a control plane.
|
|
29
|
-
*/
|
|
30
|
-
export const computerReservedPorts = new Set([
|
|
31
|
-
computerDaemonPort,
|
|
32
|
-
computerTerminalPort,
|
|
33
|
-
]);
|
|
34
|
-
export function isComputerReservedPort(port) {
|
|
35
|
-
return computerReservedPorts.has(port);
|
|
36
|
-
}
|
|
37
|
-
export const computerPortInputSchema = z.strictObject({
|
|
38
|
-
port: computerPortSchema,
|
|
39
|
-
});
|
|
40
|
-
export const computerPortOutputSchema = z.strictObject({
|
|
41
|
-
port: computerPortSchema,
|
|
42
|
-
exposed: z.boolean(),
|
|
43
|
-
});
|
|
44
|
-
export const computerPortRemovalOutputSchema = z.strictObject({
|
|
45
|
-
port: computerPortSchema,
|
|
46
|
-
removed: z.boolean(),
|
|
47
|
-
});
|
|
48
|
-
export const computerPortsOutputSchema = z.strictObject({
|
|
49
|
-
ports: z.array(computerPortSchema).max(maximumExposedPorts),
|
|
50
|
-
});
|
|
51
|
-
/** The port belongs to a Computer daemon and cannot be admitted for preview. */
|
|
52
|
-
export class ComputerPortReservedError extends Error {
|
|
53
|
-
constructor(port) {
|
|
54
|
-
super(`Computer port ${String(port)} is reserved`);
|
|
55
|
-
this.name = "ComputerPortReservedError";
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
/** A requested port cannot be reserved; no other process identity is disclosed. */
|
|
59
|
-
export class ComputerPortConflictError extends Error {
|
|
60
|
-
constructor() {
|
|
61
|
-
super("Computer port is unavailable");
|
|
62
|
-
this.name = "ComputerPortConflictError";
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/** This Computer already admits the maximum number of preview ports. */
|
|
66
|
-
export class ComputerPortLimitError extends Error {
|
|
67
|
-
constructor() {
|
|
68
|
-
super(`Computer can expose at most ${String(maximumExposedPorts)} ports`);
|
|
69
|
-
this.name = "ComputerPortLimitError";
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
// Schema keywords are opaque transport data. Zod still validates every value
|
|
73
|
-
// as JSON before the description leaves or enters the Computer boundary.
|
|
74
|
-
const schemaDocument = z
|
|
75
|
-
.record(z.string(), z.unknown())
|
|
76
|
-
.refine((value) => computerValueSchema.safeParse(value).success, "Capability schema must contain JSON values");
|
|
77
|
-
/** Native operation descriptions shared by discovery and its OpenAPI document. */
|
|
78
|
-
export const computerCapabilitiesSchema = z.array(z.strictObject({
|
|
79
|
-
id: capabilityNameSchema,
|
|
80
|
-
name: capabilityNameSchema,
|
|
81
|
-
kind: z.string(),
|
|
82
|
-
description: z.string(),
|
|
83
|
-
parameters: schemaDocument,
|
|
84
|
-
output: schemaDocument,
|
|
85
|
-
}));
|
|
86
|
-
export const pathSchema = z
|
|
87
|
-
.string()
|
|
88
|
-
.min(1)
|
|
89
|
-
.max(4_096)
|
|
90
|
-
.startsWith("/")
|
|
91
|
-
.refine((path) => !path.includes("\0"), "Path cannot contain null bytes");
|
|
92
|
-
export const boundedTextSchema = (minimumLength = 0) => z
|
|
93
|
-
.string()
|
|
94
|
-
.min(minimumLength)
|
|
95
|
-
.refine((content) => utf8.encode(content).byteLength <= maximumFileBytes, `Text exceeds the ${String(maximumFileBytes)}-byte Computer bound`);
|
|
96
|
-
/** Complete bounded UTF-8 text reads. Binary reads use the same path input. */
|
|
97
|
-
export const readInputSchema = z.strictObject({ path: pathSchema });
|
|
98
|
-
export const readOutputSchema = z.strictObject({
|
|
99
|
-
path: pathSchema,
|
|
100
|
-
content: boundedTextSchema(),
|
|
101
|
-
});
|
|
102
|
-
/** Optional byte window; text reads remain complete and independently bounded. */
|
|
103
|
-
export const readBytesInputSchema = z.strictObject({
|
|
104
|
-
path: pathSchema,
|
|
105
|
-
byteOffset: z.number().int().nonnegative().optional(),
|
|
106
|
-
byteLength: z.number().int().positive().max(maximumFileBytes).optional(),
|
|
107
|
-
});
|
|
108
|
-
/** Finite byte-read reply used by admitted App frame bindings. */
|
|
109
|
-
export const computerByteReadReplySchema = z.strictObject({
|
|
110
|
-
path: readBytesInputSchema.shape.path,
|
|
111
|
-
byteOffset: z.number().int().nonnegative(),
|
|
112
|
-
content: z.string(),
|
|
113
|
-
encoding: z.literal("base64"),
|
|
114
|
-
truncated: z.boolean(),
|
|
115
|
-
});
|
|
116
|
-
/** Host-admitted App method preview; parsing does not grant port access. */
|
|
117
|
-
export const appMethodPreviewResultSchema = z.strictObject({
|
|
118
|
-
previewUrl: z.url(),
|
|
119
|
-
expiresAt: z.number().int().positive(),
|
|
120
|
-
});
|
|
121
|
-
export const listLimitSchema = z
|
|
122
|
-
.number()
|
|
123
|
-
.int()
|
|
124
|
-
.min(1)
|
|
125
|
-
.max(maximumListEntries)
|
|
126
|
-
.default(100);
|
|
127
|
-
export const listOffsetSchema = z.number().int().nonnegative().default(0);
|
|
128
|
-
export const listInputSchema = z.strictObject({
|
|
129
|
-
path: pathSchema.default("/"),
|
|
130
|
-
limit: listLimitSchema,
|
|
131
|
-
offset: listOffsetSchema,
|
|
132
|
-
});
|
|
133
|
-
const listEntrySchema = z.strictObject({
|
|
134
|
-
name: z.string(),
|
|
135
|
-
size: z.number().int().nonnegative(),
|
|
136
|
-
modifiedAt: z.number(),
|
|
137
|
-
type: z.enum(["file", "directory", "symlink"]),
|
|
138
|
-
});
|
|
139
|
-
export const listOutputSchema = z.strictObject({
|
|
140
|
-
path: pathSchema,
|
|
141
|
-
entries: z.array(listEntrySchema).max(maximumListEntries),
|
|
142
|
-
nextOffset: z.number().int().nonnegative().nullable(),
|
|
143
|
-
});
|
|
144
|
-
export const fileContentSchema = z
|
|
145
|
-
.string()
|
|
146
|
-
.refine((content) => utf8.encode(content).byteLength <= maximumFileBytes, "File exceeds the Computer write bound");
|
|
147
|
-
export const writeInputSchema = z.strictObject({
|
|
148
|
-
path: pathSchema,
|
|
149
|
-
content: fileContentSchema,
|
|
150
|
-
});
|
|
151
|
-
export const writeOutputSchema = z.strictObject({
|
|
152
|
-
path: pathSchema,
|
|
153
|
-
bytes: z.number().int().nonnegative(),
|
|
154
|
-
});
|
|
155
|
-
export const writeBytesInputSchema = readInputSchema;
|
|
156
|
-
export const replaceInputSchema = z.strictObject({
|
|
157
|
-
path: pathSchema,
|
|
158
|
-
expectedContent: fileContentSchema,
|
|
159
|
-
content: fileContentSchema,
|
|
160
|
-
});
|
|
161
|
-
export const replaceOutputSchema = writeOutputSchema;
|
|
162
|
-
export const globInputSchema = z.strictObject({
|
|
163
|
-
path: pathSchema,
|
|
164
|
-
pattern: z.string().min(1).max(maximumPatternCharacters),
|
|
165
|
-
limit: z
|
|
166
|
-
.number()
|
|
167
|
-
.int()
|
|
168
|
-
.min(1)
|
|
169
|
-
.max(maximumListEntries)
|
|
170
|
-
.default(maximumListEntries),
|
|
171
|
-
});
|
|
172
|
-
export const globOutputSchema = z.strictObject({
|
|
173
|
-
path: pathSchema,
|
|
174
|
-
matches: z.array(pathSchema).max(maximumListEntries),
|
|
175
|
-
truncated: z.boolean(),
|
|
176
|
-
});
|
|
177
|
-
export const grepInputSchema = z.strictObject({
|
|
178
|
-
path: pathSchema,
|
|
179
|
-
pattern: z.string().min(1).max(maximumPatternCharacters),
|
|
180
|
-
regex: z.boolean().default(false),
|
|
181
|
-
ignoreCase: z.boolean().default(false),
|
|
182
|
-
limit: z
|
|
183
|
-
.number()
|
|
184
|
-
.int()
|
|
185
|
-
.min(1)
|
|
186
|
-
.max(maximumListEntries)
|
|
187
|
-
.default(maximumListEntries),
|
|
188
|
-
});
|
|
189
|
-
export const grepOutputSchema = z.strictObject({
|
|
190
|
-
path: pathSchema,
|
|
191
|
-
matches: z
|
|
192
|
-
.array(z.strictObject({
|
|
193
|
-
path: pathSchema,
|
|
194
|
-
line: z.number().int().positive(),
|
|
195
|
-
text: z.string(),
|
|
196
|
-
}))
|
|
197
|
-
.max(maximumListEntries),
|
|
198
|
-
truncated: z.boolean(),
|
|
199
|
-
});
|
|
200
|
-
export const editInputSchema = z.strictObject({
|
|
201
|
-
path: pathSchema,
|
|
202
|
-
oldText: boundedTextSchema(1),
|
|
203
|
-
newText: boundedTextSchema(),
|
|
204
|
-
});
|
|
205
|
-
export const editOutputSchema = z.strictObject({
|
|
206
|
-
path: pathSchema,
|
|
207
|
-
bytes: z.number().int().nonnegative(),
|
|
208
|
-
diff: z.string(),
|
|
209
|
-
firstChangedLine: z.number().int().positive().nullable(),
|
|
210
|
-
});
|
|
211
|
-
// Native Files tools and Computer HTTP decode the same patch contract.
|
|
212
|
-
export { patchInputSchema, patchOutputSchema, } from "@fungi.computer/knapsack/files-patch";
|
|
213
|
-
export const mkdirInputSchema = z.strictObject({
|
|
214
|
-
path: pathSchema,
|
|
215
|
-
recursive: z.boolean().default(true),
|
|
216
|
-
});
|
|
217
|
-
export const mkdirOutputSchema = z.strictObject({ path: pathSchema });
|
|
218
|
-
/**
|
|
219
|
-
* Host-owned idempotency key for one `exec` or `bash` tool invocation. The
|
|
220
|
-
* host mints it once per invocation and keeps it across its own retries of that
|
|
221
|
-
* invocation; the model never sees or supplies it.
|
|
222
|
-
*/
|
|
223
|
-
export const computerRequestIdSchema = z.uuid({ version: "v7" });
|
|
224
|
-
/** Mint the request ID for one host tool invocation. */
|
|
225
|
-
export function mintComputerRequestId() {
|
|
226
|
-
return computerRequestIdSchema.parse(replayKey());
|
|
227
|
-
}
|
|
228
|
-
/** Model-facing command input. It carries no request identity. */
|
|
229
|
-
function executionInputSchema(budget) {
|
|
230
|
-
return z.strictObject({
|
|
231
|
-
command: z.string().min(1).max(maximumCommandCharacters),
|
|
232
|
-
cwd: pathSchema.optional(),
|
|
233
|
-
/** An attached backend id; omitted routes by the Computer's default order. */
|
|
234
|
-
backend: attachedBackendIdSchema.optional(),
|
|
235
|
-
timeoutMs: z
|
|
236
|
-
.number()
|
|
237
|
-
.int()
|
|
238
|
-
.min(1)
|
|
239
|
-
.max(budget.maximumTimeMs)
|
|
240
|
-
.default(10_000),
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
export const execInputSchema = executionInputSchema(genericComputerExecutionBudget);
|
|
244
|
-
/** Resource hosts select a budget only after admitting their job principal. */
|
|
245
|
-
export function computerExecutionRequestSchema(budget) {
|
|
246
|
-
return executionInputSchema(budget).extend({
|
|
247
|
-
requestId: computerRequestIdSchema,
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
/** Host-to-Computer command request: the model input plus the host's ID. */
|
|
251
|
-
export const execRequestSchema = execInputSchema.extend({
|
|
252
|
-
requestId: computerRequestIdSchema,
|
|
253
|
-
});
|
|
254
|
-
export const execOutputSchema = z.strictObject({
|
|
255
|
-
status: z.enum(["completed", "failed", "cancelled"]),
|
|
256
|
-
exitCode: z.number().int(),
|
|
257
|
-
stdout: z.string(),
|
|
258
|
-
stderr: z.string(),
|
|
259
|
-
truncated: z.boolean(),
|
|
260
|
-
});
|
|
261
|
-
/** One long-running container process owned by this Computer. */
|
|
262
|
-
const processIds = defineIdFamily({
|
|
263
|
-
family: "computer-process",
|
|
264
|
-
version: 1,
|
|
265
|
-
kinds: { process: { prefix: "computer_process" } },
|
|
266
|
-
}).process;
|
|
267
|
-
export const computerProcessIdSchema = z
|
|
268
|
-
.string()
|
|
269
|
-
.refine((value) => processIds.is(value));
|
|
270
|
-
/** At most this many processes may be running in one host scope at once. */
|
|
271
|
-
export const maximumRunningProcesses = 16;
|
|
272
|
-
/** At most this many process records, running or exited, are kept per host scope. */
|
|
273
|
-
export const maximumProcessRecords = 64;
|
|
274
|
-
/** Mint the durable identity of one started process. */
|
|
275
|
-
export function mintComputerProcessId() {
|
|
276
|
-
return processIds.generate();
|
|
277
|
-
}
|
|
278
|
-
export const processStartInputSchema = z.strictObject({
|
|
279
|
-
requestId: z.string().min(1).max(256),
|
|
280
|
-
requestScope: z.string().min(1).max(512),
|
|
281
|
-
port: computerPortSchema.optional(),
|
|
282
|
-
command: z.string().min(1).max(maximumCommandCharacters),
|
|
283
|
-
cwd: pathSchema.optional(),
|
|
284
|
-
});
|
|
285
|
-
/** Model input excludes the host's replay identity and authority scope. */
|
|
286
|
-
export const processStartToolInputSchema = processStartInputSchema.omit({
|
|
287
|
-
requestId: true,
|
|
288
|
-
requestScope: true,
|
|
289
|
-
});
|
|
290
|
-
/** A trusted App host binds replay identity to its admitted installation and caller. */
|
|
291
|
-
export function installationProcessScope(installation, method, actor) {
|
|
292
|
-
return processStartInputSchema.shape.requestScope.parse(`installation:${JSON.stringify([installation, method, `${actor.kind}:${actor.id}`])}`);
|
|
293
|
-
}
|
|
294
|
-
export const processIdInputSchema = z.strictObject({
|
|
295
|
-
id: computerProcessIdSchema,
|
|
296
|
-
});
|
|
297
|
-
/**
|
|
298
|
-
* `running`: computerd still reports the execution live. `exited`: it ended;
|
|
299
|
-
* `exitCode` is null when the runtime that ran it was replaced or its record
|
|
300
|
-
* expired before the exit code was observed. `uncertain`: the Computer could
|
|
301
|
-
* not reach its container to check, so neither is claimed.
|
|
302
|
-
*/
|
|
303
|
-
export const computerProcessStateSchema = z.enum([
|
|
304
|
-
"running",
|
|
305
|
-
"exited",
|
|
306
|
-
"uncertain",
|
|
307
|
-
]);
|
|
308
|
-
/**
|
|
309
|
-
* `synced`: the drain that recorded this exit read all the way to EOF,
|
|
310
|
-
* which is also the read that runs computerd's post-command pull.
|
|
311
|
-
* `pending`: that drain gave up waiting at its own deadline (a
|
|
312
|
-
* backgrounded child, for example `node server.js &`, can hold the
|
|
313
|
-
* transport open long after its parent exits) -- a background
|
|
314
|
-
* continuation keeps watching and upgrades this row to `synced` once it
|
|
315
|
-
* reaches that real EOF, so `pending` rows stay updatable. `unknown`:
|
|
316
|
-
* this exit was recorded with no pull evidence at all (a replaced
|
|
317
|
-
* runtime, an expired record, or any other exit path that never drained
|
|
318
|
-
* for one). Never claim `synced` without the specific evidence for this
|
|
319
|
-
* exit; default to `unknown`, not `synced`.
|
|
320
|
-
*/
|
|
321
|
-
export const computerProcessSyncSchema = z.enum([
|
|
322
|
-
"synced",
|
|
323
|
-
"pending",
|
|
324
|
-
"unknown",
|
|
325
|
-
]);
|
|
326
|
-
export const computerProcessSchema = z.strictObject({
|
|
327
|
-
id: computerProcessIdSchema,
|
|
328
|
-
port: computerPortSchema.nullable(),
|
|
329
|
-
command: z.string(),
|
|
330
|
-
cwd: z.string().nullable(),
|
|
331
|
-
state: computerProcessStateSchema,
|
|
332
|
-
exitCode: z.number().int().nullable(),
|
|
333
|
-
sync: computerProcessSyncSchema,
|
|
334
|
-
startedAt: z.number().int(),
|
|
335
|
-
endedAt: z.number().int().nullable(),
|
|
336
|
-
});
|
|
337
|
-
export const processListOutputSchema = z.strictObject({
|
|
338
|
-
processes: z.array(computerProcessSchema).max(maximumProcessRecords),
|
|
339
|
-
});
|
|
340
|
-
export const processKillOutputSchema = z.strictObject({
|
|
341
|
-
process: computerProcessSchema,
|
|
342
|
-
signalled: z.boolean(),
|
|
343
|
-
});
|
|
344
|
-
/** No process with this id was started on this Computer. */
|
|
345
|
-
export class ComputerProcessNotFoundError extends Error {
|
|
346
|
-
constructor(id) {
|
|
347
|
-
super(`Computer process not found: ${id}`);
|
|
348
|
-
this.name = "ComputerProcessNotFoundError";
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
/** Every process slot is occupied by a running process. */
|
|
352
|
-
export class ComputerProcessLimitError extends Error {
|
|
353
|
-
constructor() {
|
|
354
|
-
super(`Computer process scope can run at most ${String(maximumRunningProcesses)} processes`);
|
|
355
|
-
this.name = "ComputerProcessLimitError";
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
export const computerOperationStatusSchema = z.enum([
|
|
359
|
-
"accepted",
|
|
360
|
-
"running",
|
|
361
|
-
"succeeded",
|
|
362
|
-
"failed",
|
|
363
|
-
"unknown",
|
|
364
|
-
"expired",
|
|
365
|
-
]);
|
|
366
|
-
/** Durable operation status returned to the host that owns the request ID. */
|
|
367
|
-
export const computerOperationResultSchema = z.strictObject({
|
|
368
|
-
requestId: computerRequestIdSchema,
|
|
369
|
-
status: computerOperationStatusSchema,
|
|
370
|
-
output: execOutputSchema.nullable(),
|
|
371
|
-
});
|
|
372
|
-
/** Model-facing command result: the durable status without the host's ID. */
|
|
373
|
-
export const computerToolResultSchema = computerOperationResultSchema.omit({
|
|
374
|
-
requestId: true,
|
|
375
|
-
});
|
|
376
|
-
/** Project one host operation result onto the model-facing tool result. */
|
|
377
|
-
export function computerToolResult(result) {
|
|
378
|
-
return computerToolResultSchema.parse({
|
|
379
|
-
status: result.status,
|
|
380
|
-
output: result.output,
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
/** Public operation vocabulary; transport adapters map these to routes. */
|
|
384
|
-
export const computerOperationSchema = z.enum([
|
|
385
|
-
"files.read",
|
|
386
|
-
"files.readBytes",
|
|
387
|
-
"files.write",
|
|
388
|
-
"files.writeBytes",
|
|
389
|
-
"files.list",
|
|
390
|
-
"files.glob",
|
|
391
|
-
"files.grep",
|
|
392
|
-
"files.edit",
|
|
393
|
-
"files.patch",
|
|
394
|
-
"mkdir",
|
|
395
|
-
"bash",
|
|
396
|
-
"exec",
|
|
397
|
-
]);
|
|
398
|
-
/** The expected file contents no longer match at atomic replacement. */
|
|
399
|
-
export class ComputerFileConflict extends Error {
|
|
400
|
-
constructor() {
|
|
401
|
-
super("Files edit conflict: contents changed before replacement");
|
|
402
|
-
this.name = "ComputerFileConflict";
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
/** A byte window starts beyond the current file extent. */
|
|
406
|
-
export class ComputerFileRangeError extends Error {
|
|
407
|
-
size;
|
|
408
|
-
constructor(size) {
|
|
409
|
-
super("Byte offset exceeds file size");
|
|
410
|
-
this.size = size;
|
|
411
|
-
this.name = "ComputerFileRangeError";
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
/** The requested file bytes exceed the admitted read bound. */
|
|
415
|
-
export class ComputerFileTooLargeError extends Error {
|
|
416
|
-
constructor() {
|
|
417
|
-
super("File exceeds the Computer read bound");
|
|
418
|
-
this.name = "ComputerFileTooLargeError";
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
function capability(id, kind, description, input, output) {
|
|
422
|
-
const parameters = structuredClone(z.toJSONSchema(input));
|
|
423
|
-
const result = structuredClone(z.toJSONSchema(output));
|
|
424
|
-
return computerValueSchema.parse({
|
|
425
|
-
id,
|
|
426
|
-
name: id,
|
|
427
|
-
kind,
|
|
428
|
-
description,
|
|
429
|
-
parameters,
|
|
430
|
-
output: result,
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
let capabilities;
|
|
434
|
-
/**
|
|
435
|
-
* The operations every Computer advertises; static, so hosts can describe them
|
|
436
|
-
* without a call. Built on first read: deriving JSON Schema for every operation
|
|
437
|
-
* is real work that a Worker should not pay at startup.
|
|
438
|
-
*/
|
|
439
|
-
export function computerCapabilities() {
|
|
440
|
-
capabilities ??= computerCapabilitiesSchema.parse([
|
|
441
|
-
capability("read", "fileStore", "Read one bounded UTF-8 file from this Computer.", readInputSchema, readOutputSchema),
|
|
442
|
-
capability("list", "fileStore", "List one bounded page of a directory on this Computer.", listInputSchema, listOutputSchema),
|
|
443
|
-
capability("mkdir", "fileStore", "Create a directory on this Computer.", mkdirInputSchema, mkdirOutputSchema),
|
|
444
|
-
capability("write", "fileStore", "Write one bounded UTF-8 file without creating its parent directory.", writeInputSchema, writeOutputSchema),
|
|
445
|
-
capability("bash", "runtime", "Run one bounded shell command in this Computer's Linux container, with node, npm and the programs installed there.", execInputSchema, computerToolResultSchema),
|
|
446
|
-
capability("exec", "runtime", "Run one bounded command in a lightweight Worker shell over this Computer's files. It has no node, npm or installed programs; use bash to run programs.", execInputSchema, computerToolResultSchema),
|
|
447
|
-
capability("start_process", "runtime", "Start one long-running command, such as a dev server, in this Computer's container. Returns its durable process id.", processStartToolInputSchema, computerProcessSchema),
|
|
448
|
-
capability("list_processes", "runtime", "List this Computer's started processes as running, exited or uncertain.", z.strictObject({}), processListOutputSchema),
|
|
449
|
-
capability("kill_process", "runtime", "Send SIGTERM to one running process on this Computer.", processIdInputSchema, processKillOutputSchema),
|
|
450
|
-
]);
|
|
451
|
-
return capabilities;
|
|
452
|
-
}
|