nylorun 0.29.3-beta → 0.29.5-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 CHANGED
@@ -1,5 +1,47 @@
1
1
  # nylorun
2
2
 
3
+ ## 0.29.5-beta
4
+
5
+ ### Patch Changes
6
+
7
+ - 71c6741: Pods on Agent Substrate (preview): a crashed sandbox is now recorded in the Agent's events. A running pod whose sandbox crashed is `failed` at once, rather than after the 5-minute ready deadline. A crash that an idle suspend finds is also recorded, where before the Agent showed only `agent.suspended`. In both cases `agent.failed` gives Substrate's crash message and says that what the Agent wrote since its last suspend is lost. The next turn reverts the sandbox to that suspend, as before. The sandboxes service now reports the crash's own message in place of the whole crash record.
8
+ - fe118db: A message's `removeTools` turns a Runtime plugin's tool off by its own name too: `memory` now does what `nylorun__memory` does, so the name events and `check --explain` showed no longer leaves the tool on without a word (#589). `nylorun check --explain` lists a plugin's tools by the names the model reads (`nylorun__memory`, `nylorun__update_plan`), the ones `removeTools` and tool policy take, and its memory note says the index is pinned again at a turn after a write from elsewhere (#590, #591).
9
+ - fe118db: The Tenant's sandbox settings round-trip, and `engine.images` comes back (#588).
10
+
11
+ - **Breaking (`@nylorun/runtime`, `@nylorun/core`, `@nylorun/admin`): `config` is the settings as stored.** `GET` and `PUT /v1/tenant/sandbox` (`admin.settings.sandbox`) answer `config` as the Tenant set it, with no defaults, in exactly the shape `PUT` takes (`limits.resources.memory: "8GiB"`), so `put(get().config)` changes nothing and saves no default as a setting. The settings in force, every default filled in and sizes in MiB (`memoryMiB`), are `effective`, which is what `config` was. Before, `PUT` refused what `GET` answered (`unrecognized_keys "memoryMiB"`). Read the settings in force from `effective` (`view.effective.limits.resources.memoryMiB`), and build a `PUT` body from `view.config`. `TenantSandboxViewSchema` has `config: TenantEnvironmentsConfigSchema` and `effective: EffectiveSandboxConfigSchema`.
12
+ - **`engine.images` is answered.** A `PUT` with `engine.images` was stored and used, but left out of its answer and of the next `GET`. Both now carry it, in `config` as set and in `effective` (`[]` when unset).
13
+ - `@nylorun/studio`: Edit compute settings puts the stored settings with only the fields it changed, so it no longer erases `engine.images` set through the API, keeps `placement`, and saves no default as a setting; clearing idle, stop grace or most Agents puts back the default. The Compute tab lists the engine images.
14
+ - `nylorun`: `nylorun tenant settings sandbox put` takes what `get` printed and puts back its `config`. `nylorun doctor sandbox` reads the limits in force from `effective`, or from `config` on an older Runtime.
15
+
16
+ - Pin core to the tested release.
17
+ - Pin agents to the tested release.
18
+ - Pin admin to the tested release.
19
+ - Pin runtime to the tested release.
20
+ - Pin studio to the tested release.
21
+ - Updated dependencies [fe118db]
22
+ - Updated dependencies [fe118db]
23
+ - Updated dependencies
24
+ - Updated dependencies
25
+ - @nylorun/core@0.41.0-beta
26
+ - @nylorun/agents@0.36.4-beta
27
+ - @nylorun/admin@0.20.0-beta
28
+
29
+ ## 0.29.4-beta
30
+
31
+ ### Patch Changes
32
+
33
+ - 4b91451: Pods on Agent Substrate (preview):
34
+
35
+ - **A crashed actor recovers.** A wake that finds the actor crashed, or that crashes it, reverts the actor to its last snapshot once and resumes it, as Substrate requires. Before, the Agent stayed failed until it was reset.
36
+ - **A wake during an idle suspend is no longer lost.** The resume waits for the suspend to finish instead of dropping the wake.
37
+ - **One resume call per wake.** It is no longer cancelled after 2 minutes, which also cancelled the restore in progress. It is tried again only while Substrate is busy, for at most 5 minutes (the Runtime's own ready deadline). It stops as soon as a later request replaces it, and holds no lock during the call.
38
+ - **Each resume is logged** as `substrate resumed` with its time in `ms`.
39
+ - **Removed:**
40
+ - `RES_OPTIONS`, which is no longer set in the actor's environment. The edge's `/etc/hosts` pin already spares the engine any DNS lookup, and the Agent's own resolver is its own.
41
+ - The shutdown-time sweep, since the Runtime never sends a shutdown time.
42
+
43
+ - Pin runtime to the tested release.
44
+
3
45
  ## 0.29.3-beta
4
46
 
5
47
  ### Patch Changes
package/README.md CHANGED
@@ -420,7 +420,7 @@ runs, its kind, state, sessions, owner and labels; `nylorun agents rm <id>`
420
420
  deletes one, with its files and vault (refused while a turn runs on it). Neither
421
421
  starts a stopped Tenant (exit 3). The Tenant's limits for Agents
422
422
  (`limits.environments`, `idle`, resources, network) are `PUT /v1/tenant/sandbox`
423
- on the Management API.
423
+ on the Management API (`nylorun tenant settings sandbox`).
424
424
 
425
425
  ### Pods on a cluster (preview)
426
426
 
@@ -843,8 +843,16 @@ nylorun tenant tool-policy get > tool-policy.json # edit it, then
843
843
  nylorun tenant tool-policy put tool-policy.json
844
844
  ```
845
845
 
846
- `settings sandbox get` prints the effective settings and what the Host offers;
847
- its `put` takes the settings alone (`limits`, `lifecycle`, `placement`).
846
+ `settings sandbox get` prints what the Host offers, the Tenant's settings as
847
+ stored (`config`: only what it set, the body `put` takes) and the settings in
848
+ force (`effective`: every default filled in, sizes in MiB). Its `put` takes the
849
+ settings alone (`limits`, `lifecycle`, `engine`, `placement`), or what `get`
850
+ printed, of which it puts back `config`, so no default becomes a setting:
851
+
852
+ ```sh
853
+ nylorun tenant settings sandbox get > sandbox.json # edit its config, then
854
+ nylorun tenant settings sandbox put sandbox.json
855
+ ```
848
856
 
849
857
  `settings limits` is the Tenant's Runtime limits: the sizes, counts and
850
858
  deadlines the Runtime holds what crosses it to, such as `recordEntryBytes`,
@@ -1,4 +1,11 @@
1
1
  import type { StackDeps } from "../stack/commands.js";
2
+ type EffectiveLimits = {
3
+ limits?: {
4
+ network?: readonly string[];
5
+ idle?: string;
6
+ environments?: number;
7
+ };
8
+ };
2
9
  export type SandboxReport = {
3
10
  preference: string;
4
11
  backend: string | null;
@@ -12,14 +19,12 @@ export type SandboxReport = {
12
19
  version?: string;
13
20
  }[];
14
21
  defaultImage?: string;
15
- /** The Tenant's settings for Agents' environments in force (`environments.config`). */
16
- config?: {
17
- limits?: {
18
- network?: readonly string[];
19
- idle?: string;
20
- environments?: number;
21
- };
22
- };
22
+ /**
23
+ * The Tenant's settings for Agents' environments in force (`environments.config` with the
24
+ * defaults). A Runtime before #588 sends them as `config`, which now holds the stored settings.
25
+ */
26
+ effective?: EffectiveLimits;
27
+ config?: EffectiveLimits;
23
28
  /** The Tenant's cluster for pod Agents (`nylorun local sandbox enable`), when it has one. */
24
29
  cluster?: {
25
30
  namespace: string;
@@ -38,3 +43,4 @@ export declare function doctorSandbox(deps: StackDeps, options: {
38
43
  json: boolean;
39
44
  tenant?: string;
40
45
  }): Promise<void>;
46
+ export {};
@@ -47,7 +47,7 @@ export async function doctorSandbox(deps, options) {
47
47
  "sessions",
48
48
  "run on an Agent, with the sandbox its manifest's runtime.kind gives (createSession({ agent }))",
49
49
  ]);
50
- const limits = report.config?.limits;
50
+ const limits = (report.effective ?? report.config)?.limits;
51
51
  if (limits)
52
52
  rows.push([
53
53
  "limits",
@@ -18,10 +18,11 @@ export interface BodySchema<T> {
18
18
  export declare function readText(deps: StackDeps, source: string): Promise<string>;
19
19
  /**
20
20
  * The JSON body in file `source`, or on standard input for `-`, as `schema` parses it. Fields
21
- * named in `readOnly` (a view's, so a `get` can be edited and put back) are dropped first. A
22
- * body that does not parse is a usage error, before any request.
21
+ * named in `readOnly` (a view's, so a `get` can be edited and put back) are dropped first. With
22
+ * `bodyField`, a view that holds the body in that field (`get`'s whole output) is read as that
23
+ * field. A body that does not parse is a usage error, before any request.
23
24
  */
24
- export declare function readBody<T>(deps: StackDeps, source: string, schema: BodySchema<T>, readOnly?: readonly string[]): Promise<T>;
25
+ export declare function readBody<T>(deps: StackDeps, source: string, schema: BodySchema<T>, readOnly?: readonly string[], bodyField?: string): Promise<T>;
25
26
  /**
26
27
  * A secret piped in on standard input (its trailing newline dropped), so it is never in the
27
28
  * arguments, the shell's history or the process list. `what` names it in the refusals.
package/dist/client/io.js CHANGED
@@ -26,10 +26,11 @@ export async function readText(deps, source) {
26
26
  }
27
27
  /**
28
28
  * The JSON body in file `source`, or on standard input for `-`, as `schema` parses it. Fields
29
- * named in `readOnly` (a view's, so a `get` can be edited and put back) are dropped first. A
30
- * body that does not parse is a usage error, before any request.
29
+ * named in `readOnly` (a view's, so a `get` can be edited and put back) are dropped first. With
30
+ * `bodyField`, a view that holds the body in that field (`get`'s whole output) is read as that
31
+ * field. A body that does not parse is a usage error, before any request.
31
32
  */
32
- export async function readBody(deps, source, schema, readOnly = []) {
33
+ export async function readBody(deps, source, schema, readOnly = [], bodyField) {
33
34
  let text;
34
35
  if (source === "-") {
35
36
  text = await readStdin(deps, "Pipe the JSON body in on standard input, or name a file.");
@@ -50,6 +51,9 @@ export async function readBody(deps, source, schema, readOnly = []) {
50
51
  catch (error) {
51
52
  throw usageError(`${where} is not JSON: ${error.message}.`);
52
53
  }
54
+ const isObject = (item) => Boolean(item) && typeof item === "object" && !Array.isArray(item);
55
+ if (bodyField && isObject(value) && isObject(value[bodyField]))
56
+ value = value[bodyField];
53
57
  if (value && typeof value === "object" && !Array.isArray(value))
54
58
  value = Object.fromEntries(Object.entries(value).filter(([key]) => !readOnly.includes(key)));
55
59
  const parsed = schema.safeParse(value);
@@ -1,5 +1,5 @@
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 (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";
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, engine\n images, placement; put takes get's output back\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 ...` */
@@ -9,7 +9,8 @@ export const settingsUsage = ` budgets [get | put <file|->] [--tenant <name>]
9
9
  tool-policy [get | put <file|->] [--tenant <name>]
10
10
  the Tool Gate's rules; put replaces them all
11
11
  settings sandbox [get | put <file|->] [--tenant <name>]
12
- the Agents' environments: limits, stop grace, placement
12
+ the Agents' environments: limits, stop grace, engine
13
+ images, placement; put takes get's output back
13
14
  settings artifacts [get | put <file|->] [--tenant <name>]
14
15
  the artifact store's limits
15
16
  settings skills [get | put <file|->] [--tenant <name>]
@@ -38,6 +39,9 @@ const toolPolicy = {
38
39
  const sandbox = {
39
40
  name: "settings sandbox",
40
41
  schema: PutTenantEnvironmentsRequestSchema,
42
+ // `get` prints the backend report, the stored settings (`config`) and those in force
43
+ // (`effective`); `put` of that output puts its `config` back, so no default becomes an override.
44
+ bodyField: "config",
41
45
  get: (admin) => admin.settings.sandbox.get(),
42
46
  put: (admin, body) => admin.settings.sandbox.put(body),
43
47
  };
@@ -67,7 +71,9 @@ async function documentCommand(deps, document, args) {
67
71
  const [verb = "get", ...operands] = flags.rest;
68
72
  if (!((verb === "get" && !operands.length) || (verb === "put" && operands.length === 1)))
69
73
  throw usageError(`Usage: ${usage}`);
70
- const body = verb === "put" ? await readBody(deps, operands[0], document.schema, document.readOnly) : undefined;
74
+ const body = verb === "put"
75
+ ? await readBody(deps, operands[0], document.schema, document.readOnly, document.bodyField)
76
+ : undefined;
71
77
  const admin = managementClient(deps, await connect(deps, "management", flags.values.get("--tenant")));
72
78
  printJson(deps, body === undefined ? await document.get(admin) : await document.put(admin, body));
73
79
  return 0;
@@ -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|--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 set --provider google-vertex --model <id> --host-identity --project <id> --location <location> [--tenant <name>]\n the same with the Host's Google identity, no key: on a Host\n whose operator sets NYLORUN_MODEL_HOST_IDENTITY\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.";
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 set --provider google-vertex --model <id> --host-identity --project <id> --location <location> [--tenant <name>]\n the same with the Host's Google identity, no key: on a Host\n whose operator sets NYLORUN_MODEL_HOST_IDENTITY\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, engine\n images, placement; put takes get's output back\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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nylorun",
3
- "version": "0.29.3-beta",
3
+ "version": "0.29.5-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,9 +30,9 @@
30
30
  "prepack": "npm run build"
31
31
  },
32
32
  "dependencies": {
33
- "@nylorun/admin": "0.19.16-beta",
34
- "@nylorun/agents": "0.36.3-beta",
35
- "@nylorun/core": "0.40.0-beta"
33
+ "@nylorun/admin": "0.20.0-beta",
34
+ "@nylorun/agents": "0.36.4-beta",
35
+ "@nylorun/core": "0.41.0-beta"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@earendil-works/pi-ai": "1.3.0",
@@ -46,7 +46,7 @@
46
46
  "nylo": "dist/nylo.js"
47
47
  },
48
48
  "nylorun": {
49
- "runtime": "0.46.1-beta",
50
- "studio": "0.35.9-beta"
49
+ "runtime": "0.47.0-beta",
50
+ "studio": "0.35.10-beta"
51
51
  }
52
52
  }