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.
@@ -1,5 +1,6 @@
1
1
  /**
2
- * `nylorun sessions`: the Tenant's sessions (`/v1/sessions`, Runtime API): open one, send it a
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>] [--status <status>] [--environment <id>] [--owner <user>]
14
+ list [--agent <id>] [--manifest <name>] [--status <status>] [--owner <user>]
14
15
  [--limit <n>] [--cursor <c>] [--json]
15
- create --agent <id> --owner <user> [--environment <id>] [--id <id>] [--info <json>]
16
- open a session; prints its id
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
- start a turn with text, JSON data or files (artifacts)
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>] [--status <s>] [--environment <id>] [--owner <user>] [--limit <n>] [--cursor <c>] [--json]";
38
- const flags = parseFlags(args, { booleans: ["--json"], values: ["--agent", "--status", "--environment", "--owner", "--limit", "--cursor"] }, usage);
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("--environment") ? { environmentId: value("--environment") } : {}),
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", "ENVIRONMENT", "LAST EVENT"],
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> [--environment <id>] [--id <id>] [--info <json>]";
74
- const flags = parseFlags(args, { values: ["--agent", "--owner", "--environment", "--id", "--info"] }, usage);
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 = { idempotencyKey: flags.values.get("--idempotency-key") ?? randomUUID() };
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
@@ -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 Environment settings: 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, Environments, model calls, tools)\n coverage --agent <id> [--environment <id>] [--tenant <name>] [--json]\n which secret of the Environment each of the agent's MCP\n servers and HTTP tools would get";
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 `--environment` each remote MCP server and HTTP tool
9
- * of saved agent `--agent` would get in a session (none without an Environment). It reads no
10
- * secret and calls no server.
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>;
@@ -4,21 +4,22 @@ import { parseStackFlags } 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; put replaces them all
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 Environment settings: limits, stop grace, placement
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, Environments, model calls, tools)
19
- coverage --agent <id> [--environment <id>] [--tenant <name>] [--json]
20
- which secret of the Environment each of the agent's MCP
21
- servers and HTTP tools would get`;
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 = {
@@ -86,29 +87,27 @@ export async function settingsCommand(deps, args) {
86
87
  return documentCommand(deps, limitSettings, rest);
87
88
  throw usageError();
88
89
  }
89
- const COVERAGE_USAGE = "nylorun tenant coverage --agent <id> [--environment <id>] [--tenant <name>] [--json]";
90
+ const COVERAGE_USAGE = "nylorun tenant coverage --agent <id> [--tenant <name>] [--json]";
90
91
  /**
91
- * `nylorun tenant coverage`: which secret of `--environment` each remote MCP server and HTTP tool
92
- * of saved agent `--agent` would get in a session (none without an Environment). It reads no
93
- * secret and calls no server.
92
+ * `nylorun tenant coverage`: which secret of Agent `--agent`'s vault each remote MCP server and
93
+ * HTTP tool of the manifest version it runs would get in its sessions. It reads no secret and
94
+ * calls no server.
94
95
  */
95
96
  export async function coverageCommand(deps, args) {
96
- const flags = parseStackFlags(args, { booleans: ["--json"], values: ["--tenant", "--agent", "--environment"] }, COVERAGE_USAGE);
97
+ if (args.includes("--environment"))
98
+ throw usageError("--environment was removed in protocol 16: pass the Agent, --agent <id>, whose vault its sessions use.");
99
+ const flags = parseStackFlags(args, { booleans: ["--json"], values: ["--tenant", "--agent"] }, COVERAGE_USAGE);
97
100
  const agentId = flags.values.get("--agent");
98
- const environmentId = flags.values.get("--environment");
99
101
  if (flags.rest.length || agentId === undefined)
100
102
  throw usageError(`Usage: ${COVERAGE_USAGE}`);
101
103
  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
- });
104
+ const coverage = await admin.coverage({ agentId });
106
105
  if (flags.booleans.has("--json")) {
107
106
  printJson(deps, coverage);
108
107
  return 0;
109
108
  }
110
109
  const missing = coverage.entries.filter((entry) => entry.status === "missing").length;
111
- deps.out(`${coverage.agentId} in ${coverage.environmentId ?? "no Environment"}: ${coverage.complete ? "every credential is covered" : `${missing} of ${coverage.entries.length} missing`}`);
110
+ deps.out(`Agent ${coverage.agentId}: ${coverage.complete ? "every credential is covered" : `${missing} of ${coverage.entries.length} missing`}`);
112
111
  if (coverage.entries.length)
113
112
  printTable(deps, [
114
113
  ["STATUS", "KIND", "NAME", "URL", "SECRET"],
@@ -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|--environments|--all] [--yes] [--tenant <name>]\n clear the Tenant's sessions, Environments or all its data\n (the Project link and 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|agent|turn] [--id <id>] [--period day|month|total] [--tenant <name>]\n what the model calls used and cost (JSON)\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; 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 Environment settings: 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, Environments, model calls, tools)\n coverage --agent <id> [--environment <id>] [--tenant <name>] [--json]\n which secret of the Environment each of the agent's MCP\n servers and HTTP tools would get\n mcp inspect <url> [--server <name>] [--environment <id>] [--sse] [--tenant <name>] [--json]\n list a remote MCP server's tools, with Environment <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.";
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;
@@ -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|--environments|--all] [--yes] [--tenant <name>]
17
- clear the Tenant's sessions, Environments or all its data
18
- (the Project link and keys stay)
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|--environments|--all] [--yes] [--tenant <name>]";
68
- const SCOPES = { "--sessions": "sessions", "--environments": "environments", "--all": "all" };
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, --environments, --all.");
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")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nylorun",
3
- "version": "0.16.0-beta",
3
+ "version": "0.17.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.18.0-beta",
34
- "@nylorun/agents": "0.23.0-beta",
35
- "@nylorun/core": "0.23.0-beta"
33
+ "@nylorun/admin": "0.19.0-beta",
34
+ "@nylorun/agents": "0.24.0-beta",
35
+ "@nylorun/core": "0.24.0-beta"
36
36
  },
37
37
  "devDependencies": {
38
- "@earendil-works/pi-ai": "0.99.1",
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.4",
42
- "vitest": "^5.0.2"
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.27.0-beta",
50
- "studio": "0.26.0-beta"
49
+ "runtime": "0.28.0-beta",
50
+ "studio": "0.27.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>;
@@ -1,173 +0,0 @@
1
- /**
2
- * `nylorun environments manifests`: the Tenant's environment manifests (protocol 14, D63), named
3
- * and versioned definitions of a kind of Environment, saved like agents. `save` reads each JSON
4
- * file (its `$schema` is dropped), turns a `files` entry with `from` (a folder, relative to the
5
- * file) into files by content hash and uploads those the Runtime lacks, then saves the next
6
- * version under `If-Match` when `--if-match` is given. `--dry-run` prints the plan and exits 1
7
- * when the Runtime would refuse the save.
8
- */
9
- import { readdir, readFile } from "node:fs/promises";
10
- import { dirname, join, relative, resolve, sep } from "node:path";
11
- import { environmentFiles } from "@nylorun/agents";
12
- import { CliError } from "../errors.js";
13
- import { integerFlag, parseFlags, positional, printJson, printTable, readJson, runtimeCall, runtimeClient, usageError, } from "./runtime.js";
14
- export const manifestsUsage = ` manifests list [--json] each environment manifest's latest version
15
- manifests get <name> [--version <n>]
16
- a manifest's latest version (or version n), as JSON
17
- manifests versions <name> its versions, with the Environments made from each
18
- manifests save <manifest.json>... [--if-match <n>] [--dry-run]
19
- save each manifest's next version (a files entry with
20
- "from": a folder beside the file, uploaded by hash);
21
- --dry-run prints the plan and saves nothing
22
- manifests rm <name> delete every version (refused while an Environment
23
- was made from one)`;
24
- /** Each file under `dir`, by its path relative to it (`/`-separated). */
25
- async function folderOf(dir) {
26
- const found = {};
27
- const visit = async (at) => {
28
- for (const entry of await readdir(at, { withFileTypes: true })) {
29
- const path = join(at, entry.name);
30
- if (entry.isDirectory())
31
- await visit(path);
32
- else if (entry.isFile())
33
- found[relative(dir, path).split(sep).join("/")] = new Uint8Array(await readFile(path));
34
- }
35
- };
36
- try {
37
- await visit(dir);
38
- }
39
- catch (error) {
40
- throw new CliError(`Cannot read ${dir}: ${error.message}`, 1);
41
- }
42
- if (Object.keys(found).length === 0)
43
- throw new CliError(`${dir} holds no files.`, 1);
44
- return found;
45
- }
46
- /** The manifest in `path`, its `from` folders hashed: the body to save and the bytes to upload. */
47
- export async function manifestFrom(path) {
48
- const raw = await readJson(path, "The manifest");
49
- if (typeof raw.name !== "string" || raw.name === "")
50
- throw usageError(`${path}: the manifest has no name.`);
51
- const bytes = {};
52
- const files = Array.isArray(raw.files) ? raw.files : undefined;
53
- const entries = [];
54
- for (const entry of files ?? []) {
55
- if (typeof entry?.from !== "string") {
56
- entries.push(entry);
57
- continue;
58
- }
59
- const { from, ...rest } = entry;
60
- if (typeof rest.path !== "string")
61
- throw usageError(`${path}: a files entry with from needs a path.`);
62
- const folder = await environmentFiles(rest.path, await folderOf(resolve(dirname(path), from)));
63
- Object.assign(bytes, folder.bytes);
64
- entries.push({ ...rest, files: folder.entry.files });
65
- }
66
- const { $schema: _schema, ...manifest } = raw;
67
- return {
68
- manifest: (files === undefined ? manifest : { ...manifest, files: entries }),
69
- bytes,
70
- };
71
- }
72
- async function save(deps, args) {
73
- const usage = "nylorun environments manifests save <manifest.json>... [--if-match <n>] [--dry-run]";
74
- const flags = parseFlags(args, { booleans: ["--dry-run"], values: ["--if-match"] }, usage);
75
- if (flags.rest.length === 0)
76
- throw usageError(`Usage: ${usage}`);
77
- const ifMatch = integerFlag(flags, "--if-match");
78
- if (ifMatch !== undefined && flags.rest.length > 1)
79
- throw usageError("--if-match takes one manifest.");
80
- const { client, connection } = await runtimeClient(deps, flags);
81
- let blocked = false;
82
- for (const path of flags.rest) {
83
- const { manifest, bytes } = await manifestFrom(path);
84
- const options = { files: bytes, ...(ifMatch === undefined ? {} : { ifMatch }) };
85
- if (flags.booleans.has("--dry-run")) {
86
- const plan = await runtimeCall(() => client.environments.manifests.plan(manifest, options));
87
- printJson(deps, plan);
88
- if (plan.errors.length > 0)
89
- blocked = true;
90
- continue;
91
- }
92
- const saved = await runtimeCall(() => client.environments.manifests.save(manifest, options));
93
- deps.err(saved.unchanged
94
- ? `Environment manifest ${saved.manifest.name} is unchanged at version ${saved.manifest.version} on ${connection.label}.`
95
- : `Saved environment manifest ${saved.manifest.name} version ${saved.manifest.version} on ${connection.label}.`);
96
- for (const warning of saved.warnings)
97
- deps.err(` warning: ${warning.message}`);
98
- printJson(deps, saved);
99
- }
100
- return blocked ? 1 : 0;
101
- }
102
- async function list(deps, args) {
103
- const usage = "nylorun environments manifests list [--json]";
104
- const flags = parseFlags(args, { booleans: ["--json"] }, usage);
105
- positional(flags, 0, usage);
106
- const { client, connection } = await runtimeClient(deps, flags);
107
- const manifests = await runtimeCall(() => client.environments.manifests.list());
108
- if (flags.booleans.has("--json")) {
109
- printJson(deps, manifests);
110
- return 0;
111
- }
112
- if (manifests.length === 0)
113
- deps.out(`No environment manifests on ${connection.label}.`);
114
- else
115
- printTable(deps, [
116
- ["NAME", "VERSION", "KIND", "ENVIRONMENTS", "SAVED BY"],
117
- ...manifests.map((manifest) => [
118
- manifest.name,
119
- String(manifest.version),
120
- manifest.manifest.kind ?? "virtual",
121
- String(manifest.environments),
122
- manifest.savedBy.actor,
123
- ]),
124
- ]);
125
- return 0;
126
- }
127
- async function get(deps, args) {
128
- const usage = "nylorun environments manifests get <name> [--version <n>]";
129
- const flags = parseFlags(args, { values: ["--version"] }, usage);
130
- const [name] = positional(flags, 1, usage);
131
- const version = integerFlag(flags, "--version");
132
- const { client } = await runtimeClient(deps, flags);
133
- printJson(deps, await runtimeCall(() => client.environments.manifests.get(name, version === undefined ? {} : { version })));
134
- return 0;
135
- }
136
- async function versions(deps, args) {
137
- const usage = "nylorun environments manifests versions <name>";
138
- const flags = parseFlags(args, {}, usage);
139
- const [name] = positional(flags, 1, usage);
140
- const { client } = await runtimeClient(deps, flags);
141
- printJson(deps, await runtimeCall(() => client.environments.manifests.versions(name)));
142
- return 0;
143
- }
144
- async function remove(deps, args) {
145
- const usage = "nylorun environments manifests rm <name>";
146
- const flags = parseFlags(args, {}, usage);
147
- const [name] = positional(flags, 1, usage);
148
- const { client, connection } = await runtimeClient(deps, flags);
149
- const deleted = await runtimeCall(() => client.environments.manifests.delete(name));
150
- if (!deleted.deleted) {
151
- deps.err(`No environment manifest ${name} on ${connection.label}.`);
152
- return 1;
153
- }
154
- deps.out(`Deleted environment manifest ${name}: every version.`);
155
- return 0;
156
- }
157
- const COMMANDS = {
158
- list,
159
- ls: list,
160
- get,
161
- versions,
162
- save,
163
- rm: remove,
164
- delete: remove,
165
- };
166
- /** `nylorun environments manifests <command> ...` */
167
- export async function manifestsCommand(deps, args, usage) {
168
- const [sub, ...rest] = args;
169
- const command = sub !== undefined && Object.hasOwn(COMMANDS, sub) ? COMMANDS[sub] : undefined;
170
- if (!command)
171
- throw usageError(`Usage: nylorun environments manifests <list|get|versions|save|rm> …\n\n${usage}`);
172
- return command(deps, rest);
173
- }
@@ -1,4 +0,0 @@
1
- import type { StackDeps } from "../stack/commands.js";
2
- export declare const environmentsUsage: string;
3
- /** `nylorun environments <command> ...` */
4
- export declare function environmentsCommand(deps: StackDeps, args: readonly string[]): Promise<number>;