@fungi.computer/computer 0.0.0-stage → 0.0.1
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/Dockerfile +85 -0
- package/LICENSE +21 -0
- package/README.md +228 -2
- package/container/computer-init.mjs +119 -0
- package/container/computer-start.sh +24 -0
- package/container/package.json +14 -0
- package/container/pnpm-lock.yaml +378 -0
- package/container/pnpm-workspace.yaml +5 -0
- package/container/resource-bounds.mjs +54 -0
- package/container/runtime-privileges.cc +37 -0
- package/container/runtime-privileges.mjs +11 -0
- package/container/terminal-assets/README.md +35 -0
- package/container/terminal-assets/bashrc +49 -0
- package/container/terminal-assets/git-prompt.sh +586 -0
- package/container/terminal-protocol.mjs +58 -0
- package/container/terminal-runtime.mjs +10 -0
- package/container/terminal-server.mjs +243 -0
- package/dist/apply-patch/LICENSE.codex +201 -0
- package/dist/apply-patch/build.mjs +98 -0
- package/dist/apply-patch/cache.mjs +168 -0
- package/dist/apply-patch/compile.mjs +199 -0
- package/dist/apply-patch/docker/darwin.Dockerfile +15 -0
- package/dist/apply-patch/docker/linux-arm64.Dockerfile +38 -0
- package/dist/apply-patch/docker/linux-x64.Dockerfile +23 -0
- package/dist/apply-patch/main.rs +320 -0
- package/dist/apply-patch/notices.mjs +44 -0
- package/dist/apply-patch/pin.mjs +8 -0
- package/dist/apply-patch/toolchain.mjs +39 -0
- package/dist/computer-backends.d.ts +94 -0
- package/dist/computer-backends.js +103 -0
- package/dist/computerd.cjs +18010 -0
- package/dist/container-policy.d.ts +7 -0
- package/dist/container-policy.js +24 -0
- package/dist/container-system-trust.d.ts +8 -0
- package/dist/container-system-trust.js +66 -0
- package/dist/egress-policy.d.ts +89 -0
- package/dist/egress-policy.js +240 -0
- package/dist/execution-result.d.ts +3 -0
- package/dist/execution-result.js +28 -0
- package/dist/files-patch.d.ts +20 -0
- package/dist/files-patch.js +108 -0
- package/dist/files.d.ts +75 -0
- package/dist/files.js +136 -0
- package/dist/fleet/admission.d.ts +14 -0
- package/dist/fleet/admission.js +10 -0
- package/dist/fleet/backing.d.ts +52 -0
- package/dist/fleet/backing.js +242 -0
- package/dist/fleet/computers.d.ts +62 -0
- package/dist/fleet/computers.js +35 -0
- package/dist/fleet/index.d.ts +11 -0
- package/dist/fleet/index.js +11 -0
- package/dist/fleet/inventory-wire.d.ts +29 -0
- package/dist/fleet/inventory-wire.js +15 -0
- package/dist/fleet/inventory.d.ts +24 -0
- package/dist/fleet/inventory.js +152 -0
- package/dist/fleet/lifecycle.d.ts +99 -0
- package/dist/fleet/lifecycle.js +423 -0
- package/dist/fleet/runtime-usage.d.ts +50 -0
- package/dist/fleet/runtime-usage.js +145 -0
- package/dist/fleet/slots.d.ts +30 -0
- package/dist/fleet/slots.js +46 -0
- package/dist/fleet/wire.d.ts +228 -0
- package/dist/fleet/wire.js +127 -0
- package/dist/host-config.d.ts +12 -0
- package/dist/host-config.js +10 -0
- package/dist/index.d.ts +282 -0
- package/dist/index.js +1237 -0
- package/dist/light-shell.d.ts +44 -0
- package/dist/light-shell.js +376 -0
- package/dist/local-backend.d.ts +52 -0
- package/dist/local-backend.js +143 -0
- package/dist/metered-container-host.d.ts +26 -0
- package/dist/metered-container-host.js +48 -0
- package/dist/on-box-vm.d.ts +119 -0
- package/dist/on-box-vm.js +294 -0
- package/dist/operation-contract.d.ts +456 -0
- package/dist/operation-contract.js +452 -0
- package/dist/operation-record.d.ts +50 -0
- package/dist/operation-record.js +162 -0
- package/dist/preview.d.ts +55 -0
- package/dist/preview.js +151 -0
- package/dist/process-inventory.d.ts +80 -0
- package/dist/process-inventory.js +427 -0
- package/dist/pull-pending.d.ts +26 -0
- package/dist/pull-pending.js +35 -0
- package/dist/team-candidate-builder.mjs +28170 -0
- package/dist/transport-backend.d.ts +3 -0
- package/dist/transport-backend.js +99 -0
- package/dist/workspace-stream.d.ts +2 -0
- package/dist/workspace-stream.js +31 -0
- package/package.json +126 -3
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { WatchdogSqliteOwner } from "@fungi.computer/watchdog";
|
|
2
|
+
import { type ContainerRuntimeStart, type HostedBacking } from "../computer-backends.js";
|
|
3
|
+
import type { ComputerFact, ComputerProvenance, ComputerUsageInterval } from "./wire.js";
|
|
4
|
+
/**
|
|
5
|
+
* Computer-local interval ledger; the host owns usage settlement.
|
|
6
|
+
*
|
|
7
|
+
* A running runtime's checkpoint advances at most once per `checkpointMs`.
|
|
8
|
+
* Repeated reads inside one checkpoint expose the same interval so the host
|
|
9
|
+
* can deliver it idempotently.
|
|
10
|
+
*/
|
|
11
|
+
export declare class ComputerRuntimeUsage {
|
|
12
|
+
private readonly sql;
|
|
13
|
+
private readonly checkpointMs;
|
|
14
|
+
constructor(sql: WatchdogSqliteOwner["sql"], checkpointMs: number);
|
|
15
|
+
ensure(): void;
|
|
16
|
+
started(start: ContainerRuntimeStart): void;
|
|
17
|
+
touchActivity(backing: HostedBacking, at: number): void;
|
|
18
|
+
idleDeadline(runtimeId: string, idleMs: number, now: number): number | null;
|
|
19
|
+
hasOpen(backing: HostedBacking): boolean;
|
|
20
|
+
hasAnyOpen(): boolean;
|
|
21
|
+
open(): {
|
|
22
|
+
runtimeId: string;
|
|
23
|
+
backing: HostedBacking;
|
|
24
|
+
}[];
|
|
25
|
+
recycleCandidates(before: number): {
|
|
26
|
+
runtimeId: string;
|
|
27
|
+
backing: HostedBacking;
|
|
28
|
+
}[];
|
|
29
|
+
private ensureRecycle;
|
|
30
|
+
pendingRecycles(): {
|
|
31
|
+
runtimeId: string;
|
|
32
|
+
backing: Extract<HostedBacking, {
|
|
33
|
+
kind: "on-box-vm";
|
|
34
|
+
}>;
|
|
35
|
+
requestedAt: number;
|
|
36
|
+
}[];
|
|
37
|
+
requestRecycle(runtimeId: string, backing: HostedBacking, requestedAt: number): void;
|
|
38
|
+
finishRecycle(runtimeId: string): void;
|
|
39
|
+
oldestVmStart(): number | null;
|
|
40
|
+
observe(runtimeId: string, observed: {
|
|
41
|
+
running: boolean;
|
|
42
|
+
endedAt: number;
|
|
43
|
+
}): void;
|
|
44
|
+
pending(): ComputerUsageInterval[];
|
|
45
|
+
/** Read delivery facts without changing the retained checkpoint or acknowledgment. */
|
|
46
|
+
pendingFacts(computerId: string, provenance: ComputerProvenance): Extract<ComputerFact, {
|
|
47
|
+
kind: "interval";
|
|
48
|
+
}>[];
|
|
49
|
+
acknowledge(intervals: readonly ComputerUsageInterval[]): void;
|
|
50
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { hostedBackingSchema, } from "../computer-backends.js";
|
|
3
|
+
/**
|
|
4
|
+
* Computer-local interval ledger; the host owns usage settlement.
|
|
5
|
+
*
|
|
6
|
+
* A running runtime's checkpoint advances at most once per `checkpointMs`.
|
|
7
|
+
* Repeated reads inside one checkpoint expose the same interval so the host
|
|
8
|
+
* can deliver it idempotently.
|
|
9
|
+
*/
|
|
10
|
+
export class ComputerRuntimeUsage {
|
|
11
|
+
sql;
|
|
12
|
+
checkpointMs;
|
|
13
|
+
constructor(sql, checkpointMs) {
|
|
14
|
+
this.sql = sql;
|
|
15
|
+
this.checkpointMs = checkpointMs;
|
|
16
|
+
}
|
|
17
|
+
ensure() {
|
|
18
|
+
this.sql.exec("CREATE TABLE IF NOT EXISTS hub_computer_runtime_usage (runtime_id TEXT PRIMARY KEY, backing TEXT NOT NULL, started_at INTEGER NOT NULL, observed_at INTEGER NOT NULL, ended INTEGER NOT NULL CHECK (ended IN (0,1)), delivered_at INTEGER NOT NULL DEFAULT -1) STRICT");
|
|
19
|
+
this.sql.exec("CREATE TABLE IF NOT EXISTS hub_computer_runtime_activity (runtime_id TEXT PRIMARY KEY, last_activity_at INTEGER NOT NULL) STRICT");
|
|
20
|
+
}
|
|
21
|
+
started(start) {
|
|
22
|
+
this.ensure();
|
|
23
|
+
this.sql.exec("INSERT OR IGNORE INTO hub_computer_runtime_usage (runtime_id, backing, started_at, observed_at, ended) VALUES (?,?,?,?,0)", start.runtimeId, JSON.stringify(start.backing), start.startedAt, start.startedAt);
|
|
24
|
+
this.sql.exec("INSERT OR IGNORE INTO hub_computer_runtime_activity (runtime_id, last_activity_at) VALUES (?,?)", start.runtimeId, start.startedAt);
|
|
25
|
+
}
|
|
26
|
+
touchActivity(backing, at) {
|
|
27
|
+
this.ensure();
|
|
28
|
+
const encodedBacking = JSON.stringify(backing);
|
|
29
|
+
this.sql.exec("UPDATE hub_computer_runtime_activity SET last_activity_at=MAX(last_activity_at, ?) WHERE runtime_id IN (SELECT runtime_id FROM hub_computer_runtime_usage WHERE backing=? AND ended=0)", at, encodedBacking);
|
|
30
|
+
this.sql.exec("INSERT OR IGNORE INTO hub_computer_runtime_activity (runtime_id, last_activity_at) SELECT runtime_id, ? FROM hub_computer_runtime_usage WHERE backing=? AND ended=0", at, encodedBacking);
|
|
31
|
+
}
|
|
32
|
+
idleDeadline(runtimeId, idleMs, now) {
|
|
33
|
+
this.ensure();
|
|
34
|
+
this.sql.exec("INSERT OR IGNORE INTO hub_computer_runtime_activity (runtime_id, last_activity_at) SELECT runtime_id, ? FROM hub_computer_runtime_usage WHERE runtime_id=? AND ended=0", now, runtimeId);
|
|
35
|
+
const row = this.sql
|
|
36
|
+
.exec("SELECT last_activity_at FROM hub_computer_runtime_activity WHERE runtime_id=?", runtimeId)
|
|
37
|
+
.toArray()[0];
|
|
38
|
+
return row === undefined
|
|
39
|
+
? null
|
|
40
|
+
: z.number().int().nonnegative().parse(row.last_activity_at) + idleMs;
|
|
41
|
+
}
|
|
42
|
+
hasOpen(backing) {
|
|
43
|
+
this.ensure();
|
|
44
|
+
return (this.sql
|
|
45
|
+
.exec("SELECT runtime_id FROM hub_computer_runtime_usage WHERE ended=0 AND backing=? LIMIT 1", JSON.stringify(backing))
|
|
46
|
+
.toArray().length > 0);
|
|
47
|
+
}
|
|
48
|
+
hasAnyOpen() {
|
|
49
|
+
return (this.sql
|
|
50
|
+
.exec("SELECT runtime_id FROM hub_computer_runtime_usage WHERE ended=0 LIMIT 1")
|
|
51
|
+
.toArray().length > 0);
|
|
52
|
+
}
|
|
53
|
+
open() {
|
|
54
|
+
return this.sql
|
|
55
|
+
.exec("SELECT runtime_id, backing FROM hub_computer_runtime_usage WHERE ended = 0 ORDER BY started_at DESC")
|
|
56
|
+
.toArray()
|
|
57
|
+
.map((row) => ({
|
|
58
|
+
runtimeId: z.string().parse(row.runtime_id),
|
|
59
|
+
backing: hostedBackingSchema.parse(JSON.parse(z.string().parse(row.backing))),
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
recycleCandidates(before) {
|
|
63
|
+
return this.sql
|
|
64
|
+
.exec("SELECT runtime_id,backing FROM hub_computer_runtime_usage WHERE ended=0 AND started_at<=?", before)
|
|
65
|
+
.toArray()
|
|
66
|
+
.map((row) => ({
|
|
67
|
+
runtimeId: z.string().parse(row.runtime_id),
|
|
68
|
+
backing: hostedBackingSchema.parse(JSON.parse(z.string().parse(row.backing))),
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
ensureRecycle() {
|
|
72
|
+
this.sql.exec("CREATE TABLE IF NOT EXISTS hub_computer_vm_recycle (runtime_id TEXT PRIMARY KEY, backing TEXT NOT NULL, requested_at INTEGER NOT NULL) STRICT");
|
|
73
|
+
}
|
|
74
|
+
pendingRecycles() {
|
|
75
|
+
this.ensureRecycle();
|
|
76
|
+
return this.sql
|
|
77
|
+
.exec("SELECT runtime_id,backing,requested_at FROM hub_computer_vm_recycle")
|
|
78
|
+
.toArray()
|
|
79
|
+
.map((row) => {
|
|
80
|
+
const backing = hostedBackingSchema.parse(JSON.parse(z.string().parse(row.backing)));
|
|
81
|
+
if (backing.kind !== "on-box-vm")
|
|
82
|
+
throw new Error("Invalid VM recycle backing");
|
|
83
|
+
return {
|
|
84
|
+
runtimeId: z.string().parse(row.runtime_id),
|
|
85
|
+
backing,
|
|
86
|
+
requestedAt: z.number().parse(row.requested_at),
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
requestRecycle(runtimeId, backing, requestedAt) {
|
|
91
|
+
this.ensureRecycle();
|
|
92
|
+
this.sql.exec("INSERT INTO hub_computer_vm_recycle (runtime_id,backing,requested_at) VALUES (?,?,?)", runtimeId, JSON.stringify(backing), requestedAt);
|
|
93
|
+
}
|
|
94
|
+
finishRecycle(runtimeId) {
|
|
95
|
+
this.sql.exec("DELETE FROM hub_computer_vm_recycle WHERE runtime_id=?", runtimeId);
|
|
96
|
+
}
|
|
97
|
+
oldestVmStart() {
|
|
98
|
+
return z
|
|
99
|
+
.number()
|
|
100
|
+
.nullable()
|
|
101
|
+
.parse(this.sql
|
|
102
|
+
.exec("SELECT MIN(started_at) AS started_at FROM hub_computer_runtime_usage WHERE ended=0 AND json_extract(backing,'$.kind')='on-box-vm'")
|
|
103
|
+
.toArray()[0]?.started_at ?? null);
|
|
104
|
+
}
|
|
105
|
+
observe(runtimeId, observed) {
|
|
106
|
+
if (!observed.running) {
|
|
107
|
+
this.sql.exec("UPDATE hub_computer_runtime_usage SET observed_at = MAX(observed_at, ?), ended = 1 WHERE runtime_id = ?", observed.endedAt, runtimeId);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
this.sql.exec("UPDATE hub_computer_runtime_usage SET observed_at = ? WHERE runtime_id = ? AND ended = 0 AND observed_at <= ?", now, runtimeId, now - this.checkpointMs);
|
|
112
|
+
}
|
|
113
|
+
pending() {
|
|
114
|
+
return this.sql
|
|
115
|
+
.exec("SELECT runtime_id, backing, started_at, observed_at, ended FROM hub_computer_runtime_usage WHERE observed_at > delivered_at OR ended = 1 LIMIT 64")
|
|
116
|
+
.toArray()
|
|
117
|
+
.map((row) => ({
|
|
118
|
+
runtimeId: z.string().parse(row.runtime_id),
|
|
119
|
+
backing: hostedBackingSchema.parse(JSON.parse(z.string().parse(row.backing))),
|
|
120
|
+
startedAt: z.number().parse(row.started_at),
|
|
121
|
+
observedAt: z.number().parse(row.observed_at),
|
|
122
|
+
ended: row.ended === 1,
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
/** Read delivery facts without changing the retained checkpoint or acknowledgment. */
|
|
126
|
+
pendingFacts(computerId, provenance) {
|
|
127
|
+
return this.pending().map((interval) => ({
|
|
128
|
+
kind: "interval",
|
|
129
|
+
computerId,
|
|
130
|
+
provenance,
|
|
131
|
+
...interval,
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
acknowledge(intervals) {
|
|
135
|
+
for (const interval of intervals)
|
|
136
|
+
this.sql.exec("UPDATE hub_computer_runtime_usage SET delivered_at = ? WHERE runtime_id = ?", interval.observedAt, interval.runtimeId);
|
|
137
|
+
// Ended and delivered intervals live on in the host's settlement ledger only.
|
|
138
|
+
for (const interval of intervals)
|
|
139
|
+
if (interval.ended)
|
|
140
|
+
this.sql.exec("DELETE FROM hub_computer_runtime_usage WHERE runtime_id = ? AND ended = 1 AND delivered_at >= observed_at", interval.runtimeId);
|
|
141
|
+
for (const interval of intervals)
|
|
142
|
+
if (interval.ended)
|
|
143
|
+
this.sql.exec("DELETE FROM hub_computer_runtime_activity WHERE runtime_id=? AND NOT EXISTS (SELECT 1 FROM hub_computer_runtime_usage WHERE runtime_id=?)", interval.runtimeId, interval.runtimeId);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { WatchdogSqliteOwner } from "@fungi.computer/watchdog";
|
|
2
|
+
/** Reservation facts; infrastructure capacity is supplied by the host. */
|
|
3
|
+
type FleetSlotReservation = Readonly<{
|
|
4
|
+
kind: "reserved";
|
|
5
|
+
runningComputers: number;
|
|
6
|
+
}> | Readonly<{
|
|
7
|
+
kind: "capacity";
|
|
8
|
+
runningComputers: number;
|
|
9
|
+
limit: number;
|
|
10
|
+
retryAfterSeconds: number;
|
|
11
|
+
}> | Readonly<{
|
|
12
|
+
kind: "unavailable";
|
|
13
|
+
cause: unknown;
|
|
14
|
+
}>;
|
|
15
|
+
/** Atomically held hosted cold starts, independent of host policy. */
|
|
16
|
+
export declare function createFleetSlots(options: Readonly<{
|
|
17
|
+
sql: WatchdogSqliteOwner["sql"];
|
|
18
|
+
transactionSync: <T>(body: () => T) => T;
|
|
19
|
+
}>, capacity: Readonly<{
|
|
20
|
+
limit: number;
|
|
21
|
+
retryAfterSeconds: number;
|
|
22
|
+
}>): {
|
|
23
|
+
ensure: () => Readonly<{
|
|
24
|
+
toArray: () => readonly import("@fungi.computer/watchdog").WatchdogSqliteRow[];
|
|
25
|
+
}>;
|
|
26
|
+
count: () => number;
|
|
27
|
+
reserve: (computerId: string) => FleetSlotReservation;
|
|
28
|
+
release: (computerId: string) => void;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Atomically held hosted cold starts, independent of host policy. */
|
|
3
|
+
export function createFleetSlots(options, capacity) {
|
|
4
|
+
const { sql } = options;
|
|
5
|
+
const ensure = () => sql.exec(`CREATE TABLE IF NOT EXISTS hub_team_running_computers (
|
|
6
|
+
computer_id TEXT PRIMARY KEY
|
|
7
|
+
) STRICT`);
|
|
8
|
+
const count = () => {
|
|
9
|
+
const row = sql
|
|
10
|
+
.exec("SELECT COUNT(*) AS count FROM hub_team_running_computers")
|
|
11
|
+
.toArray()[0];
|
|
12
|
+
if (row === undefined)
|
|
13
|
+
throw new Error("Running Computer count missing");
|
|
14
|
+
return z.number().int().nonnegative().parse(row.count);
|
|
15
|
+
};
|
|
16
|
+
/** Capacity-only synchronous admission for a hosted cold start. */
|
|
17
|
+
const reserve = (computerId) => {
|
|
18
|
+
try {
|
|
19
|
+
return options.transactionSync(() => {
|
|
20
|
+
const existing = sql
|
|
21
|
+
.exec("SELECT computer_id FROM hub_team_running_computers WHERE computer_id = ?", computerId)
|
|
22
|
+
.toArray()[0];
|
|
23
|
+
const running = count();
|
|
24
|
+
if (existing !== undefined)
|
|
25
|
+
return { kind: "reserved", runningComputers: running };
|
|
26
|
+
if (running >= capacity.limit)
|
|
27
|
+
return {
|
|
28
|
+
kind: "capacity",
|
|
29
|
+
runningComputers: running,
|
|
30
|
+
limit: capacity.limit,
|
|
31
|
+
retryAfterSeconds: capacity.retryAfterSeconds,
|
|
32
|
+
};
|
|
33
|
+
sql.exec("INSERT INTO hub_team_running_computers (computer_id) VALUES (?)", computerId);
|
|
34
|
+
return { kind: "reserved", runningComputers: running + 1 };
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (cause) {
|
|
38
|
+
return { kind: "unavailable", cause };
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/** Releasing an absent slot is an ordinary replay from stop/sleep recovery. */
|
|
42
|
+
const release = (computerId) => {
|
|
43
|
+
options.transactionSync(() => sql.exec("DELETE FROM hub_team_running_computers WHERE computer_id = ?", computerId));
|
|
44
|
+
};
|
|
45
|
+
return { ensure, count, reserve, release };
|
|
46
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { hostedBackingSchema, type AttachedBackend } from "../computer-backends.js";
|
|
3
|
+
/** Operations the host may admit on one Computer. */
|
|
4
|
+
export declare const computerActionSchema: z.ZodEnum<{
|
|
5
|
+
exec: "exec";
|
|
6
|
+
start: "start";
|
|
7
|
+
delete: "delete";
|
|
8
|
+
"files.read": "files.read";
|
|
9
|
+
"files.readBytes": "files.readBytes";
|
|
10
|
+
"files.write": "files.write";
|
|
11
|
+
"files.writeBytes": "files.writeBytes";
|
|
12
|
+
"files.list": "files.list";
|
|
13
|
+
"files.glob": "files.glob";
|
|
14
|
+
"files.grep": "files.grep";
|
|
15
|
+
"files.edit": "files.edit";
|
|
16
|
+
"files.patch": "files.patch";
|
|
17
|
+
mkdir: "mkdir";
|
|
18
|
+
bash: "bash";
|
|
19
|
+
backing: "backing";
|
|
20
|
+
exposePort: "exposePort";
|
|
21
|
+
listPorts: "listPorts";
|
|
22
|
+
unexposePort: "unexposePort";
|
|
23
|
+
terminal: "terminal";
|
|
24
|
+
stop: "stop";
|
|
25
|
+
processStart: "processStart";
|
|
26
|
+
processList: "processList";
|
|
27
|
+
processKill: "processKill";
|
|
28
|
+
}>;
|
|
29
|
+
export type ComputerAction = z.output<typeof computerActionSchema>;
|
|
30
|
+
/** Opaque host identities; the fleet does not derive authority from their text. */
|
|
31
|
+
export declare const computerProvenanceSchema: z.ZodObject<{
|
|
32
|
+
actor: z.ZodString;
|
|
33
|
+
via: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
export type ComputerProvenance = z.output<typeof computerProvenanceSchema>;
|
|
36
|
+
/** Host-issued data, never a request body's claim to authority. Times are milliseconds. */
|
|
37
|
+
export declare const computerGrantSchema: z.ZodObject<{
|
|
38
|
+
computerId: z.ZodString;
|
|
39
|
+
actions: z.ZodReadonly<z.ZodSet<z.ZodEnum<{
|
|
40
|
+
exec: "exec";
|
|
41
|
+
start: "start";
|
|
42
|
+
delete: "delete";
|
|
43
|
+
"files.read": "files.read";
|
|
44
|
+
"files.readBytes": "files.readBytes";
|
|
45
|
+
"files.write": "files.write";
|
|
46
|
+
"files.writeBytes": "files.writeBytes";
|
|
47
|
+
"files.list": "files.list";
|
|
48
|
+
"files.glob": "files.glob";
|
|
49
|
+
"files.grep": "files.grep";
|
|
50
|
+
"files.edit": "files.edit";
|
|
51
|
+
"files.patch": "files.patch";
|
|
52
|
+
mkdir: "mkdir";
|
|
53
|
+
bash: "bash";
|
|
54
|
+
backing: "backing";
|
|
55
|
+
exposePort: "exposePort";
|
|
56
|
+
listPorts: "listPorts";
|
|
57
|
+
unexposePort: "unexposePort";
|
|
58
|
+
terminal: "terminal";
|
|
59
|
+
stop: "stop";
|
|
60
|
+
processStart: "processStart";
|
|
61
|
+
processList: "processList";
|
|
62
|
+
processKill: "processKill";
|
|
63
|
+
}>>>;
|
|
64
|
+
expiresAt: z.ZodNumber;
|
|
65
|
+
egress: z.ZodOptional<z.ZodJSONSchema>;
|
|
66
|
+
provenance: z.ZodObject<{
|
|
67
|
+
actor: z.ZodString;
|
|
68
|
+
via: z.ZodOptional<z.ZodString>;
|
|
69
|
+
}, z.core.$strict>;
|
|
70
|
+
}, z.core.$strict>;
|
|
71
|
+
export type ComputerGrant = z.output<typeof computerGrantSchema>;
|
|
72
|
+
/** State visible without knowing which application hosts the Computer. */
|
|
73
|
+
export declare const computerStateSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
74
|
+
state: z.ZodEnum<{
|
|
75
|
+
running: "running";
|
|
76
|
+
sleeping: "sleeping";
|
|
77
|
+
starting: "starting";
|
|
78
|
+
}>;
|
|
79
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
80
|
+
state: z.ZodLiteral<"queued">;
|
|
81
|
+
position: z.ZodNumber;
|
|
82
|
+
}, z.core.$strict>], "state">;
|
|
83
|
+
export type ComputerRuntimeState = z.output<typeof computerStateSchema>;
|
|
84
|
+
/** Hosted fallback order, with the same bound and identity law as the retained owner. */
|
|
85
|
+
export declare const hostedBackingsSchema: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
86
|
+
kind: z.ZodLiteral<"platform-container">;
|
|
87
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
88
|
+
kind: z.ZodLiteral<"on-box-vm">;
|
|
89
|
+
hostId: z.ZodString;
|
|
90
|
+
}, z.core.$strict>], "kind">>;
|
|
91
|
+
/** The host delivers this complete revision to its Computer runtime. */
|
|
92
|
+
export type ComputerBackendsProjection = Readonly<{
|
|
93
|
+
computerId: string;
|
|
94
|
+
revision: number;
|
|
95
|
+
backends: readonly AttachedBackend[];
|
|
96
|
+
}>;
|
|
97
|
+
/** An explicit override, or the fleet default when no Computer is selected. */
|
|
98
|
+
export declare const computerBackingChangeSchema: z.ZodObject<{
|
|
99
|
+
computerId: z.ZodOptional<z.ZodString>;
|
|
100
|
+
backings: z.ZodNullable<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
101
|
+
kind: z.ZodLiteral<"platform-container">;
|
|
102
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
103
|
+
kind: z.ZodLiteral<"on-box-vm">;
|
|
104
|
+
hostId: z.ZodString;
|
|
105
|
+
}, z.core.$strict>], "kind">>>;
|
|
106
|
+
}, z.core.$strict>;
|
|
107
|
+
export type ComputerBackingChange = Readonly<{
|
|
108
|
+
computerId?: string | undefined;
|
|
109
|
+
backings: readonly z.output<typeof hostedBackingSchema>[] | null;
|
|
110
|
+
}>;
|
|
111
|
+
/** A backing operation was refused without changing the stored decision. */
|
|
112
|
+
export declare class ComputerBackingError extends Error {
|
|
113
|
+
readonly code: "unknown_computer" | "not_enabled" | "invalid" | "request_conflict" | "local_limit" | "not_owner";
|
|
114
|
+
constructor(code: "unknown_computer" | "not_enabled" | "invalid" | "request_conflict" | "local_limit" | "not_owner");
|
|
115
|
+
}
|
|
116
|
+
/** Local device attachment uses an opaque actor supplied by the host. */
|
|
117
|
+
export declare const localBackendAttachSchema: z.ZodObject<{
|
|
118
|
+
computerId: z.ZodString;
|
|
119
|
+
publicKey: z.ZodBase64;
|
|
120
|
+
hostLabel: z.ZodString;
|
|
121
|
+
folderLabel: z.ZodString;
|
|
122
|
+
requestId: z.ZodString;
|
|
123
|
+
}, z.core.$strict>;
|
|
124
|
+
export type LocalBackendAttachInput = z.output<typeof localBackendAttachSchema>;
|
|
125
|
+
export declare const localBackendDetachSchema: z.ZodObject<{
|
|
126
|
+
computerId: z.ZodString;
|
|
127
|
+
backendId: z.ZodString;
|
|
128
|
+
}, z.core.$strict>;
|
|
129
|
+
/** Recover a lost attach response without retaining the device key. */
|
|
130
|
+
export declare const localBackendDetachRequestSchema: z.ZodObject<{
|
|
131
|
+
computerId: z.ZodString;
|
|
132
|
+
requestId: z.ZodString;
|
|
133
|
+
}, z.core.$strict>;
|
|
134
|
+
export type LocalBackendDetachInput = z.output<typeof localBackendDetachSchema> | z.output<typeof localBackendDetachRequestSchema>;
|
|
135
|
+
/** One runtime observation; the host owns delivery and settlement. */
|
|
136
|
+
export declare const computerUsageIntervalSchema: z.ZodObject<{
|
|
137
|
+
runtimeId: z.ZodString;
|
|
138
|
+
backing: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
139
|
+
kind: z.ZodLiteral<"platform-container">;
|
|
140
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
141
|
+
kind: z.ZodLiteral<"on-box-vm">;
|
|
142
|
+
hostId: z.ZodString;
|
|
143
|
+
}, z.core.$strict>], "kind">;
|
|
144
|
+
startedAt: z.ZodNumber;
|
|
145
|
+
observedAt: z.ZodNumber;
|
|
146
|
+
ended: z.ZodBoolean;
|
|
147
|
+
}, z.core.$strict>;
|
|
148
|
+
/** Spelled out: it types a Durable Object RPC parameter. */
|
|
149
|
+
export type ComputerUsageInterval = Readonly<{
|
|
150
|
+
runtimeId: string;
|
|
151
|
+
backing: Readonly<{
|
|
152
|
+
kind: "platform-container";
|
|
153
|
+
}> | Readonly<{
|
|
154
|
+
kind: "on-box-vm";
|
|
155
|
+
hostId: string;
|
|
156
|
+
}>;
|
|
157
|
+
startedAt: number;
|
|
158
|
+
observedAt: number;
|
|
159
|
+
ended: boolean;
|
|
160
|
+
}>;
|
|
161
|
+
/** Observations, not billing decisions. The host owns delivery and settlement. */
|
|
162
|
+
export declare const computerFactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
163
|
+
kind: z.ZodLiteral<"process.exited">;
|
|
164
|
+
requestId: z.ZodString;
|
|
165
|
+
exitCode: z.ZodNullable<z.ZodNumber>;
|
|
166
|
+
cpuTimeMs: z.ZodNullable<z.ZodNumber>;
|
|
167
|
+
wallTimeMs: z.ZodNumber;
|
|
168
|
+
computerId: z.ZodString;
|
|
169
|
+
provenance: z.ZodObject<{
|
|
170
|
+
actor: z.ZodString;
|
|
171
|
+
via: z.ZodOptional<z.ZodString>;
|
|
172
|
+
}, z.core.$strict>;
|
|
173
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
174
|
+
kind: z.ZodLiteral<"files.written">;
|
|
175
|
+
path: z.ZodString;
|
|
176
|
+
bytes: z.ZodNumber;
|
|
177
|
+
computerId: z.ZodString;
|
|
178
|
+
provenance: z.ZodObject<{
|
|
179
|
+
actor: z.ZodString;
|
|
180
|
+
via: z.ZodOptional<z.ZodString>;
|
|
181
|
+
}, z.core.$strict>;
|
|
182
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
183
|
+
kind: z.ZodLiteral<"egress">;
|
|
184
|
+
host: z.ZodString;
|
|
185
|
+
method: z.ZodString;
|
|
186
|
+
status: z.ZodNumber;
|
|
187
|
+
computerId: z.ZodString;
|
|
188
|
+
provenance: z.ZodObject<{
|
|
189
|
+
actor: z.ZodString;
|
|
190
|
+
via: z.ZodOptional<z.ZodString>;
|
|
191
|
+
}, z.core.$strict>;
|
|
192
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
193
|
+
kind: z.ZodLiteral<"lifecycle">;
|
|
194
|
+
observedAt: z.ZodNumber;
|
|
195
|
+
state: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
196
|
+
state: z.ZodEnum<{
|
|
197
|
+
running: "running";
|
|
198
|
+
sleeping: "sleeping";
|
|
199
|
+
starting: "starting";
|
|
200
|
+
}>;
|
|
201
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
202
|
+
state: z.ZodLiteral<"queued">;
|
|
203
|
+
position: z.ZodNumber;
|
|
204
|
+
}, z.core.$strict>], "state">;
|
|
205
|
+
computerId: z.ZodString;
|
|
206
|
+
provenance: z.ZodObject<{
|
|
207
|
+
actor: z.ZodString;
|
|
208
|
+
via: z.ZodOptional<z.ZodString>;
|
|
209
|
+
}, z.core.$strict>;
|
|
210
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
211
|
+
runtimeId: z.ZodString;
|
|
212
|
+
backing: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
213
|
+
kind: z.ZodLiteral<"platform-container">;
|
|
214
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
215
|
+
kind: z.ZodLiteral<"on-box-vm">;
|
|
216
|
+
hostId: z.ZodString;
|
|
217
|
+
}, z.core.$strict>], "kind">;
|
|
218
|
+
startedAt: z.ZodNumber;
|
|
219
|
+
observedAt: z.ZodNumber;
|
|
220
|
+
ended: z.ZodBoolean;
|
|
221
|
+
kind: z.ZodLiteral<"interval">;
|
|
222
|
+
computerId: z.ZodString;
|
|
223
|
+
provenance: z.ZodObject<{
|
|
224
|
+
actor: z.ZodString;
|
|
225
|
+
via: z.ZodOptional<z.ZodString>;
|
|
226
|
+
}, z.core.$strict>;
|
|
227
|
+
}, z.core.$strict>], "kind">;
|
|
228
|
+
export type ComputerFact = z.output<typeof computerFactSchema>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { computerOperationSchema, computerValueSchema, pathSchema, } from "../operation-contract.js";
|
|
3
|
+
import { attachedBackendId, hostedBackingSchema, localBackendSchema, } from "../computer-backends.js";
|
|
4
|
+
/** Operations the host may admit on one Computer. */
|
|
5
|
+
export const computerActionSchema = z.enum([
|
|
6
|
+
...computerOperationSchema.options,
|
|
7
|
+
"terminal",
|
|
8
|
+
"start",
|
|
9
|
+
"stop",
|
|
10
|
+
"processStart",
|
|
11
|
+
"processList",
|
|
12
|
+
"processKill",
|
|
13
|
+
"exposePort",
|
|
14
|
+
"unexposePort",
|
|
15
|
+
"listPorts",
|
|
16
|
+
"backing",
|
|
17
|
+
"delete",
|
|
18
|
+
]);
|
|
19
|
+
/** Opaque host identities; the fleet does not derive authority from their text. */
|
|
20
|
+
export const computerProvenanceSchema = z.strictObject({
|
|
21
|
+
actor: z.string().min(1),
|
|
22
|
+
via: z.string().min(1).optional(),
|
|
23
|
+
});
|
|
24
|
+
/** Host-issued data, never a request body's claim to authority. Times are milliseconds. */
|
|
25
|
+
export const computerGrantSchema = z.strictObject({
|
|
26
|
+
computerId: z.string().min(1).max(256),
|
|
27
|
+
actions: z.set(computerActionSchema).readonly(),
|
|
28
|
+
expiresAt: z.number().int().nonnegative(),
|
|
29
|
+
/** Host-specific policy data travels downward without an upward policy callback. */
|
|
30
|
+
egress: computerValueSchema.optional(),
|
|
31
|
+
provenance: computerProvenanceSchema,
|
|
32
|
+
});
|
|
33
|
+
/** State visible without knowing which application hosts the Computer. */
|
|
34
|
+
export const computerStateSchema = z.discriminatedUnion("state", [
|
|
35
|
+
z.strictObject({ state: z.enum(["running", "sleeping", "starting"]) }),
|
|
36
|
+
z.strictObject({
|
|
37
|
+
state: z.literal("queued"),
|
|
38
|
+
position: z.number().int().positive(),
|
|
39
|
+
}),
|
|
40
|
+
]);
|
|
41
|
+
/** Hosted fallback order, with the same bound and identity law as the retained owner. */
|
|
42
|
+
export const hostedBackingsSchema = z
|
|
43
|
+
.array(hostedBackingSchema)
|
|
44
|
+
.max(4)
|
|
45
|
+
.refine((backings) => new Set(backings.map(attachedBackendId)).size === backings.length, "hosted backings must be distinct");
|
|
46
|
+
/** An explicit override, or the fleet default when no Computer is selected. */
|
|
47
|
+
export const computerBackingChangeSchema = z.strictObject({
|
|
48
|
+
computerId: z.string().min(1).max(256).optional(),
|
|
49
|
+
backings: hostedBackingsSchema.nullable(),
|
|
50
|
+
});
|
|
51
|
+
/** A backing operation was refused without changing the stored decision. */
|
|
52
|
+
export class ComputerBackingError extends Error {
|
|
53
|
+
code;
|
|
54
|
+
constructor(code) {
|
|
55
|
+
super(`Computer backing refused: ${code}`);
|
|
56
|
+
this.code = code;
|
|
57
|
+
this.name = "ComputerBackingError";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Local device attachment uses an opaque actor supplied by the host. */
|
|
61
|
+
export const localBackendAttachSchema = z.strictObject({
|
|
62
|
+
computerId: z.string().min(1).max(256),
|
|
63
|
+
publicKey: localBackendSchema.shape.publicKey,
|
|
64
|
+
hostLabel: localBackendSchema.shape.hostLabel,
|
|
65
|
+
folderLabel: localBackendSchema.shape.folderLabel,
|
|
66
|
+
requestId: z.string().min(1).max(256),
|
|
67
|
+
});
|
|
68
|
+
export const localBackendDetachSchema = z.strictObject({
|
|
69
|
+
computerId: z.string().min(1).max(256),
|
|
70
|
+
backendId: z.string().regex(/^local-[a-z2-7]{16}$/),
|
|
71
|
+
});
|
|
72
|
+
/** Recover a lost attach response without retaining the device key. */
|
|
73
|
+
export const localBackendDetachRequestSchema = z.strictObject({
|
|
74
|
+
computerId: localBackendAttachSchema.shape.computerId,
|
|
75
|
+
requestId: localBackendAttachSchema.shape.requestId,
|
|
76
|
+
});
|
|
77
|
+
const factIdentity = {
|
|
78
|
+
computerId: computerGrantSchema.shape.computerId,
|
|
79
|
+
provenance: computerProvenanceSchema,
|
|
80
|
+
};
|
|
81
|
+
/** One runtime observation; the host owns delivery and settlement. */
|
|
82
|
+
export const computerUsageIntervalSchema = z.strictObject({
|
|
83
|
+
runtimeId: z.string().min(1).max(128),
|
|
84
|
+
backing: hostedBackingSchema,
|
|
85
|
+
startedAt: z.number().int().nonnegative(),
|
|
86
|
+
/** The last observed instant; final once `ended` is true. */
|
|
87
|
+
observedAt: z.number().int().nonnegative(),
|
|
88
|
+
ended: z.boolean(),
|
|
89
|
+
});
|
|
90
|
+
const timestamp = z.number().int().nonnegative();
|
|
91
|
+
/** Observations, not billing decisions. The host owns delivery and settlement. */
|
|
92
|
+
export const computerFactSchema = z.discriminatedUnion("kind", [
|
|
93
|
+
z.strictObject({
|
|
94
|
+
...factIdentity,
|
|
95
|
+
kind: z.literal("process.exited"),
|
|
96
|
+
requestId: z.string().min(1),
|
|
97
|
+
exitCode: z.number().int().nullable(),
|
|
98
|
+
/** Null means the backend did not measure CPU; it does not mean zero usage. */
|
|
99
|
+
cpuTimeMs: z.number().nonnegative().nullable(),
|
|
100
|
+
wallTimeMs: z.number().nonnegative(),
|
|
101
|
+
}),
|
|
102
|
+
z.strictObject({
|
|
103
|
+
...factIdentity,
|
|
104
|
+
kind: z.literal("files.written"),
|
|
105
|
+
path: pathSchema,
|
|
106
|
+
bytes: z.number().int().nonnegative(),
|
|
107
|
+
}),
|
|
108
|
+
z.strictObject({
|
|
109
|
+
...factIdentity,
|
|
110
|
+
kind: z.literal("egress"),
|
|
111
|
+
/** Only the destination host; URLs may carry credentials in paths or queries. */
|
|
112
|
+
host: z.string().min(1),
|
|
113
|
+
method: z.string().min(1),
|
|
114
|
+
status: z.number().int().min(100).max(599),
|
|
115
|
+
}),
|
|
116
|
+
z.strictObject({
|
|
117
|
+
...factIdentity,
|
|
118
|
+
kind: z.literal("lifecycle"),
|
|
119
|
+
observedAt: timestamp,
|
|
120
|
+
state: computerStateSchema,
|
|
121
|
+
}),
|
|
122
|
+
z.strictObject({
|
|
123
|
+
...factIdentity,
|
|
124
|
+
kind: z.literal("interval"),
|
|
125
|
+
...computerUsageIntervalSchema.shape,
|
|
126
|
+
}),
|
|
127
|
+
]);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** One VM host's active capacity, including slots held back as headroom. */
|
|
3
|
+
export declare const hostCapacitySchema: z.ZodObject<{
|
|
4
|
+
maxActive: z.ZodNumber;
|
|
5
|
+
reservedHeadroom: z.ZodNumber;
|
|
6
|
+
}, z.core.$strict>;
|
|
7
|
+
/** Public Computer host capacity configuration, keyed by registered host ID. */
|
|
8
|
+
export declare const hostCapacityRegistrySchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
9
|
+
maxActive: z.ZodNumber;
|
|
10
|
+
reservedHeadroom: z.ZodNumber;
|
|
11
|
+
}, z.core.$strict>>;
|
|
12
|
+
export type HostCapacity = z.infer<typeof hostCapacitySchema>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** One VM host's active capacity, including slots held back as headroom. */
|
|
3
|
+
export const hostCapacitySchema = z
|
|
4
|
+
.strictObject({
|
|
5
|
+
maxActive: z.number().int().positive(),
|
|
6
|
+
reservedHeadroom: z.number().int().nonnegative(),
|
|
7
|
+
})
|
|
8
|
+
.refine((value) => value.reservedHeadroom < value.maxActive);
|
|
9
|
+
/** Public Computer host capacity configuration, keyed by registered host ID. */
|
|
10
|
+
export const hostCapacityRegistrySchema = z.record(z.string(), hostCapacitySchema);
|