nylorun 0.16.0-beta → 0.17.0-beta
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/CHANGELOG.md +41 -0
- package/README.md +111 -67
- package/dist/cli.js +31 -12
- package/dist/client/agent-manifests.d.ts +4 -0
- package/dist/client/agent-manifests.js +100 -0
- package/dist/client/agents.d.ts +1 -3
- package/dist/client/agents.js +459 -117
- package/dist/client/apply.d.ts +7 -0
- package/dist/client/apply.js +99 -0
- package/dist/client/artifacts.js +3 -3
- package/dist/client/doctor.d.ts +1 -1
- package/dist/client/doctor.js +2 -2
- package/dist/client/io.d.ts +2 -0
- package/dist/client/io.js +11 -0
- package/dist/client/mcp.d.ts +5 -3
- package/dist/client/mcp.js +27 -22
- package/dist/client/migrate.d.ts +4 -0
- package/dist/client/migrate.js +140 -0
- package/dist/client/model/pi-ai.d.ts +1 -1
- package/dist/client/model/pi-ai.js +1 -1
- package/dist/client/models.d.ts +5 -2
- package/dist/client/models.js +14 -6
- package/dist/client/runtime.js +3 -3
- package/dist/client/sessions.js +29 -18
- package/dist/client/settings.d.ts +4 -4
- package/dist/client/settings.js +16 -17
- package/dist/client/tenant.d.ts +1 -1
- package/dist/client/tenant.js +9 -6
- package/package.json +9 -9
- package/dist/client/environment-manifests.d.ts +0 -10
- package/dist/client/environment-manifests.js +0 -173
- package/dist/client/environments.d.ts +0 -4
- package/dist/client/environments.js +0 -295
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import { manifestsCommand, manifestsUsage } from "./environment-manifests.js";
|
|
2
|
-
import { readSecret } from "./io.js";
|
|
3
|
-
import { integerFlag, labelsOf, parseFlags, positional, printCursor, printJson, printTable, readJson, runtimeCall, runtimeClient, runtimeFlagsUsage, usageError, } from "./runtime.js";
|
|
4
|
-
export const environmentsUsage = `nylorun environments <command>
|
|
5
|
-
|
|
6
|
-
The Tenant's Environments (one sandbox and one vault each), through the Runtime API with an
|
|
7
|
-
application key (or NYLORUN_TOKEN).
|
|
8
|
-
|
|
9
|
-
list [--label <key=value>]... [--behind] [--limit <n>] [--cursor <c>] [--json]
|
|
10
|
-
id, kind, manifest, state, sessions and labels;
|
|
11
|
-
--behind: those made from an older manifest version
|
|
12
|
-
get <id> the Environment, as JSON
|
|
13
|
-
put <id> --manifest <name[@n]> [--label <key=value>]...
|
|
14
|
-
put <id> [<inline.json|->] [--kind <virtual|pod|none>] [--label <key=value>]...
|
|
15
|
-
create it from a manifest (its latest version, or n)
|
|
16
|
-
or inline fields, or find it and change its labels
|
|
17
|
-
(what it runs never changes: fork it for that)
|
|
18
|
-
fork <id> <new-id> [--manifest <name[@n]>] [--disk <latest|n|empty>]
|
|
19
|
-
[--secrets <copy|none>] [--label <key=value>]... [--dry-run]
|
|
20
|
-
a new Environment from a manifest version (default
|
|
21
|
-
its manifest's latest), with this one's disk and the
|
|
22
|
-
secrets it declares; --dry-run prints the plan
|
|
23
|
-
stop <id> | reset <id> stop its sandbox; reset its disk
|
|
24
|
-
delete <id> delete it: its sandbox, files and vault (refused while a
|
|
25
|
-
turn runs in it)
|
|
26
|
-
snapshot <id> keep a version of its disk
|
|
27
|
-
versions <id> its disk versions
|
|
28
|
-
restore <id> <version|latest> put a version of its disk back
|
|
29
|
-
delete-version <id> <version>
|
|
30
|
-
events <id> [--from <n>] [--types <type,…>] [--since <time>] [--until <time>]
|
|
31
|
-
its events (lifecycle, and environment.egress for every
|
|
32
|
-
connection, naming the turns running), as JSON
|
|
33
|
-
secrets list <id> its secrets' names, types and bindings (never a value)
|
|
34
|
-
secrets get <id> <name>
|
|
35
|
-
secrets put <id> <name> the value of a slot its manifest declares, piped in
|
|
36
|
-
on standard input
|
|
37
|
-
secrets put <id> <name> <secret.json|->
|
|
38
|
-
create or replace a secret: {"type": "bearer", ...}, read
|
|
39
|
-
from a file or standard input
|
|
40
|
-
secrets rm <id> <name>
|
|
41
|
-
${manifestsUsage}
|
|
42
|
-
|
|
43
|
-
${runtimeFlagsUsage}`;
|
|
44
|
-
async function list(deps, args) {
|
|
45
|
-
const usage = "nylorun environments list [--label <key=value>]... [--behind] [--limit <n>] [--cursor <c>] [--json]";
|
|
46
|
-
const flags = parseFlags(args, { booleans: ["--json", "--behind"], values: ["--limit", "--cursor"], lists: ["--label"] }, usage);
|
|
47
|
-
positional(flags, 0, usage);
|
|
48
|
-
const labels = labelsOf(flags);
|
|
49
|
-
const limit = integerFlag(flags, "--limit");
|
|
50
|
-
const cursor = flags.values.get("--cursor");
|
|
51
|
-
const { client, connection } = await runtimeClient(deps, flags);
|
|
52
|
-
const paged = limit !== undefined || cursor !== undefined;
|
|
53
|
-
const page = paged
|
|
54
|
-
? await runtimeCall(() => client.environments.page({
|
|
55
|
-
...(labels ? { labels } : {}),
|
|
56
|
-
...(limit === undefined ? {} : { limit }),
|
|
57
|
-
...(cursor ? { cursor } : {}),
|
|
58
|
-
}))
|
|
59
|
-
: {
|
|
60
|
-
environments: await runtimeCall(() => client.environments.list(labels ? { labels } : {})),
|
|
61
|
-
nextCursor: null,
|
|
62
|
-
};
|
|
63
|
-
let environments = page.environments;
|
|
64
|
-
if (flags.booleans.has("--behind")) {
|
|
65
|
-
// Made from a manifest version older than its latest: fork them to move on (D63).
|
|
66
|
-
const latest = new Map((await runtimeCall(() => client.environments.manifests.list())).map((manifest) => [manifest.name, manifest.version]));
|
|
67
|
-
environments = environments.filter((environment) => environment.manifestName !== undefined &&
|
|
68
|
-
(environment.manifestVersion ?? 0) < (latest.get(environment.manifestName) ?? 0));
|
|
69
|
-
}
|
|
70
|
-
if (flags.booleans.has("--json")) {
|
|
71
|
-
printJson(deps, paged ? page : environments);
|
|
72
|
-
return 0;
|
|
73
|
-
}
|
|
74
|
-
if (environments.length === 0)
|
|
75
|
-
deps.out(`No Environments on ${connection.label}.`);
|
|
76
|
-
else
|
|
77
|
-
printTable(deps, [
|
|
78
|
-
["ID", "KIND", "MANIFEST", "STATE", "SESSIONS", "LABELS"],
|
|
79
|
-
...environments.map((environment) => [
|
|
80
|
-
environment.id,
|
|
81
|
-
environment.kind,
|
|
82
|
-
environment.manifestName === undefined ? "-" : `${environment.manifestName}@${environment.manifestVersion}`,
|
|
83
|
-
environment.state,
|
|
84
|
-
String(environment.sessions.length),
|
|
85
|
-
Object.entries(environment.labels)
|
|
86
|
-
.map(([key, value]) => `${key}=${value}`)
|
|
87
|
-
.join(",") || "-",
|
|
88
|
-
]),
|
|
89
|
-
]);
|
|
90
|
-
printCursor(deps, page.nextCursor);
|
|
91
|
-
return 0;
|
|
92
|
-
}
|
|
93
|
-
/** A command that takes one Environment id and prints the Runtime's answer. */
|
|
94
|
-
function byId(name, call) {
|
|
95
|
-
return async (deps, args) => {
|
|
96
|
-
const usage = `nylorun environments ${name} <id>`;
|
|
97
|
-
const flags = parseFlags(args, {}, usage);
|
|
98
|
-
const [id] = positional(flags, 1, usage);
|
|
99
|
-
const { client } = await runtimeClient(deps, flags);
|
|
100
|
-
printJson(deps, await runtimeCall(() => call(client, id)));
|
|
101
|
-
return 0;
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
async function put(deps, args) {
|
|
105
|
-
const usage = "nylorun environments put <id> [--manifest <name[@n]> | <inline.json|-> [--kind <virtual|pod|none>]] [--label <key=value>]...";
|
|
106
|
-
const flags = parseFlags(args, { values: ["--kind", "--manifest"], lists: ["--label"] }, usage);
|
|
107
|
-
if (flags.rest.length < 1 || flags.rest.length > 2)
|
|
108
|
-
throw usageError(`Usage: ${usage}`);
|
|
109
|
-
const [id, path] = flags.rest;
|
|
110
|
-
const manifest = flags.values.get("--manifest");
|
|
111
|
-
const kind = flags.values.get("--kind");
|
|
112
|
-
if (manifest !== undefined && (path !== undefined || kind !== undefined))
|
|
113
|
-
throw usageError("--manifest makes it from the manifest: give no inline fields or --kind with it.");
|
|
114
|
-
const recipe = path === undefined ? {} : await readJson(path, "The inline fields");
|
|
115
|
-
const labels = labelsOf(flags);
|
|
116
|
-
const body = {
|
|
117
|
-
...recipe,
|
|
118
|
-
...(manifest ? { manifest } : {}),
|
|
119
|
-
...(kind ? { kind } : {}),
|
|
120
|
-
...(labels ? { labels: { ...recipe.labels, ...labels } } : {}),
|
|
121
|
-
};
|
|
122
|
-
const { client } = await runtimeClient(deps, flags);
|
|
123
|
-
printJson(deps, await runtimeCall(() => client.environments.put(id, body)));
|
|
124
|
-
return 0;
|
|
125
|
-
}
|
|
126
|
-
async function fork(deps, args) {
|
|
127
|
-
const usage = "nylorun environments fork <id> <new-id> [--manifest <name[@n]>] [--disk <latest|n|empty>] [--secrets <copy|none>] [--label <key=value>]... [--dry-run]";
|
|
128
|
-
const flags = parseFlags(args, { booleans: ["--dry-run"], values: ["--manifest", "--disk", "--secrets"], lists: ["--label"] }, usage);
|
|
129
|
-
const [id, next] = positional(flags, 2, usage);
|
|
130
|
-
const disk = flags.values.get("--disk");
|
|
131
|
-
if (disk !== undefined && disk !== "latest" && disk !== "empty" && !/^[1-9]\d*$/.test(disk))
|
|
132
|
-
throw usageError("--disk is latest, empty or a version number.");
|
|
133
|
-
const secrets = flags.values.get("--secrets");
|
|
134
|
-
if (secrets !== undefined && secrets !== "copy" && secrets !== "none")
|
|
135
|
-
throw usageError("--secrets is copy or none.");
|
|
136
|
-
const manifest = flags.values.get("--manifest");
|
|
137
|
-
const labels = labelsOf(flags);
|
|
138
|
-
const options = {
|
|
139
|
-
id: next,
|
|
140
|
-
...(manifest ? { manifest } : {}),
|
|
141
|
-
...(disk === undefined ? {} : { disk: disk === "latest" || disk === "empty" ? disk : Number(disk) }),
|
|
142
|
-
...(secrets ? { secrets: secrets } : {}),
|
|
143
|
-
...(labels ? { labels } : {}),
|
|
144
|
-
};
|
|
145
|
-
const { client, connection } = await runtimeClient(deps, flags);
|
|
146
|
-
if (flags.booleans.has("--dry-run")) {
|
|
147
|
-
printJson(deps, await runtimeCall(() => client.environments.planFork(id, options)));
|
|
148
|
-
return 0;
|
|
149
|
-
}
|
|
150
|
-
const forked = await runtimeCall(() => client.environments.fork(id, options));
|
|
151
|
-
const { plan } = forked;
|
|
152
|
-
deps.err(`Forked Environment ${id} into ${next} on ${connection.label}: ${plan.manifest ? `${plan.manifest.name}@${plan.manifest.version}` : "its fields"}, ${plan.disk === null ? "an empty disk" : `disk version ${plan.disk}`}, ${plan.secrets.copied.length} secrets copied${plan.setup ? "; its setup runs before the first turn" : ""}.`);
|
|
153
|
-
if (plan.secrets.missing.length > 0)
|
|
154
|
-
deps.err(` set before use: ${plan.secrets.missing.join(", ")} (nylorun environments secrets put ${next} <name>)`);
|
|
155
|
-
printJson(deps, forked);
|
|
156
|
-
return 0;
|
|
157
|
-
}
|
|
158
|
-
async function deleteEnvironment(deps, args) {
|
|
159
|
-
const usage = "nylorun environments delete <id>";
|
|
160
|
-
const flags = parseFlags(args, {}, usage);
|
|
161
|
-
const [id] = positional(flags, 1, usage);
|
|
162
|
-
const { client, connection } = await runtimeClient(deps, flags);
|
|
163
|
-
const deleted = await runtimeCall(async () => {
|
|
164
|
-
try {
|
|
165
|
-
return await client.environments.delete(id);
|
|
166
|
-
}
|
|
167
|
-
catch (error) {
|
|
168
|
-
if (error.status === 404)
|
|
169
|
-
return undefined;
|
|
170
|
-
throw error;
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
if (!deleted || deleted.deleted === false) {
|
|
174
|
-
deps.err(`No Environment ${id} on ${connection.label}.`);
|
|
175
|
-
return 1;
|
|
176
|
-
}
|
|
177
|
-
deps.out(`Deleted Environment ${id}: its sandbox, files and vault.`);
|
|
178
|
-
return 0;
|
|
179
|
-
}
|
|
180
|
-
async function restore(deps, args) {
|
|
181
|
-
const usage = "nylorun environments restore <id> <version|latest>";
|
|
182
|
-
const flags = parseFlags(args, {}, usage);
|
|
183
|
-
const [id, version] = positional(flags, 2, usage);
|
|
184
|
-
if (version !== "latest" && !/^[1-9]\d*$/.test(version))
|
|
185
|
-
throw usageError("The version is a positive number or latest.");
|
|
186
|
-
const { client } = await runtimeClient(deps, flags);
|
|
187
|
-
printJson(deps, await runtimeCall(() => client.environments.restore(id, version === "latest" ? "latest" : Number(version))));
|
|
188
|
-
return 0;
|
|
189
|
-
}
|
|
190
|
-
async function deleteVersion(deps, args) {
|
|
191
|
-
const usage = "nylorun environments delete-version <id> <version>";
|
|
192
|
-
const flags = parseFlags(args, {}, usage);
|
|
193
|
-
const [id, version] = positional(flags, 2, usage);
|
|
194
|
-
if (!/^[1-9]\d*$/.test(version))
|
|
195
|
-
throw usageError("The version is a positive number.");
|
|
196
|
-
const { client } = await runtimeClient(deps, flags);
|
|
197
|
-
printJson(deps, await runtimeCall(() => client.environments.deleteVersion(id, Number(version))));
|
|
198
|
-
return 0;
|
|
199
|
-
}
|
|
200
|
-
async function events(deps, args) {
|
|
201
|
-
const usage = "nylorun environments events <id> [--from <n>] [--types <type,…>] [--since <time>] [--until <time>]";
|
|
202
|
-
const flags = parseFlags(args, { values: ["--from", "--types", "--since", "--until"] }, usage);
|
|
203
|
-
const [id] = positional(flags, 1, usage);
|
|
204
|
-
const from = integerFlag(flags, "--from");
|
|
205
|
-
const types = flags.values.get("--types")?.split(",").map((type) => type.trim()).filter(Boolean);
|
|
206
|
-
const since = flags.values.get("--since");
|
|
207
|
-
const until = flags.values.get("--until");
|
|
208
|
-
const { client } = await runtimeClient(deps, flags);
|
|
209
|
-
printJson(deps, await runtimeCall(() => client.environments.events(id, {
|
|
210
|
-
...(from === undefined ? {} : { from }),
|
|
211
|
-
...(types === undefined || types.length === 0 ? {} : { types }),
|
|
212
|
-
...(since === undefined ? {} : { since }),
|
|
213
|
-
...(until === undefined ? {} : { until }),
|
|
214
|
-
})));
|
|
215
|
-
return 0;
|
|
216
|
-
}
|
|
217
|
-
async function secrets(deps, args) {
|
|
218
|
-
const [verb, ...rest] = args;
|
|
219
|
-
if (verb === "list" || verb === "ls") {
|
|
220
|
-
const usage = "nylorun environments secrets list <id>";
|
|
221
|
-
const flags = parseFlags(rest, {}, usage);
|
|
222
|
-
const [id] = positional(flags, 1, usage);
|
|
223
|
-
const { client } = await runtimeClient(deps, flags);
|
|
224
|
-
printJson(deps, await runtimeCall(() => client.environments.secrets.list(id)));
|
|
225
|
-
return 0;
|
|
226
|
-
}
|
|
227
|
-
if (verb === "get") {
|
|
228
|
-
const usage = "nylorun environments secrets get <id> <name>";
|
|
229
|
-
const flags = parseFlags(rest, {}, usage);
|
|
230
|
-
const [id, name] = positional(flags, 2, usage);
|
|
231
|
-
const { client } = await runtimeClient(deps, flags);
|
|
232
|
-
printJson(deps, await runtimeCall(() => client.environments.secrets.get(id, name)));
|
|
233
|
-
return 0;
|
|
234
|
-
}
|
|
235
|
-
if (verb === "put") {
|
|
236
|
-
const usage = "nylorun environments secrets put <id> <name> [<secret.json|->]";
|
|
237
|
-
const flags = parseFlags(rest, {}, usage);
|
|
238
|
-
if (flags.rest.length < 2 || flags.rest.length > 3)
|
|
239
|
-
throw usageError(`Usage: ${usage}`);
|
|
240
|
-
const [id, name, path] = flags.rest;
|
|
241
|
-
if (path === undefined) {
|
|
242
|
-
// A slot its manifest declares (D64): the value only, piped in; the binding is the slot's.
|
|
243
|
-
const value = await readSecret(deps, `value of ${name}`, `printf %s "$TOKEN" | nylorun environments secrets put ${id} ${name}`);
|
|
244
|
-
const { client } = await runtimeClient(deps, flags);
|
|
245
|
-
printJson(deps, await runtimeCall(() => client.environments.secrets.put(id, name, { value })));
|
|
246
|
-
return 0;
|
|
247
|
-
}
|
|
248
|
-
const secret = await readJson(path, "The secret");
|
|
249
|
-
if (typeof secret.type !== "string")
|
|
250
|
-
throw usageError('The secret needs a "type".');
|
|
251
|
-
const { client } = await runtimeClient(deps, flags);
|
|
252
|
-
printJson(deps, await runtimeCall(() => client.environments.secrets.put(id, name, secret)));
|
|
253
|
-
return 0;
|
|
254
|
-
}
|
|
255
|
-
if (verb === "rm" || verb === "delete") {
|
|
256
|
-
const usage = "nylorun environments secrets rm <id> <name>";
|
|
257
|
-
const flags = parseFlags(rest, {}, usage);
|
|
258
|
-
const [id, name] = positional(flags, 2, usage);
|
|
259
|
-
const { client } = await runtimeClient(deps, flags);
|
|
260
|
-
await runtimeCall(() => client.environments.secrets.delete(id, name));
|
|
261
|
-
deps.out(`Deleted secret ${name} of Environment ${id}.`);
|
|
262
|
-
return 0;
|
|
263
|
-
}
|
|
264
|
-
throw usageError(`Usage: nylorun environments secrets <list|get|put|rm> …\n\n${environmentsUsage}`);
|
|
265
|
-
}
|
|
266
|
-
const COMMANDS = {
|
|
267
|
-
list,
|
|
268
|
-
ls: list,
|
|
269
|
-
get: byId("get", (client, id) => client.environments.get(id)),
|
|
270
|
-
put,
|
|
271
|
-
stop: byId("stop", (client, id) => client.environments.stop(id)),
|
|
272
|
-
reset: byId("reset", (client, id) => client.environments.reset(id)),
|
|
273
|
-
delete: deleteEnvironment,
|
|
274
|
-
rm: deleteEnvironment,
|
|
275
|
-
snapshot: byId("snapshot", (client, id) => client.environments.snapshot(id)),
|
|
276
|
-
versions: byId("versions", (client, id) => client.environments.versions(id)),
|
|
277
|
-
restore,
|
|
278
|
-
"delete-version": deleteVersion,
|
|
279
|
-
events,
|
|
280
|
-
secrets,
|
|
281
|
-
fork,
|
|
282
|
-
manifests: (deps, args) => manifestsCommand(deps, args, manifestsUsage),
|
|
283
|
-
};
|
|
284
|
-
/** `nylorun environments <command> ...` */
|
|
285
|
-
export async function environmentsCommand(deps, args) {
|
|
286
|
-
const [sub, ...rest] = args;
|
|
287
|
-
if (sub === "--help" || sub === "-h") {
|
|
288
|
-
deps.out(environmentsUsage);
|
|
289
|
-
return 0;
|
|
290
|
-
}
|
|
291
|
-
const command = sub !== undefined && Object.hasOwn(COMMANDS, sub) ? COMMANDS[sub] : undefined;
|
|
292
|
-
if (!command)
|
|
293
|
-
throw usageError(sub ? `Unknown environments command ${sub}.\n${environmentsUsage}` : environmentsUsage);
|
|
294
|
-
return command(deps, rest);
|
|
295
|
-
}
|