@tealbrick/avm 0.1.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/LICENSE +21 -0
- package/PROVENANCE.md +38 -0
- package/README.md +165 -0
- package/dist/_chunks/extension-CS1otfhf.mjs +232 -0
- package/dist/_chunks/src-BhUiVsTW.mjs +522 -0
- package/dist/client/administration.d.ts +3 -0
- package/dist/client/administration.js +145 -0
- package/dist/client/config.d.ts +1125 -0
- package/dist/client/config.js +257 -0
- package/dist/client/index.d.ts +126 -0
- package/dist/client/index.js +364 -0
- package/dist/extension/_manifest.json +11 -0
- package/dist/extension/extension.d.ts +626 -0
- package/dist/extension/extension.mjs +8 -0
- package/dist/extension/tools/action.d.ts +24 -0
- package/dist/extension/tools/action.mjs +46 -0
- package/dist/extension/tools/inspect.d.ts +50 -0
- package/dist/extension/tools/inspect.mjs +66 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +8 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.mjs +9 -0
- package/package.json +70 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const id = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/);
|
|
3
|
+
const workspace = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);
|
|
4
|
+
const user = z.string().regex(/^[a-z][a-z0-9_-]{0,63}$/);
|
|
5
|
+
const nonnegative = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
6
|
+
const publicValue = z
|
|
7
|
+
.string()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(512)
|
|
10
|
+
.regex(/^[^\0\r\n]+$/);
|
|
11
|
+
const provider = z.string().regex(/^[a-z][a-z0-9._-]{0,63}$/);
|
|
12
|
+
const positive = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
|
|
13
|
+
const path = z
|
|
14
|
+
.string()
|
|
15
|
+
.regex(/^\/[A-Za-z0-9_./ -]+$/)
|
|
16
|
+
.max(4096);
|
|
17
|
+
const queue = {
|
|
18
|
+
weight: positive.optional(),
|
|
19
|
+
concurrentHeavyWork: nonnegative.optional(),
|
|
20
|
+
queuePolicy: z.enum(["fair", "fifo", "reject"]).optional(),
|
|
21
|
+
};
|
|
22
|
+
export const administrationSchema = z.discriminatedUnion("operation", [
|
|
23
|
+
z
|
|
24
|
+
.object({
|
|
25
|
+
operation: z.literal("tenantSync"),
|
|
26
|
+
workspace,
|
|
27
|
+
displayName: publicValue.optional(),
|
|
28
|
+
principalId: user.optional(),
|
|
29
|
+
issuer: z.url().optional(),
|
|
30
|
+
subject: publicValue.optional(),
|
|
31
|
+
role: z.enum(["member", "admin", "operator"]).default("member"),
|
|
32
|
+
...queue,
|
|
33
|
+
})
|
|
34
|
+
.strict(),
|
|
35
|
+
z
|
|
36
|
+
.object({
|
|
37
|
+
operation: z.literal("ingressPut"),
|
|
38
|
+
provider,
|
|
39
|
+
externalIdentity: publicValue,
|
|
40
|
+
worker: id,
|
|
41
|
+
channelScope: publicValue.optional(),
|
|
42
|
+
metadataFile: path.optional(),
|
|
43
|
+
})
|
|
44
|
+
.strict(),
|
|
45
|
+
z.object({ operation: z.literal("ingressRevoke"), identityId: id }).strict(),
|
|
46
|
+
z
|
|
47
|
+
.object({
|
|
48
|
+
operation: z.literal("ingressWake"),
|
|
49
|
+
provider,
|
|
50
|
+
externalIdentity: publicValue,
|
|
51
|
+
eventId: publicValue,
|
|
52
|
+
channelScope: publicValue.optional(),
|
|
53
|
+
payloadFile: path.optional(),
|
|
54
|
+
correlationId: publicValue.optional(),
|
|
55
|
+
})
|
|
56
|
+
.strict(),
|
|
57
|
+
z
|
|
58
|
+
.object({
|
|
59
|
+
operation: z.literal("ingressComplete"),
|
|
60
|
+
wakeId: id,
|
|
61
|
+
error: publicValue.optional(),
|
|
62
|
+
})
|
|
63
|
+
.strict(),
|
|
64
|
+
z
|
|
65
|
+
.object({
|
|
66
|
+
operation: z.literal("resize"),
|
|
67
|
+
worker: id,
|
|
68
|
+
memoryTargetMiB: positive,
|
|
69
|
+
})
|
|
70
|
+
.strict(),
|
|
71
|
+
z
|
|
72
|
+
.object({
|
|
73
|
+
operation: z.literal("workspacePut"),
|
|
74
|
+
workspace,
|
|
75
|
+
displayName: z
|
|
76
|
+
.string()
|
|
77
|
+
.min(1)
|
|
78
|
+
.max(256)
|
|
79
|
+
.regex(/^[^\0\r\n]+$/)
|
|
80
|
+
.optional(),
|
|
81
|
+
...queue,
|
|
82
|
+
})
|
|
83
|
+
.strict(),
|
|
84
|
+
z.object({ operation: z.literal("workspaceDisable"), workspace }).strict(),
|
|
85
|
+
z
|
|
86
|
+
.object({
|
|
87
|
+
operation: z.literal("userPut"),
|
|
88
|
+
user,
|
|
89
|
+
workspace,
|
|
90
|
+
role: z.enum(["member", "admin", "operator"]),
|
|
91
|
+
})
|
|
92
|
+
.strict(),
|
|
93
|
+
z
|
|
94
|
+
.object({
|
|
95
|
+
operation: z.literal("ownerSet"),
|
|
96
|
+
worker: id,
|
|
97
|
+
workspace,
|
|
98
|
+
user: user.optional(),
|
|
99
|
+
})
|
|
100
|
+
.strict(),
|
|
101
|
+
z
|
|
102
|
+
.object({
|
|
103
|
+
operation: z.literal("shareGrant"),
|
|
104
|
+
worker: id,
|
|
105
|
+
grantee: z.discriminatedUnion("kind", [
|
|
106
|
+
z.object({ kind: z.literal("workspace"), id: workspace }).strict(),
|
|
107
|
+
z.object({ kind: z.literal("user"), id: user }).strict(),
|
|
108
|
+
]),
|
|
109
|
+
allow: z
|
|
110
|
+
.array(z.enum([
|
|
111
|
+
"status",
|
|
112
|
+
"exec",
|
|
113
|
+
"start",
|
|
114
|
+
"stop",
|
|
115
|
+
"ssh",
|
|
116
|
+
"logs",
|
|
117
|
+
"events",
|
|
118
|
+
"runs",
|
|
119
|
+
"assignments",
|
|
120
|
+
"schedule",
|
|
121
|
+
"capabilities",
|
|
122
|
+
"auth",
|
|
123
|
+
"leases",
|
|
124
|
+
"resident",
|
|
125
|
+
"wake",
|
|
126
|
+
"cool",
|
|
127
|
+
"list",
|
|
128
|
+
"inventory",
|
|
129
|
+
"monitor",
|
|
130
|
+
"roles",
|
|
131
|
+
"ingress",
|
|
132
|
+
]))
|
|
133
|
+
.min(1),
|
|
134
|
+
})
|
|
135
|
+
.strict(),
|
|
136
|
+
z
|
|
137
|
+
.object({ operation: z.literal("shareRevoke"), worker: id, shareId: id })
|
|
138
|
+
.strict(),
|
|
139
|
+
z.object({ operation: z.literal("residentSet"), worker: id }).strict(),
|
|
140
|
+
z
|
|
141
|
+
.object({
|
|
142
|
+
operation: z.literal("wake"),
|
|
143
|
+
worker: id,
|
|
144
|
+
reason: z.string().min(1).max(256).optional(),
|
|
145
|
+
source: z
|
|
146
|
+
.enum(["cli", "schedule", "control-plane", "delegation"])
|
|
147
|
+
.default("cli"),
|
|
148
|
+
externalEventId: id.optional(),
|
|
149
|
+
idempotencyKey: id,
|
|
150
|
+
})
|
|
151
|
+
.strict(),
|
|
152
|
+
z.object({ operation: z.literal("cool"), worker: id }).strict(),
|
|
153
|
+
z
|
|
154
|
+
.object({
|
|
155
|
+
operation: z.literal("poolPolicySet"),
|
|
156
|
+
cpuPercent: positive.optional(),
|
|
157
|
+
memoryMaxBytes: positive.optional(),
|
|
158
|
+
memoryHighBytes: positive.optional(),
|
|
159
|
+
hostMemoryReserveBytes: nonnegative.optional(),
|
|
160
|
+
launchReserveBytes: nonnegative.optional(),
|
|
161
|
+
})
|
|
162
|
+
.strict(),
|
|
163
|
+
]);
|
|
164
|
+
export const policySchema = z
|
|
165
|
+
.object({
|
|
166
|
+
lifecycle: z
|
|
167
|
+
.array(z
|
|
168
|
+
.object({
|
|
169
|
+
worker: id,
|
|
170
|
+
operations: z.array(z.enum(["start", "stop", "promote", "destroy"])),
|
|
171
|
+
})
|
|
172
|
+
.strict())
|
|
173
|
+
.default([]),
|
|
174
|
+
spawns: z
|
|
175
|
+
.array(z
|
|
176
|
+
.object({
|
|
177
|
+
worker: id,
|
|
178
|
+
profile: z.enum(["light", "small", "standard", "browser"]),
|
|
179
|
+
mode: z.enum(["ephemeral", "durable"]),
|
|
180
|
+
harnesses: z.array(z.string()).optional(),
|
|
181
|
+
bundles: z.array(z.string()).optional(),
|
|
182
|
+
capabilities: z.array(z.string()).optional(),
|
|
183
|
+
mcps: z.array(z.string()).optional(),
|
|
184
|
+
plugins: z.array(z.string()).optional(),
|
|
185
|
+
auth: z
|
|
186
|
+
.array(z
|
|
187
|
+
.string()
|
|
188
|
+
.regex(/^[a-z][a-z0-9_-]*=(none|local)$|^codex=shared$/))
|
|
189
|
+
.optional(),
|
|
190
|
+
})
|
|
191
|
+
.strict())
|
|
192
|
+
.default([]),
|
|
193
|
+
commands: z
|
|
194
|
+
.array(z
|
|
195
|
+
.object({
|
|
196
|
+
worker: id,
|
|
197
|
+
command: id,
|
|
198
|
+
argv: z
|
|
199
|
+
.array(z
|
|
200
|
+
.string()
|
|
201
|
+
.max(8192)
|
|
202
|
+
.refine((v) => !v.includes("\0")))
|
|
203
|
+
.min(1)
|
|
204
|
+
.max(100),
|
|
205
|
+
})
|
|
206
|
+
.strict())
|
|
207
|
+
.default([]),
|
|
208
|
+
administration: z
|
|
209
|
+
.array(z.object({ name: id, request: administrationSchema }).strict())
|
|
210
|
+
.default([]),
|
|
211
|
+
})
|
|
212
|
+
.strict();
|
|
213
|
+
export const connectionSchema = z
|
|
214
|
+
.object({
|
|
215
|
+
target: z
|
|
216
|
+
.string()
|
|
217
|
+
.regex(/^(?:[A-Za-z0-9_][A-Za-z0-9_.-]*@)?[A-Za-z0-9][A-Za-z0-9.-]*$/),
|
|
218
|
+
mode: z.enum(["operator", "paired"]).default("operator"),
|
|
219
|
+
sudo: z.boolean().default(false),
|
|
220
|
+
identityFile: path.optional(),
|
|
221
|
+
identityTokenFile: path.optional(),
|
|
222
|
+
timeoutMs: z.number().int().min(1).max(300000).default(30000),
|
|
223
|
+
policy: policySchema.default({
|
|
224
|
+
lifecycle: [],
|
|
225
|
+
spawns: [],
|
|
226
|
+
commands: [],
|
|
227
|
+
administration: [],
|
|
228
|
+
}),
|
|
229
|
+
})
|
|
230
|
+
.strict()
|
|
231
|
+
.refine((c) => c.mode !== "paired" ||
|
|
232
|
+
(c.target.startsWith("agentvm-client@") &&
|
|
233
|
+
!c.sudo &&
|
|
234
|
+
!!c.identityFile &&
|
|
235
|
+
!c.identityTokenFile), {
|
|
236
|
+
message: "Paired mode requires agentvm-client@host and its bound SSH identity file and disallows sudo or identity token overrides",
|
|
237
|
+
});
|
|
238
|
+
/** The operator selects one connection; tools cannot choose another identity or policy. */
|
|
239
|
+
export const avmConfigSchema = z.union([
|
|
240
|
+
connectionSchema,
|
|
241
|
+
z
|
|
242
|
+
.object({ selectedProfile: id, profiles: z.record(id, connectionSchema) })
|
|
243
|
+
.strict()
|
|
244
|
+
.transform((c, ctx) => {
|
|
245
|
+
const selected = Object.hasOwn(c.profiles, c.selectedProfile)
|
|
246
|
+
? c.profiles[c.selectedProfile]
|
|
247
|
+
: undefined;
|
|
248
|
+
if (!selected) {
|
|
249
|
+
ctx.addIssue({
|
|
250
|
+
code: "custom",
|
|
251
|
+
message: "Unknown AVM connection profile",
|
|
252
|
+
});
|
|
253
|
+
return z.NEVER;
|
|
254
|
+
}
|
|
255
|
+
return selected;
|
|
256
|
+
}),
|
|
257
|
+
]);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { AdministrationRequest } from "./config.js";
|
|
2
|
+
export { avmConfigSchema, connectionSchema, policySchema, administrationSchema, } from "./config.js";
|
|
3
|
+
export type { AvmConfig, AdministrationRequest } from "./config.js";
|
|
4
|
+
export declare const AVMM_COMPATIBILITY: {
|
|
5
|
+
readonly version: "0.13.0-alpha.2";
|
|
6
|
+
readonly revision: "75078743b9bfc2ba268f1fdeea74f298983dfac4";
|
|
7
|
+
};
|
|
8
|
+
export type Json = null | boolean | number | string | Json[] | {
|
|
9
|
+
[key: string]: Json;
|
|
10
|
+
};
|
|
11
|
+
export type ReadRequest = {
|
|
12
|
+
operation: "doctor" | "inventory" | "workers" | "bundles" | "monitor" | "poolStatus" | "poolPressure" | "poolQueue" | "poolPolicy" | "workspaces" | "users" | "resident";
|
|
13
|
+
} | {
|
|
14
|
+
operation: "workerStatus" | "capabilities" | "owner" | "shares";
|
|
15
|
+
worker: string;
|
|
16
|
+
} | {
|
|
17
|
+
operation: "runs";
|
|
18
|
+
limit?: number;
|
|
19
|
+
} | {
|
|
20
|
+
operation: "events";
|
|
21
|
+
limit?: number;
|
|
22
|
+
worker?: string;
|
|
23
|
+
event?: string;
|
|
24
|
+
runId?: string;
|
|
25
|
+
} | {
|
|
26
|
+
operation: "workspace" | "user";
|
|
27
|
+
id: string;
|
|
28
|
+
} | {
|
|
29
|
+
operation: "ingress";
|
|
30
|
+
worker?: string;
|
|
31
|
+
} | {
|
|
32
|
+
operation: "runStatus";
|
|
33
|
+
runId: string;
|
|
34
|
+
};
|
|
35
|
+
export type SpawnGrant = {
|
|
36
|
+
worker: string;
|
|
37
|
+
profile: "light" | "small" | "standard" | "browser";
|
|
38
|
+
mode: "ephemeral" | "durable";
|
|
39
|
+
mcps?: readonly string[];
|
|
40
|
+
plugins?: readonly string[];
|
|
41
|
+
auth?: readonly string[];
|
|
42
|
+
harnesses?: readonly string[];
|
|
43
|
+
bundles?: readonly string[];
|
|
44
|
+
capabilities?: readonly string[];
|
|
45
|
+
};
|
|
46
|
+
export type MutationRequest = {
|
|
47
|
+
operation: "configured";
|
|
48
|
+
action: string;
|
|
49
|
+
} | {
|
|
50
|
+
operation: "spawn";
|
|
51
|
+
worker: string;
|
|
52
|
+
} | {
|
|
53
|
+
operation: "start" | "stop" | "promote" | "destroy";
|
|
54
|
+
worker: string;
|
|
55
|
+
} | {
|
|
56
|
+
operation: "exec";
|
|
57
|
+
worker: string;
|
|
58
|
+
command: string;
|
|
59
|
+
};
|
|
60
|
+
export type Request = ReadRequest | MutationRequest;
|
|
61
|
+
export interface CommandGrant {
|
|
62
|
+
worker: string;
|
|
63
|
+
command: string;
|
|
64
|
+
argv: readonly string[];
|
|
65
|
+
}
|
|
66
|
+
export interface Policy {
|
|
67
|
+
administration?: readonly {
|
|
68
|
+
name: string;
|
|
69
|
+
request: AdministrationRequest;
|
|
70
|
+
}[];
|
|
71
|
+
spawns?: readonly SpawnGrant[];
|
|
72
|
+
lifecycle?: readonly {
|
|
73
|
+
worker: string;
|
|
74
|
+
operations: readonly ("start" | "stop" | "promote" | "destroy")[];
|
|
75
|
+
}[];
|
|
76
|
+
commands?: readonly CommandGrant[];
|
|
77
|
+
}
|
|
78
|
+
export interface TransportResult {
|
|
79
|
+
stdout: string;
|
|
80
|
+
exitCode: number;
|
|
81
|
+
}
|
|
82
|
+
export interface Transport {
|
|
83
|
+
run(argv: readonly string[], options: {
|
|
84
|
+
signal: AbortSignal;
|
|
85
|
+
}): Promise<TransportResult>;
|
|
86
|
+
}
|
|
87
|
+
export type ErrorCode = "INVALID_REQUEST" | "DENIED" | "TIMEOUT" | "CANCELLED" | "TRANSPORT" | "PROTOCOL" | "REMOTE" | "GUEST_FAILED" | "OUTPUT_LIMIT";
|
|
88
|
+
/** Errors intentionally exclude command arguments, remote messages, stdout and stderr. */
|
|
89
|
+
export declare class AvmError extends Error {
|
|
90
|
+
readonly code: ErrorCode;
|
|
91
|
+
readonly exitCode?: number | undefined;
|
|
92
|
+
constructor(code: ErrorCode, exitCode?: number | undefined);
|
|
93
|
+
}
|
|
94
|
+
export declare function commandArgv(request: Request, policy?: Policy): string[];
|
|
95
|
+
export declare class AvmClient {
|
|
96
|
+
private readonly transport;
|
|
97
|
+
private readonly policy;
|
|
98
|
+
constructor(transport: Transport, options?: {
|
|
99
|
+
policy?: Policy;
|
|
100
|
+
timeoutMs?: number;
|
|
101
|
+
});
|
|
102
|
+
private readonly timeoutMs;
|
|
103
|
+
request(request: Request, options?: {
|
|
104
|
+
signal?: AbortSignal;
|
|
105
|
+
}): Promise<Json>;
|
|
106
|
+
}
|
|
107
|
+
/** Executes host-owned AVM remotely: operator JSON stdin or paired, quoted ForceCommand protocol. */
|
|
108
|
+
export declare class SshTransport implements Transport {
|
|
109
|
+
private readonly target;
|
|
110
|
+
private readonly mode;
|
|
111
|
+
private readonly identityFile?;
|
|
112
|
+
private readonly identityTokenFile?;
|
|
113
|
+
private readonly command;
|
|
114
|
+
private readonly maxOutputBytes;
|
|
115
|
+
constructor(options: {
|
|
116
|
+
target: string;
|
|
117
|
+
mode?: "operator" | "paired";
|
|
118
|
+
identityFile?: string;
|
|
119
|
+
identityTokenFile?: string;
|
|
120
|
+
sudo?: boolean;
|
|
121
|
+
maxOutputBytes?: number;
|
|
122
|
+
});
|
|
123
|
+
run(argv: readonly string[], { signal }: {
|
|
124
|
+
signal: AbortSignal;
|
|
125
|
+
}): Promise<TransportResult>;
|
|
126
|
+
}
|