nylorun 0.16.0-beta → 0.18.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 +70 -0
- package/README.md +118 -70
- package/dist/cli.js +39 -14
- package/dist/client/agent-manifests.d.ts +4 -0
- package/dist/client/agent-manifests.js +100 -0
- package/dist/client/agents.d.ts +2 -4
- package/dist/client/agents.js +467 -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 +30 -23
- 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 +17 -7
- package/dist/client/runtime.d.ts +1 -1
- package/dist/client/runtime.js +8 -6
- package/dist/client/sessions.js +30 -19
- package/dist/client/settings.d.ts +4 -4
- package/dist/client/settings.js +21 -20
- package/dist/client/signing-keys.js +3 -1
- package/dist/client/tenant.d.ts +1 -1
- package/dist/client/tenant.js +12 -7
- package/dist/command.d.ts +1 -1
- package/dist/command.js +6 -2
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +9 -0
- package/dist/nylo.js +4 -4
- package/dist/stack/commands.d.ts +11 -0
- package/dist/stack/commands.js +24 -1
- package/dist/stack/compose-file.js +5 -3
- package/dist/telemetry.js +3 -1
- 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
package/dist/client/sessions.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `nylorun sessions`: the Tenant's sessions (`/v1/sessions`, Runtime API): open one
|
|
2
|
+
* `nylorun sessions`: the Tenant's sessions (`/v1/sessions`, Runtime API): open one on an Agent
|
|
3
|
+
* (protocol 16: every session runs on one, and its id is the caller's to choose), send it a
|
|
3
4
|
* message, answer what it waits for, watch its events, and read its history, usage, calls and
|
|
4
5
|
* traces. `exec` runs a command in the session's sandbox, as an app's own tool would.
|
|
5
6
|
*/
|
|
@@ -10,13 +11,17 @@ export const sessionsUsage = `nylorun sessions <command>
|
|
|
10
11
|
|
|
11
12
|
The Tenant's sessions, through the Runtime API with an application key (or NYLORUN_TOKEN).
|
|
12
13
|
|
|
13
|
-
list [--agent <id>] [--
|
|
14
|
+
list [--agent <id>] [--manifest <name>] [--status <status>] [--owner <user>]
|
|
14
15
|
[--limit <n>] [--cursor <c>] [--json]
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
--agent: on that Agent; --manifest: on the Agents made
|
|
17
|
+
from that agent manifest
|
|
18
|
+
create --agent <id> --owner <user> [--id <id>] [--info <json>]
|
|
19
|
+
open a session on Agent <id>; prints its id
|
|
17
20
|
get <id> the session: status, active turn, what it waits for
|
|
18
21
|
send <id> [<text>] [--data <json>] [--file <artifact>[@<version>]]... [--idempotency-key <k>]
|
|
19
|
-
|
|
22
|
+
[--reject-if-busy] start a turn with text, JSON data or files (artifacts); while
|
|
23
|
+
a turn runs the message waits in the session's queue, or is
|
|
24
|
+
refused with --reject-if-busy
|
|
20
25
|
approve <id> <interaction> [--deny] approve (or deny) a held tool call
|
|
21
26
|
respond <id> <interaction> <json> answer a question the agent asked
|
|
22
27
|
cancel <id> [--reason <text>] cancel the running turn
|
|
@@ -33,9 +38,13 @@ The Tenant's sessions, through the Runtime API with an application key (or NYLOR
|
|
|
33
38
|
its exit code
|
|
34
39
|
|
|
35
40
|
${runtimeFlagsUsage}`;
|
|
41
|
+
/** Protocol 16: a session runs on the Agent `--agent` names, which holds what an Environment did. */
|
|
42
|
+
const ENVIRONMENT_REMOVED = "--environment was removed in protocol 16: a session runs on an Agent, its sandbox and vault included. Pass --agent <id> (nylorun agents list).";
|
|
36
43
|
async function list(deps, args) {
|
|
37
|
-
const usage = "nylorun sessions list [--agent <id>] [--
|
|
38
|
-
|
|
44
|
+
const usage = "nylorun sessions list [--agent <id>] [--manifest <name>] [--status <s>] [--owner <user>] [--limit <n>] [--cursor <c>] [--json]";
|
|
45
|
+
if (args.includes("--environment"))
|
|
46
|
+
throw usageError(ENVIRONMENT_REMOVED);
|
|
47
|
+
const flags = parseFlags(args, { booleans: ["--json"], values: ["--agent", "--manifest", "--status", "--owner", "--limit", "--cursor"] }, usage);
|
|
39
48
|
positional(flags, 0, usage);
|
|
40
49
|
const { client } = await runtimeClient(deps, flags);
|
|
41
50
|
const value = (name) => flags.values.get(name);
|
|
@@ -43,7 +52,7 @@ async function list(deps, args) {
|
|
|
43
52
|
const page = await runtimeCall(() => client.sessions.page({
|
|
44
53
|
...(value("--agent") ? { agentId: value("--agent") } : {}),
|
|
45
54
|
...(value("--status") ? { status: value("--status") } : {}),
|
|
46
|
-
...(value("--
|
|
55
|
+
...(value("--manifest") ? { manifest: value("--manifest") } : {}),
|
|
47
56
|
...(value("--owner") ? { ownerUserId: value("--owner") } : {}),
|
|
48
57
|
...(limit === undefined ? {} : { limit }),
|
|
49
58
|
...(value("--cursor") ? { cursor: value("--cursor") } : {}),
|
|
@@ -56,13 +65,12 @@ async function list(deps, args) {
|
|
|
56
65
|
deps.out("No sessions.");
|
|
57
66
|
else
|
|
58
67
|
printTable(deps, [
|
|
59
|
-
["ID", "AGENT", "OWNER", "STATUS", "
|
|
68
|
+
["ID", "AGENT", "OWNER", "STATUS", "LAST EVENT"],
|
|
60
69
|
...page.sessions.map((session) => [
|
|
61
70
|
session.id,
|
|
62
71
|
session.agentId,
|
|
63
72
|
session.ownerUserId,
|
|
64
73
|
session.status,
|
|
65
|
-
session.environmentId ?? "-",
|
|
66
74
|
session.lastEventAt ?? "-",
|
|
67
75
|
]),
|
|
68
76
|
]);
|
|
@@ -70,8 +78,10 @@ async function list(deps, args) {
|
|
|
70
78
|
return 0;
|
|
71
79
|
}
|
|
72
80
|
async function create(deps, args) {
|
|
73
|
-
const usage = "nylorun sessions create --agent <id> --owner <user> [--
|
|
74
|
-
|
|
81
|
+
const usage = "nylorun sessions create --agent <id> --owner <user> [--id <id>] [--info <json>]";
|
|
82
|
+
if (args.includes("--environment"))
|
|
83
|
+
throw usageError(ENVIRONMENT_REMOVED);
|
|
84
|
+
const flags = parseFlags(args, { values: ["--agent", "--owner", "--id", "--info"] }, usage);
|
|
75
85
|
positional(flags, 0, usage);
|
|
76
86
|
const agentId = flags.values.get("--agent");
|
|
77
87
|
const ownerUserId = flags.values.get("--owner");
|
|
@@ -81,14 +91,12 @@ async function create(deps, args) {
|
|
|
81
91
|
const parsedInfo = info === undefined ? undefined : parseJsonArgument(info, "--info");
|
|
82
92
|
if (parsedInfo !== undefined && (!parsedInfo || typeof parsedInfo !== "object" || Array.isArray(parsedInfo)))
|
|
83
93
|
throw usageError("--info must be a JSON object.");
|
|
84
|
-
const environment = flags.values.get("--environment");
|
|
85
94
|
const id = flags.values.get("--id");
|
|
86
95
|
const { client } = await runtimeClient(deps, flags);
|
|
87
96
|
const session = await runtimeCall(() => client.createSession({
|
|
88
|
-
agentId,
|
|
97
|
+
agent: agentId,
|
|
89
98
|
ownerUserId,
|
|
90
99
|
...(id ? { id } : {}),
|
|
91
|
-
...(environment ? { environment } : {}),
|
|
92
100
|
...(parsedInfo ? { info: parsedInfo } : {}),
|
|
93
101
|
}));
|
|
94
102
|
deps.out(session.id);
|
|
@@ -113,8 +121,8 @@ function filePart(value) {
|
|
|
113
121
|
return { type: "file", artifactId: value.slice(0, at), version: Number(version) };
|
|
114
122
|
}
|
|
115
123
|
async function send(deps, args) {
|
|
116
|
-
const usage = "nylorun sessions send <id> [<text>] [--data <json>] [--file <artifact>[@<version>]]... [--idempotency-key <k>]";
|
|
117
|
-
const flags = parseFlags(args, { values: ["--data", "--idempotency-key"], lists: ["--file"] }, usage);
|
|
124
|
+
const usage = "nylorun sessions send <id> [<text>] [--data <json>] [--file <artifact>[@<version>]]... [--idempotency-key <k>] [--reject-if-busy]";
|
|
125
|
+
const flags = parseFlags(args, { values: ["--data", "--idempotency-key"], lists: ["--file"], booleans: ["--reject-if-busy"] }, usage);
|
|
118
126
|
if (flags.rest.length < 1 || flags.rest.length > 2)
|
|
119
127
|
throw usageError(`Usage: ${usage}`);
|
|
120
128
|
const [id, text] = flags.rest;
|
|
@@ -125,7 +133,10 @@ async function send(deps, args) {
|
|
|
125
133
|
if (data === undefined && text === undefined && files.length === 0)
|
|
126
134
|
throw usageError(`Nothing to send. Usage: ${usage}`);
|
|
127
135
|
const parts = files.map(filePart);
|
|
128
|
-
const options = {
|
|
136
|
+
const options = {
|
|
137
|
+
idempotencyKey: flags.values.get("--idempotency-key") ?? randomUUID(),
|
|
138
|
+
...(flags.booleans.has("--reject-if-busy") ? { delivery: "reject" } : {}),
|
|
139
|
+
};
|
|
129
140
|
const { client } = await runtimeClient(deps, flags);
|
|
130
141
|
const session = client.session(id);
|
|
131
142
|
const accepted = await runtimeCall(() => data !== undefined
|
|
@@ -247,9 +258,9 @@ async function trace(deps, args) {
|
|
|
247
258
|
async function exec(deps, args) {
|
|
248
259
|
const usage = "nylorun sessions exec <id> [--timeout <s>] -- <command>...";
|
|
249
260
|
const split = args.indexOf("--");
|
|
261
|
+
const flags = parseFlags(split < 0 ? args : args.slice(0, split), { values: ["--timeout"] }, usage);
|
|
250
262
|
if (split < 0 || split === args.length - 1)
|
|
251
263
|
throw usageError(`Usage: ${usage}`);
|
|
252
|
-
const flags = parseFlags(args.slice(0, split), { values: ["--timeout"] }, usage);
|
|
253
264
|
const [id] = positional(flags, 1, usage);
|
|
254
265
|
const timeout = integerFlag(flags, "--timeout");
|
|
255
266
|
const command = args.slice(split + 1).join(" ");
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type StackDeps } from "../stack/commands.js";
|
|
2
|
-
export declare const settingsUsage = " budgets [get | put <file|->] [--tenant <name>]\n the model spend caps; put replaces them all\n tool-policy [get | put <file|->] [--tenant <name>]\n the Tool Gate's rules; put replaces them all\n settings sandbox [get | put <file|->] [--tenant <name>]\n the
|
|
2
|
+
export declare const settingsUsage = " budgets [get | put <file|->] [--tenant <name>]\n the model spend caps (scope tenant, manifest with id an\n agent manifest's name, or turn); put replaces them all\n tool-policy [get | put <file|->] [--tenant <name>]\n the Tool Gate's rules; put replaces them all\n settings sandbox [get | put <file|->] [--tenant <name>]\n the Agents' environments: limits, stop grace, placement\n settings artifacts [get | put <file|->] [--tenant <name>]\n the artifact store's limits\n settings skills [get | put <file|->] [--tenant <name>]\n the most bytes one skill may hold\n settings limits [get | put <file|->] [--tenant <name>]\n the Runtime limits: sizes, counts and deadlines (record\n entries, request bodies, Agents, model calls, tools)\n coverage --agent <id> [--tenant <name>] [--json]\n which secret of Agent <id>'s vault each MCP server and\n HTTP tool of its manifest would get";
|
|
3
3
|
export declare const budgetsCommand: (deps: StackDeps, args: readonly string[]) => Promise<number>;
|
|
4
4
|
export declare const toolPolicyCommand: (deps: StackDeps, args: readonly string[]) => Promise<number>;
|
|
5
5
|
/** `nylorun tenant settings sandbox | artifacts | skills | limits ...` */
|
|
6
6
|
export declare function settingsCommand(deps: StackDeps, args: readonly string[]): Promise<number>;
|
|
7
7
|
/**
|
|
8
|
-
* `nylorun tenant coverage`: which secret of `--
|
|
9
|
-
* of
|
|
10
|
-
*
|
|
8
|
+
* `nylorun tenant coverage`: which secret of Agent `--agent`'s vault each remote MCP server and
|
|
9
|
+
* HTTP tool of the manifest version it runs would get in its sessions. It reads no secret and
|
|
10
|
+
* calls no server.
|
|
11
11
|
*/
|
|
12
12
|
export declare function coverageCommand(deps: StackDeps, args: readonly string[]): Promise<number>;
|
package/dist/client/settings.js
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { PutModelBudgetsRequestSchema, PutTenantArtifactsRequestSchema, PutTenantEnvironmentsRequestSchema, PutTenantLimitsRequestSchema, PutTenantSkillsRequestSchema, PutToolPolicyRequestSchema, } from "@nylorun/core/contracts";
|
|
2
|
-
import { CliError } from "../errors.js";
|
|
3
|
-
import { parseStackFlags } from "../stack/commands.js";
|
|
2
|
+
import { CliError, HelpRequest, isHelp } from "../errors.js";
|
|
3
|
+
import { parseStackFlags, usageLinesOf } from "../stack/commands.js";
|
|
4
4
|
import { printJson, printTable, readBody } from "./io.js";
|
|
5
5
|
import { connect, managementClient } from "./target.js";
|
|
6
6
|
export const settingsUsage = ` budgets [get | put <file|->] [--tenant <name>]
|
|
7
|
-
the model spend caps
|
|
7
|
+
the model spend caps (scope tenant, manifest with id an
|
|
8
|
+
agent manifest's name, or turn); put replaces them all
|
|
8
9
|
tool-policy [get | put <file|->] [--tenant <name>]
|
|
9
10
|
the Tool Gate's rules; put replaces them all
|
|
10
11
|
settings sandbox [get | put <file|->] [--tenant <name>]
|
|
11
|
-
the
|
|
12
|
+
the Agents' environments: limits, stop grace, placement
|
|
12
13
|
settings artifacts [get | put <file|->] [--tenant <name>]
|
|
13
14
|
the artifact store's limits
|
|
14
15
|
settings skills [get | put <file|->] [--tenant <name>]
|
|
15
16
|
the most bytes one skill may hold
|
|
16
17
|
settings limits [get | put <file|->] [--tenant <name>]
|
|
17
18
|
the Runtime limits: sizes, counts and deadlines (record
|
|
18
|
-
entries, request bodies,
|
|
19
|
-
coverage --agent <id> [--
|
|
20
|
-
which secret of
|
|
21
|
-
|
|
19
|
+
entries, request bodies, Agents, model calls, tools)
|
|
20
|
+
coverage --agent <id> [--tenant <name>] [--json]
|
|
21
|
+
which secret of Agent <id>'s vault each MCP server and
|
|
22
|
+
HTTP tool of its manifest would get`;
|
|
22
23
|
const usageError = (message = `Usage:\n${settingsUsage}`) => new CliError(message, 2);
|
|
23
24
|
/* The bodies' `requestId` is optional in the contracts; the client adds one when it is absent. */
|
|
24
25
|
const budgets = {
|
|
@@ -76,6 +77,8 @@ export const toolPolicyCommand = (deps, args) => documentCommand(deps, toolPolic
|
|
|
76
77
|
/** `nylorun tenant settings sandbox | artifacts | skills | limits ...` */
|
|
77
78
|
export async function settingsCommand(deps, args) {
|
|
78
79
|
const [which, ...rest] = args;
|
|
80
|
+
if (isHelp(which))
|
|
81
|
+
throw new HelpRequest(usageLinesOf(settingsUsage, "settings"));
|
|
79
82
|
if (which === "sandbox")
|
|
80
83
|
return documentCommand(deps, sandbox, rest);
|
|
81
84
|
if (which === "artifacts")
|
|
@@ -84,31 +87,29 @@ export async function settingsCommand(deps, args) {
|
|
|
84
87
|
return documentCommand(deps, skillSettings, rest);
|
|
85
88
|
if (which === "limits")
|
|
86
89
|
return documentCommand(deps, limitSettings, rest);
|
|
87
|
-
throw usageError();
|
|
90
|
+
throw usageError(usageLinesOf(settingsUsage, "settings"));
|
|
88
91
|
}
|
|
89
|
-
const COVERAGE_USAGE = "nylorun tenant coverage --agent <id> [--
|
|
92
|
+
const COVERAGE_USAGE = "nylorun tenant coverage --agent <id> [--tenant <name>] [--json]";
|
|
90
93
|
/**
|
|
91
|
-
* `nylorun tenant coverage`: which secret of `--
|
|
92
|
-
* of
|
|
93
|
-
*
|
|
94
|
+
* `nylorun tenant coverage`: which secret of Agent `--agent`'s vault each remote MCP server and
|
|
95
|
+
* HTTP tool of the manifest version it runs would get in its sessions. It reads no secret and
|
|
96
|
+
* calls no server.
|
|
94
97
|
*/
|
|
95
98
|
export async function coverageCommand(deps, args) {
|
|
96
|
-
|
|
99
|
+
if (args.includes("--environment"))
|
|
100
|
+
throw usageError("--environment was removed in protocol 16: pass the Agent, --agent <id>, whose vault its sessions use.");
|
|
101
|
+
const flags = parseStackFlags(args, { booleans: ["--json"], values: ["--tenant", "--agent"] }, COVERAGE_USAGE);
|
|
97
102
|
const agentId = flags.values.get("--agent");
|
|
98
|
-
const environmentId = flags.values.get("--environment");
|
|
99
103
|
if (flags.rest.length || agentId === undefined)
|
|
100
104
|
throw usageError(`Usage: ${COVERAGE_USAGE}`);
|
|
101
105
|
const admin = managementClient(deps, await connect(deps, "management", flags.values.get("--tenant")));
|
|
102
|
-
const coverage = await admin.coverage({
|
|
103
|
-
agentId,
|
|
104
|
-
...(environmentId === undefined ? {} : { environmentId }),
|
|
105
|
-
});
|
|
106
|
+
const coverage = await admin.coverage({ agentId });
|
|
106
107
|
if (flags.booleans.has("--json")) {
|
|
107
108
|
printJson(deps, coverage);
|
|
108
109
|
return 0;
|
|
109
110
|
}
|
|
110
111
|
const missing = coverage.entries.filter((entry) => entry.status === "missing").length;
|
|
111
|
-
deps.out(
|
|
112
|
+
deps.out(`Agent ${coverage.agentId}: ${coverage.complete ? "every credential is covered" : `${missing} of ${coverage.entries.length} missing`}`);
|
|
112
113
|
if (coverage.entries.length)
|
|
113
114
|
printTable(deps, [
|
|
114
115
|
["STATUS", "KIND", "NAME", "URL", "SECRET"],
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* tokens, through the Management API. (Subject tokens, the access policy, browser keys and
|
|
4
4
|
* revocations left the Runtime in protocol 7.)
|
|
5
5
|
*/
|
|
6
|
-
import { CliError } from "../errors.js";
|
|
6
|
+
import { CliError, HelpRequest, isHelp } from "../errors.js";
|
|
7
7
|
import { parseStackFlags } from "../stack/commands.js";
|
|
8
8
|
import { connect, managementClient } from "./target.js";
|
|
9
9
|
export const signingKeysUsage = ` signing-keys list [--tenant <name>]
|
|
@@ -15,6 +15,8 @@ export const signingKeysUsage = ` signing-keys list [--tenant <name>]
|
|
|
15
15
|
const usageError = (message = `Usage:\n${signingKeysUsage}`) => new CliError(message, 2);
|
|
16
16
|
export async function signingKeysCommand(deps, input) {
|
|
17
17
|
const [action, ...args] = input;
|
|
18
|
+
if (isHelp(action))
|
|
19
|
+
throw new HelpRequest(`Usage:\n${signingKeysUsage}`);
|
|
18
20
|
const flags = parseStackFlags(args, { booleans: action === "rotate" ? ["--force"] : [], values: ["--tenant"] }, signingKeysUsage);
|
|
19
21
|
const arity = action === "revoke" ? 1 : 0;
|
|
20
22
|
if (!["list", "rotate", "revoke"].includes(action ?? "") || flags.rest.length !== arity)
|
package/dist/client/tenant.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { ManagementClient } from "@nylorun/admin";
|
|
7
7
|
import { type StackDeps } from "../stack/commands.js";
|
|
8
8
|
import { type Connection } from "./target.js";
|
|
9
|
-
export declare const tenantUsage = "nylorun tenant <command>\n\nThe Management API of the installation's one Tenant, with a management key: the local Tenant\n--tenant names (else the linked project's, else the default one), or the installation that\nNYLORUN_RUNTIME_URL and NYLORUN_MANAGEMENT_KEY name.\n\n reset [--sessions|--
|
|
9
|
+
export declare const tenantUsage = "nylorun tenant <command>\n\nThe Management API of the installation's one Tenant, with a management key: the local Tenant\n--tenant names (else the linked project's, else the default one), or the installation that\nNYLORUN_RUNTIME_URL and NYLORUN_MANAGEMENT_KEY name.\n\n reset [--sessions|--agents|--all] [--yes] [--tenant <name>]\n clear the Tenant's sessions, its Agents (their vaults,\n disks and sessions) or all its data (the Project link and\n keys stay)\n keys put <id> [--management] [--tenant <name>]\n create the Tenant's application key <id> (--management: a\n management key, on the Runtime's machine only), or rotate it\n (the old key stops working); prints the key once\n keys list [--tenant <name>] [--json]\n the Tenant's keys: id, role, when issued (never the keys)\n keys rm <id> [--tenant <name>] delete key <id>: it stops working at once\n signing-keys list [--tenant <name>]\n the Tenant's token signing keys\n signing-keys rotate [--force] [--tenant <name>]\n rotate; --force ends outstanding links and run tokens\n signing-keys revoke <kid> [--tenant <name>]\n revoke a previous or standby key\n models catalog [--tenant <name>] [--json]\n every provider and model the Runtime knows\n models providers [--tenant <name>] [--json]\n the providers with a credential, and the one in use\n models get [--tenant <name>] [--json]\n the Tenant's model\n models set [--tenant <name>] sign in to a model provider and set the Tenant's model\n models set --provider <id> --model <id> [--base-url <url>] [--tenant <name>]\n the same with an API key piped in on stdin (CI)\n models select <provider> [--model <id>] [--tenant <name>]\n use a provider that has a credential (default: its model)\n usage [--scope tenant|manifest|turn] [--id <id>] [--period day|month|total] [--tenant <name>]\n what the model calls used and cost (JSON); --scope\n manifest: the Agents made from agent manifest <id>\n calls [--after <cursor>] [--limit <n>] [--tenant <name>]\n every recorded model call, one JSON line each, until\n caught up; prints the cursor to resume from on stderr\n budgets [get | put <file|->] [--tenant <name>]\n the model spend caps (scope tenant, manifest with id an\n agent manifest's name, or turn); put replaces them all\n tool-policy [get | put <file|->] [--tenant <name>]\n the Tool Gate's rules; put replaces them all\n settings sandbox [get | put <file|->] [--tenant <name>]\n the Agents' environments: limits, stop grace, placement\n settings artifacts [get | put <file|->] [--tenant <name>]\n the artifact store's limits\n settings skills [get | put <file|->] [--tenant <name>]\n the most bytes one skill may hold\n settings limits [get | put <file|->] [--tenant <name>]\n the Runtime limits: sizes, counts and deadlines (record\n entries, request bodies, Agents, model calls, tools)\n coverage --agent <id> [--tenant <name>] [--json]\n which secret of Agent <id>'s vault each MCP server and\n HTTP tool of its manifest would get\n mcp inspect <url> [--server <name>] [--agent <id>] [--sse] [--tenant <name>] [--json]\n list a remote MCP server's tools, with Agent <id>'s\n credential for <url> (none without it): model names, schema\n sizes, renames, or that it needs a person's sign-in (the\n Runtime calls no tool)\n\nA put reads a JSON body from a file, or from stdin for -, and replaces the whole document; what\nbudgets, tool-policy, settings artifacts, settings skills and settings limits get print, put takes back. An API key is read from\nstdin, never from the arguments.";
|
|
10
10
|
/** The Management API client of the installation `--tenant` (or the environment) names. */
|
|
11
11
|
export declare function tenantClient(deps: StackDeps, tenant: string | undefined): Promise<{
|
|
12
12
|
connection: Connection;
|
package/dist/client/tenant.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CliError } from "../errors.js";
|
|
1
|
+
import { CliError, HelpRequest, isHelp } from "../errors.js";
|
|
2
2
|
import { parseStackFlags } from "../stack/commands.js";
|
|
3
3
|
import { keyCommand, keyUsage } from "../stack/keys.js";
|
|
4
4
|
import { printJson, printTable } from "./io.js";
|
|
@@ -13,9 +13,10 @@ The Management API of the installation's one Tenant, with a management key: the
|
|
|
13
13
|
--tenant names (else the linked project's, else the default one), or the installation that
|
|
14
14
|
NYLORUN_RUNTIME_URL and NYLORUN_MANAGEMENT_KEY name.
|
|
15
15
|
|
|
16
|
-
reset [--sessions|--
|
|
17
|
-
clear the Tenant's sessions,
|
|
18
|
-
(the Project link and
|
|
16
|
+
reset [--sessions|--agents|--all] [--yes] [--tenant <name>]
|
|
17
|
+
clear the Tenant's sessions, its Agents (their vaults,
|
|
18
|
+
disks and sessions) or all its data (the Project link and
|
|
19
|
+
keys stay)
|
|
19
20
|
${keyUsage}
|
|
20
21
|
${signingKeysUsage}
|
|
21
22
|
${modelsUsage}
|
|
@@ -64,16 +65,18 @@ export async function remoteStatus(deps, args) {
|
|
|
64
65
|
deps.out(`sandbox ${body.sandbox.backend ?? "none"}`);
|
|
65
66
|
return 0;
|
|
66
67
|
}
|
|
67
|
-
const RESET_USAGE = "nylorun tenant reset [--sessions|--
|
|
68
|
-
const SCOPES = { "--sessions": "sessions", "--
|
|
68
|
+
const RESET_USAGE = "nylorun tenant reset [--sessions|--agents|--all] [--yes] [--tenant <name>]";
|
|
69
|
+
const SCOPES = { "--sessions": "sessions", "--agents": "agents", "--all": "all" };
|
|
69
70
|
/** `nylorun tenant reset`; `--all` asks first. */
|
|
70
71
|
async function reset(deps, args) {
|
|
72
|
+
if (args.includes("--environments"))
|
|
73
|
+
throw usageError("--environments is --agents in protocol 16: Environments are Agents. Pass --agents.");
|
|
71
74
|
const flags = parseStackFlags(args, { booleans: ["--yes", ...Object.keys(SCOPES)], values: ["--tenant"], aliases: { "-y": "--yes" } }, RESET_USAGE);
|
|
72
75
|
if (flags.rest.length)
|
|
73
76
|
throw usageError(`Usage: ${RESET_USAGE}`);
|
|
74
77
|
const chosen = Object.keys(SCOPES).filter((flag) => flags.booleans.has(flag));
|
|
75
78
|
if (chosen.length > 1)
|
|
76
|
-
throw usageError("Pass only one of --sessions, --
|
|
79
|
+
throw usageError("Pass only one of --sessions, --agents, --all.");
|
|
77
80
|
const scope = chosen.length ? SCOPES[chosen[0]] : "sessions";
|
|
78
81
|
const { connection, admin } = await tenantClient(deps, flags.values.get("--tenant"));
|
|
79
82
|
if (scope === "all" && !flags.booleans.has("--yes")) {
|
|
@@ -98,6 +101,8 @@ async function reset(deps, args) {
|
|
|
98
101
|
* (application keys only), else on the local Tenant through `nylorun-operate`.
|
|
99
102
|
*/
|
|
100
103
|
async function keys(deps, args) {
|
|
104
|
+
if (isHelp(args[0]))
|
|
105
|
+
throw new HelpRequest(`Usage:\n${keyUsage}`);
|
|
101
106
|
if (args.includes("--tenant") || !remoteConnection(deps.env, "management"))
|
|
102
107
|
return keyCommand(deps, args);
|
|
103
108
|
const [verb, ...rest] = args;
|
package/dist/command.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export declare function refuseNativeWindows(): void;
|
|
|
3
3
|
/**
|
|
4
4
|
* Run a command (`nylorun` or `nylo`) and exit once stdout and stderr are flushed: with
|
|
5
5
|
* `process.exitCode` (0 when unset), or after printing a failure's message with its
|
|
6
|
-
* `CliError` exit code (else 1).
|
|
6
|
+
* `CliError` exit code (else 1); a `HelpRequest`'s usage on stdout, exiting 0.
|
|
7
7
|
*/
|
|
8
8
|
export declare function runCommand(main: () => Promise<void>): void;
|
package/dist/command.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CliError } from "./errors.js";
|
|
1
|
+
import { CliError, HelpRequest } from "./errors.js";
|
|
2
2
|
/** Both commands refuse native Windows before acting; WSL2 runs them. */
|
|
3
3
|
export function refuseNativeWindows() {
|
|
4
4
|
if (process.platform === "win32")
|
|
@@ -7,10 +7,14 @@ export function refuseNativeWindows() {
|
|
|
7
7
|
/**
|
|
8
8
|
* Run a command (`nylorun` or `nylo`) and exit once stdout and stderr are flushed: with
|
|
9
9
|
* `process.exitCode` (0 when unset), or after printing a failure's message with its
|
|
10
|
-
* `CliError` exit code (else 1).
|
|
10
|
+
* `CliError` exit code (else 1); a `HelpRequest`'s usage on stdout, exiting 0.
|
|
11
11
|
*/
|
|
12
12
|
export function runCommand(main) {
|
|
13
13
|
void main().then(() => finish(process.exitCode === undefined ? 0 : Number(process.exitCode)), (error) => {
|
|
14
|
+
if (error instanceof HelpRequest) {
|
|
15
|
+
console.log(error.message);
|
|
16
|
+
return finish(0);
|
|
17
|
+
}
|
|
14
18
|
console.error(error instanceof Error ? error.message : String(error));
|
|
15
19
|
return finish(error instanceof CliError ? error.exitCode : 1);
|
|
16
20
|
});
|
package/dist/errors.d.ts
CHANGED
|
@@ -3,3 +3,9 @@ export declare class CliError extends Error {
|
|
|
3
3
|
readonly exitCode: number;
|
|
4
4
|
constructor(message: string, exitCode?: number);
|
|
5
5
|
}
|
|
6
|
+
/** `--help` or `-h`, which every command and group takes. */
|
|
7
|
+
export declare const isHelp: (arg: string | undefined) => boolean;
|
|
8
|
+
/** A command's usage, asked for with `--help`: printed on stdout, exit 0. */
|
|
9
|
+
export declare class HelpRequest extends CliError {
|
|
10
|
+
constructor(usage: string);
|
|
11
|
+
}
|
package/dist/errors.js
CHANGED
|
@@ -7,3 +7,12 @@ export class CliError extends Error {
|
|
|
7
7
|
this.name = "CliError";
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
+
/** `--help` or `-h`, which every command and group takes. */
|
|
11
|
+
export const isHelp = (arg) => arg === "--help" || arg === "-h";
|
|
12
|
+
/** A command's usage, asked for with `--help`: printed on stdout, exit 0. */
|
|
13
|
+
export class HelpRequest extends CliError {
|
|
14
|
+
constructor(usage) {
|
|
15
|
+
super(usage, 0);
|
|
16
|
+
this.name = "HelpRequest";
|
|
17
|
+
}
|
|
18
|
+
}
|
package/dist/nylo.js
CHANGED
|
@@ -3,8 +3,8 @@ import "./baseline.js";
|
|
|
3
3
|
import { runCommand } from "./command.js";
|
|
4
4
|
import { CliError } from "./errors.js";
|
|
5
5
|
/**
|
|
6
|
-
* `nylo` became part of `nylorun`.
|
|
7
|
-
* replaces each of its own and exits 2
|
|
6
|
+
* `nylo` became part of `nylorun`. Until nylorun 0.19, which removes it, this command names the
|
|
7
|
+
* `nylorun` command that replaces each of its own and exits 2.
|
|
8
8
|
*/
|
|
9
9
|
const REPLACEMENTS = {
|
|
10
10
|
status: "nylorun status",
|
|
@@ -16,9 +16,9 @@ const REPLACEMENTS = {
|
|
|
16
16
|
};
|
|
17
17
|
function nyloMessage(argv) {
|
|
18
18
|
const replacement = REPLACEMENTS[argv[0] ?? ""];
|
|
19
|
-
return replacement
|
|
19
|
+
return `${replacement
|
|
20
20
|
? `nylo is part of nylorun now: nylo ${argv[0]} is ${replacement}.`
|
|
21
|
-
: "nylo is part of nylorun now: run nylorun --help."
|
|
21
|
+
: "nylo is part of nylorun now: run nylorun --help."} nylorun 0.19 removes nylo.`;
|
|
22
22
|
}
|
|
23
23
|
runCommand(async () => {
|
|
24
24
|
throw new CliError(nyloMessage(process.argv.slice(2)), 2);
|
package/dist/stack/commands.d.ts
CHANGED
|
@@ -51,6 +51,17 @@ interface Flags {
|
|
|
51
51
|
/** Options that may repeat, in order. */
|
|
52
52
|
lists: Map<string, string[]>;
|
|
53
53
|
}
|
|
54
|
+
/** A command's `usage` line (or block, when it starts indented), as `--help` prints it. */
|
|
55
|
+
export declare const usageText: (usage: string) => string;
|
|
56
|
+
/**
|
|
57
|
+
* The lines of a group's usage block that start with command `name` (`secrets`, `settings`),
|
|
58
|
+
* with the lines that continue them, as `--help` prints them.
|
|
59
|
+
*/
|
|
60
|
+
export declare function usageLinesOf(usage: string, name: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* `args` as the options `allowed` names, and the rest. `--help` or `-h` anywhere is a
|
|
63
|
+
* `HelpRequest` for `usage`; an option `allowed` does not name is a usage error.
|
|
64
|
+
*/
|
|
54
65
|
export declare function parseStackFlags(args: readonly string[], allowed: {
|
|
55
66
|
booleans?: readonly string[];
|
|
56
67
|
values?: readonly string[];
|
package/dist/stack/commands.js
CHANGED
|
@@ -3,7 +3,7 @@ import { mkdir, readFile, rm } from "node:fs/promises";
|
|
|
3
3
|
import { basename, resolve } from "node:path";
|
|
4
4
|
import { compareVersions } from "@nylorun/core/compatibility";
|
|
5
5
|
import { findProjectRoot } from "@nylorun/core/project";
|
|
6
|
-
import { CliError } from "../errors.js";
|
|
6
|
+
import { CliError, HelpRequest, isHelp } from "../errors.js";
|
|
7
7
|
import { credentialsPath, readCredentialsFile, readProjectCredentials, readProjectLink, writeProjectCredentials, writeProjectLink, } from "../project/link.js";
|
|
8
8
|
import { seedTenant } from "../project/seed.js";
|
|
9
9
|
import { readTelemetry, STUDIO_ANALYTICS_ID, TELEMETRY_NOTICE, telemetryDecision, writeTelemetry, } from "../telemetry.js";
|
|
@@ -154,6 +154,27 @@ function requireStackFiles(ctx) {
|
|
|
154
154
|
if (!existsSync(ctx.paths.compose) || !existsSync(ctx.paths.env))
|
|
155
155
|
throw new CliError(`No Tenant ${ctx.name} under ${ctx.paths.root}. Run "nylorun start" first.`, 3);
|
|
156
156
|
}
|
|
157
|
+
/** A command's `usage` line (or block, when it starts indented), as `--help` prints it. */
|
|
158
|
+
export const usageText = (usage) => (/^\s/.test(usage) ? `Usage:\n${usage}` : `Usage: ${usage}`);
|
|
159
|
+
/**
|
|
160
|
+
* The lines of a group's usage block that start with command `name` (`secrets`, `settings`),
|
|
161
|
+
* with the lines that continue them, as `--help` prints them.
|
|
162
|
+
*/
|
|
163
|
+
export function usageLinesOf(usage, name) {
|
|
164
|
+
let keep = false;
|
|
165
|
+
const lines = usage.split("\n").filter((line) => {
|
|
166
|
+
if (/^ {2}\S/.test(line))
|
|
167
|
+
keep = line === ` ${name}` || line.startsWith(` ${name} `);
|
|
168
|
+
else if (!/^ {3}/.test(line))
|
|
169
|
+
keep = false;
|
|
170
|
+
return keep;
|
|
171
|
+
});
|
|
172
|
+
return `Usage:\n${lines.join("\n")}`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* `args` as the options `allowed` names, and the rest. `--help` or `-h` anywhere is a
|
|
176
|
+
* `HelpRequest` for `usage`; an option `allowed` does not name is a usage error.
|
|
177
|
+
*/
|
|
157
178
|
export function parseStackFlags(args, allowed, usage) {
|
|
158
179
|
const booleans = new Set();
|
|
159
180
|
const values = new Map();
|
|
@@ -161,6 +182,8 @@ export function parseStackFlags(args, allowed, usage) {
|
|
|
161
182
|
const rest = [];
|
|
162
183
|
for (let index = 0; index < args.length; index += 1) {
|
|
163
184
|
const raw = args[index];
|
|
185
|
+
if (isHelp(raw))
|
|
186
|
+
throw new HelpRequest(usageText(usage));
|
|
164
187
|
const arg = allowed.aliases?.[raw] ?? raw;
|
|
165
188
|
// `-` alone is an argument: standard input.
|
|
166
189
|
if (arg === "-" || !arg.startsWith("-")) {
|
|
@@ -143,7 +143,7 @@ ${healthcheck("restate")} restart: unless-stopped
|
|
|
143
143
|
# Its reachability is in the Tenant's status (GET /v1/tenant, streams.reachable).
|
|
144
144
|
restart: unless-stopped
|
|
145
145
|
|
|
146
|
-
rustfs: # the Object store
|
|
146
|
+
rustfs: # the Object store; not published, only the runtime and the gateway hold its credential
|
|
147
147
|
image: ${PINNED_IMAGES.rustfs}
|
|
148
148
|
container_name: ${project}-rustfs
|
|
149
149
|
labels: *tenant
|
|
@@ -222,7 +222,9 @@ ${healthcheck("gateway")} restart: unless-stopped
|
|
|
222
222
|
# Host headers the Runtime accepts: its name on the Compose network, and the
|
|
223
223
|
# published port as clients on this machine address it.
|
|
224
224
|
NYLORUN_ALLOWED_HOSTS: runtime:4000,localhost:\${NYLORUN_PORT},127.0.0.1:\${NYLORUN_PORT}
|
|
225
|
-
|
|
225
|
+
# The URL clients use: webhook URLs and the OAuth resource. Behind a reverse proxy, its URL
|
|
226
|
+
# (\`NYLORUN_PUBLIC_URL=https://runtime.example.com nylorun start\`).
|
|
227
|
+
NYLORUN_PUBLIC_URL: \${NYLORUN_PUBLIC_URL:-http://localhost:\${NYLORUN_PORT}}
|
|
226
228
|
NYLORUN_DATABASE_URL: postgres://nylorun:\${NYLORUN_POSTGRES_PASSWORD}@postgres:5432/nylorun
|
|
227
229
|
NYLORUN_RESTATE_INGRESS_URL: http://restate:8080
|
|
228
230
|
NYLORUN_RESTATE_ADMIN_URL: http://restate:9070
|
|
@@ -243,7 +245,7 @@ ${healthcheck("gateway")} restart: unless-stopped
|
|
|
243
245
|
NYLORUN_HARNESS_LISTEN_PORT: "4200"
|
|
244
246
|
NYLORUN_HARNESS_ALLOWED_HOSTS: runtime:4200${sandboxes ? SANDBOXES_HARNESS_HOST : ""}
|
|
245
247
|
NYLORUN_HARNESS_TOKEN: \${NYLORUN_HARNESS_TOKEN:?run nylorun start}
|
|
246
|
-
# Traces
|
|
248
|
+
# Traces: from the shell that runs \`nylorun start\`. Unset, they are
|
|
247
249
|
# empty and the Runtime exports nothing. A collector on this machine is host.docker.internal.
|
|
248
250
|
OTEL_EXPORTER_OTLP_ENDPOINT: \${OTEL_EXPORTER_OTLP_ENDPOINT:-}
|
|
249
251
|
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: \${OTEL_EXPORTER_OTLP_TRACES_ENDPOINT:-}
|
package/dist/telemetry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { CliError } from "./errors.js";
|
|
4
|
+
import { CliError, HelpRequest, isHelp } from "./errors.js";
|
|
5
5
|
/**
|
|
6
6
|
* Studio's anonymous usage analytics. Studio's dashboard reports page views,
|
|
7
7
|
* with every id replaced by `:id`, to this Google Analytics property unless the
|
|
@@ -62,6 +62,8 @@ export function telemetryDecision(env, file) {
|
|
|
62
62
|
const USAGE = "Usage: nylorun local telemetry [status|enable|disable]";
|
|
63
63
|
/** `nylorun local telemetry [status|enable|disable]`. */
|
|
64
64
|
export async function telemetryCommand(args, context) {
|
|
65
|
+
if (args.some(isHelp))
|
|
66
|
+
throw new HelpRequest(USAGE);
|
|
65
67
|
const [action = "status", ...rest] = args;
|
|
66
68
|
if (rest.length || !["status", "enable", "disable"].includes(action))
|
|
67
69
|
throw new CliError(USAGE, 2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nylorun",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0-beta",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Set up and run local Nylorun Tenants (Runtime and Studio) with Docker Compose, and act on a Tenant through its Runtime and Management APIs",
|
|
@@ -30,23 +30,23 @@
|
|
|
30
30
|
"prepack": "npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@nylorun/admin": "0.
|
|
34
|
-
"@nylorun/agents": "0.
|
|
35
|
-
"@nylorun/core": "0.
|
|
33
|
+
"@nylorun/admin": "0.19.1-beta",
|
|
34
|
+
"@nylorun/agents": "0.25.0-beta",
|
|
35
|
+
"@nylorun/core": "0.25.0-beta"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@earendil-works/pi-ai": "
|
|
38
|
+
"@earendil-works/pi-ai": "1.2.0",
|
|
39
39
|
"@nylorun/agents": "file:../../sdks/agents",
|
|
40
40
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
41
|
-
"@types/node": "^26.6.
|
|
42
|
-
"vitest": "^5.0.
|
|
41
|
+
"@types/node": "^26.6.5",
|
|
42
|
+
"vitest": "^5.0.4"
|
|
43
43
|
},
|
|
44
44
|
"bin": {
|
|
45
45
|
"nylorun": "dist/cli.js",
|
|
46
46
|
"nylo": "dist/nylo.js"
|
|
47
47
|
},
|
|
48
48
|
"nylorun": {
|
|
49
|
-
"runtime": "0.
|
|
50
|
-
"studio": "0.
|
|
49
|
+
"runtime": "0.29.0-beta",
|
|
50
|
+
"studio": "0.28.0-beta"
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type EnvironmentManifestInput } from "@nylorun/agents";
|
|
2
|
-
import type { StackDeps } from "../stack/commands.js";
|
|
3
|
-
export declare const manifestsUsage = " manifests list [--json] each environment manifest's latest version\n manifests get <name> [--version <n>]\n a manifest's latest version (or version n), as JSON\n manifests versions <name> its versions, with the Environments made from each\n manifests save <manifest.json>... [--if-match <n>] [--dry-run]\n save each manifest's next version (a files entry with\n \"from\": a folder beside the file, uploaded by hash);\n --dry-run prints the plan and saves nothing\n manifests rm <name> delete every version (refused while an Environment\n was made from one)";
|
|
4
|
-
/** The manifest in `path`, its `from` folders hashed: the body to save and the bytes to upload. */
|
|
5
|
-
export declare function manifestFrom(path: string): Promise<{
|
|
6
|
-
manifest: EnvironmentManifestInput;
|
|
7
|
-
bytes: Record<string, Uint8Array>;
|
|
8
|
-
}>;
|
|
9
|
-
/** `nylorun environments manifests <command> ...` */
|
|
10
|
-
export declare function manifestsCommand(deps: StackDeps, args: readonly string[], usage: string): Promise<number>;
|