nylorun 0.19.0-beta → 0.20.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 CHANGED
@@ -1,5 +1,58 @@
1
1
  # nylorun
2
2
 
3
+ ## 0.20.0-beta
4
+
5
+ ### Minor Changes
6
+
7
+ - 498d972: `nylorun check --fix` makes the edits the compiler's diagnostics carry (track T7). A diagnostic one edit fixes has a `fix` (`AgentFolderFix`, in `AgentFolderDiagnostic` and the Runtime API's): `rename_key` for an unknown key with exactly one did-you-mean (in `AGENT.md`, a trigger, a `SKILL.md`, a tool file, `runtime.json`, `mcp.json`, `flow.json` and a JSON Schema's keywords), at its line and column, and none when two keys are as close or the key it would be is already there; `crlf` for a file with CRLF line ends, which is now a `crlf` note (it is read as LF, as before); and `move_skill_secrets` for `secrets` in a root skill's `SKILL.md`, when `AGENT.md` lists none for the skill, or lists them all. Messages, manifests and hashes are unchanged. `applyFolderFixes` in `@nylorun/core/folder` makes them on text: the key token renamed with every other byte kept, LF line ends, and the secrets moved to `AGENT.md`'s `skills` block as `migrate folder` writes it, skipping (with why) a fix whose text is no longer where it was.
8
+
9
+ `nylorun check` marks each fixable problem `(fixable with --fix)` and writes nothing. `check --fix` makes the edits in the folder's files, prints each change by file, and checks again until nothing is left to fix; it leaves a file whose bytes changed since it was checked (writing nothing when one changes while it fixes), and a `runtime.json` that `extends` another. `check --json` gives each diagnostic's `fix`, and with `--fix` each folder's `fixed` and `unfixed`.
10
+
11
+ - b3dad06: Agent folders convert both ways (track T7, D80). `folderOfManifest(manifest)` in `@nylorun/core/folder` (also exported by `@nylorun/agents`) writes the agent folder that compiles back to the same manifest: name, description, metadata, harness, memory, loop and server and skill settings in `AGENT.md`, the first instruction as its body and the rest as `instructions/NN-*.md`, HTTP tools as `tools/<name>.json`, subagents as `agents/<name>/`, a flow as `flow.json` (v3's node tree, naming agents by id and tools by file name) with one flat `agents/<id>/` for its agents and its sub-flows' (a sub-flow is an `agents/<id>/` with its own `flow.json`, and a tool stage or HTTP verifier a `tools/<name>.json` beside the `flow.json` that names it), MCP servers in `mcp.json` with `Bearer ${SLOT}` or `${SLOT}` for a credential, triggers as `triggers/<id>.md`, and `runtime.json` without the slots the compiler derives the same way. It checks itself by compiling the folder, says whether the hash is the same (`exact`), and notes what it writes differently. Skills are written from their bytes when given them, else as a placeholder with the files to copy in. An embedded agent's display `name` is left out with a note, since a folder names an agent by its id.
12
+
13
+ `nylorun export --folder <name>[@<version>]` writes the folder of a saved manifest, from JSON or TypeScript; `nylorun migrate folder <dir>` writes the folder of a three-file folder, offline, with its skills; `nylorun pull <name>[@<version>]` writes back the folder a version was saved from, byte for byte, and says to use `export --folder` for a version saved as JSON. None writes over a file with other bytes.
14
+
15
+ Deprecated, still read: the three-file format (`agent.manifest.json`), whose `composeManifest` and `nylorun apply` now warn and name `nylorun migrate folder`, and `secrets` in a `SKILL.md`, which the skills loader warns about (a `DeprecationWarning` from `.skills()`): an agent folder lists a skill's secrets in `AGENT.md`.
16
+
17
+ - b3dad06: Both ends of the agent folder loop (track T7).
18
+
19
+ - `nylorun init <path>` names the agent after the path's last segment (`init agents/hello`). `--example` adds `tools/get_order.json`, `mcp.json` (a `Bearer ${ORDERS_MCP_TOKEN}` header) and `triggers/new-order.md`, explained in the folder's README.md, and the result passes `nylorun check`. The first run in a project (the nearest directory with `.git`) writes `.gitattributes` (`* text=auto eol=lf`), ignores `.nylorun/credentials.json` in `.gitignore`, and maps the folder files to their JSON Schemas in `.vscode/settings.json`, merged into an existing file. Its hint names `apply --agent` and `chat`.
20
+ - `nylorun apply --agent [<id>]` makes the Agent from the manifest after a save (or on an unchanged one), or moves it, as `nylorun agents put` does, and prints what it needs a person for.
21
+ - `nylorun apply --watch [--save]` checks and plans again on each change to the folders (and the files their `runtime.json` extends); it saves only with `--save`.
22
+ - A plan's change to the instructions prints their text diff, `-` and `+` lines.
23
+ - `nylorun chat <agent> [--session <id>] [--message <text>]` opens or reuses a session, sends `--message` or each line of standard input, and prints the reply as it comes.
24
+ - `nylorun check --json` prints `{ folders: [{ path, ok, manifest?, diagnostics }] }` for CI, with the same exit codes. `check` says "1 file", and `nylorun --version` prints the version.
25
+ - `packFolder` (`@nylorun/agents`) leaves out what the folder's `.nyloignore` names (gitignore rules), and resolves `extends` in `runtime.json`: the packed file is the merge, the folder's own keys winning, with `.nylorun/origin.json` naming the files it came from; a missing file or a cycle is a `FolderError`. `ignoreMatcher` is exported.
26
+ - `session.approve(id, approved)` and `session.respond(id, value)` take no options: each makes its own idempotency key.
27
+ - The Runtime's Agent view names each required secret of the version it runs that has no value, as an attention item (`secret_unset: required secret ORDERS_TOKEN unset`, state `input_required`), until it is set.
28
+ - The compiler's refusal of an unresolved `extends` says to resolve it before uploading.
29
+
30
+ ### Patch Changes
31
+
32
+ - 498d972: `@nylorun/agents` exports `harnessSectionOf` and `sectionGaps` from its main entry, as its README documents: the harness section `agentManifests.save` makes from a built agent or flow, and the gaps the Runtime refuses between a manifest's two sections. Both were only in `@nylorun/agents/define` and `@nylorun/core/define`.
33
+
34
+ `nylo` no longer says nylorun 0.19 removes it, which 0.19 does not: its message ends "A later nylorun release removes nylo."
35
+
36
+ - Pin core to the tested release.
37
+ - Pin agents to the tested release.
38
+ - Pin admin to the tested release.
39
+ - Pin runtime to the tested release.
40
+ - Pin studio to the tested release.
41
+ - Updated dependencies [7bcdc85]
42
+ - Updated dependencies [498d972]
43
+ - Updated dependencies [498d972]
44
+ - Updated dependencies [d23304e]
45
+ - Updated dependencies [b3dad06]
46
+ - Updated dependencies [b3dad06]
47
+ - Updated dependencies [b3dad06]
48
+ - Updated dependencies [498d972]
49
+ - Updated dependencies [b3dad06]
50
+ - Updated dependencies
51
+ - Updated dependencies
52
+ - @nylorun/core@0.28.0-beta
53
+ - @nylorun/agents@0.28.0-beta
54
+ - @nylorun/admin@0.19.4-beta
55
+
3
56
  ## 0.19.0-beta
4
57
 
5
58
  ### Minor Changes
package/README.md CHANGED
@@ -53,10 +53,14 @@ nylorun doctor sandbox [--tenant <name>] [--json] # the sandbox backend the Te
53
53
 
54
54
  # apply, agent-manifests, agents, sessions, artifacts: the Runtime API (an application key, or NYLORUN_TOKEN)
55
55
  # every one takes --tenant <name>, and --as <subject> [--scope <scope>]... to act for a person
56
- nylorun init <name> [--description <text>] # write <name>/AGENT.md, a new agent folder
57
- nylorun check [<dir>...] # compile each agent folder offline: every problem by file, line and column
58
- nylorun apply [<dir>...] [--dry-run] [--if-match <n>] # plan, then save each folder (AGENT.md or agent.manifest.json), its files uploaded
56
+ nylorun init <path> [--description <text>] [--example] # write <path>/AGENT.md, a new agent folder named after the last segment
57
+ nylorun check [<dir>...] [--fix] [--json] # compile each agent folder offline: every problem by file, line and column; --fix makes the fixable ones' edits
58
+ nylorun apply [<dir>...] [--dry-run] [--if-match <n>] [--agent [<id>]] [--watch [--save]] # plan, then save each folder (AGENT.md or agent.manifest.json), its files uploaded
59
+ nylorun chat <agent> [--session <id>] [--message <text>] # send each line (or --message), print each reply
59
60
  nylorun migrate v8 <agent.json> [--runtime <environment-manifest.json>] [--name <name>] [--out <dir>] # the three files from a v7 manifest; reads no Runtime
61
+ nylorun migrate folder <dir> [--out <dir>] # the agent folder of a three-file folder; reads no Runtime
62
+ nylorun export --folder <name>[@<n>] [--out <dir>] # the agent folder of a saved manifest (JSON or TypeScript)
63
+ nylorun pull <name>[@<n>] [--out <dir>] # the folder a version was saved from, byte for byte
60
64
  nylorun agent-manifests list [--json] # name, latest version, runtime kind, harness, Agents
61
65
  nylorun agent-manifests get <name>[@<n>] | versions <name> | rm <name>
62
66
  nylorun agents list [--state <s>] [--manifest <name>] [--label <key=value>]... [--outdated] [--limit <n>] [--cursor <c>] [--json] # --outdated (or --behind): moving to another manifest version
@@ -132,8 +136,8 @@ apply`; `nylorun configure` is `nylorun tenant models set`. `nylorun dev`,
132
136
  are gone.
133
137
 
134
138
  The package's second command, `nylo`, was the Runtime client until nylorun took
135
- its commands. Until nylorun 0.19, which removes it, it names the `nylorun`
136
- command that replaced each of its own and exits 2:
139
+ its commands. It still ships, and a later release removes it: it names the
140
+ `nylorun` command that replaced each of its own and exits 2:
137
141
 
138
142
  | `nylo` | `nylorun` |
139
143
  | --- | --- |
@@ -478,25 +482,163 @@ from a terminal.
478
482
  An agent runs from a saved **agent manifest** (protocol 16): one named, versioned
479
483
  document with a harness section (instructions, tools, skills, MCP servers,
480
484
  plugins) and a runtime section (kind, image, network, setup, files, secret
481
- slots). Author it as an agent folder (track T6), one folder per agent:
485
+ slots). Author it as an agent folder (tracks T6 and T7), one folder per agent:
482
486
 
483
487
  ```
484
488
  agents/support/AGENT.md # frontmatter (name, description), then the instructions
485
489
  agents/support/mcp.json # MCP servers; "Authorization": "Bearer ${GITHUB_TOKEN}" names a slot
486
490
  agents/support/runtime.json # kind, network, secrets (optional)
487
491
  agents/support/skills/<skill>/SKILL.md, tools/<tool>.json, triggers/<id>.md, files/**
492
+ agents/support/agents/<id>/ # a subagent, offered to support as the tool <id>
493
+ agents/support/plugins/<name>/ # a vendored Agent Plugin: its skills and mcp.json servers
488
494
  ```
489
495
 
490
- `nylorun init support` writes the `AGENT.md`; `nylorun check agents/support`
496
+ A small one, with an HTTP tool and GitHub's MCP server. `AGENT.md`:
497
+
498
+ <!-- doc-test: folder support AGENT.md -->
499
+ ```markdown
500
+ ---
501
+ name: support
502
+ description: Answers questions about a customer's orders.
503
+ ---
504
+ Answer questions about the customer's orders. Look an order up with lookup_order before you
505
+ answer a question about it. When the customer reports a bug, find the matching GitHub issue.
506
+ ```
507
+
508
+ `tools/lookup_order.json`, an HTTP tool named after its file. `credential` names
509
+ the secret slot `ORDERS_TOKEN`, sent as a bearer token, never a value:
510
+
511
+ <!-- doc-test: folder support tools/lookup_order.json -->
512
+ ```json
513
+ {
514
+ "description": "Look up one order by its id: its status, items and total.",
515
+ "inputSchema": {
516
+ "type": "object",
517
+ "properties": { "orderId": { "type": "string", "description": "The order's id, such as A-1001." } },
518
+ "required": ["orderId"],
519
+ "additionalProperties": false
520
+ },
521
+ "http": { "url": "https://orders.example.com/lookup", "method": "POST", "credential": "ORDERS_TOKEN" }
522
+ }
523
+ ```
524
+
525
+ `mcp.json`, in Agent Plugins syntax; `${GITHUB_TOKEN}` names the slot the
526
+ server authenticates with:
527
+
528
+ <!-- doc-test: folder support mcp.json -->
529
+ ```json
530
+ {
531
+ "mcpServers": {
532
+ "github": {
533
+ "type": "streamable-http",
534
+ "url": "https://api.githubcopilot.com/mcp/",
535
+ "headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }
536
+ }
537
+ }
538
+ }
539
+ ```
540
+
541
+ With no `runtime.json`, the compiler derives both slots (`ORDERS_TOKEN` and
542
+ `GITHUB_TOKEN`, each bound to its URL) and says so; write their values with
543
+ `nylorun agents secrets put support <name>`.
544
+
545
+ `nylorun init agents/support` writes the `AGENT.md`; `nylorun check agents/support`
491
546
  compiles the folder offline with the Runtime's compiler and prints every problem
492
547
  as `file:line:column severity: message`, exiting 1 when it does not compile.
548
+ A problem one edit fixes ends `(fixable with --fix)`: an unknown key with one
549
+ did-you-mean (`memmory` for `memory`), CRLF line ends, and `secrets` in a
550
+ `SKILL.md`. `nylorun check --fix agents/support` makes those edits, and only
551
+ those: it renames the key where it is, keeping every other byte; makes the line
552
+ ends LF; and moves the secrets to `AGENT.md`'s `skills` block, as
553
+ `nylorun migrate folder` writes it. It prints each change, then checks again. It
554
+ leaves a file whose bytes changed since it was checked, and a `runtime.json`
555
+ that `extends` another; without `--fix`, `check` writes nothing.
493
556
  `nylorun apply agents/support` checks it the same way (sending nothing when it
494
557
  does not compile), plans it, prints the compiler's notes (such as a slot derived
495
558
  from `mcp.json`) and saves it, uploading its files by hash; the Runtime keeps the
496
559
  folder as the version's source. `--dry-run` also prints the compiled manifest. A
497
560
  change only to a file outside the agent, such as a README, is `unchanged`.
498
561
 
499
- Or as three files:
562
+ The loop from an empty folder to an answer:
563
+
564
+ ```
565
+ nylorun init agents/hello --example # AGENT.md, tools/, mcp.json and triggers/, each explained in its README.md
566
+ nylorun apply agents/hello --agent # save it, then make the Agent hello from it (or move it to the new version)
567
+ nylorun chat hello # send each line, print each reply; --message <text> sends one
568
+ ```
569
+
570
+ `init <path>` names the agent after the path's last segment. The first run in a
571
+ project (the nearest directory with `.git`) also writes `.gitattributes`
572
+ (`* text=auto eol=lf`), ignores `.nylorun/credentials.json` in `.gitignore`, and
573
+ maps the folder files to their JSON Schemas in `.vscode/settings.json`, merged
574
+ into the file that is there. `check --json` prints
575
+ `{ "folders": [{ path, ok, manifest?, diagnostics }] }` for CI, each fixable
576
+ diagnostic with its `fix`; with `--fix`, each folder also lists what was `fixed`
577
+ and what was `unfixed`, with why. A plan's change
578
+ to the instructions prints their text diff. `apply --watch` checks and plans
579
+ again on each change, and saves only with `--save` (for a development manifest:
580
+ each save is a new version that moves the Agents tracking it).
581
+
582
+ `.nyloignore` in a folder names, in gitignore syntax, what packing leaves out.
583
+ `runtime.json` may say `"extends": "../../platform/pod.runtime.json"`: `apply`
584
+ and `check` merge that file under it (the folder's keys win, objects merge,
585
+ arrays replace), send the merged `runtime.json`, and name the files it came from
586
+ in `.nylorun/origin.json`.
587
+
588
+ A folder with `flow.json` is a flow: its stages name agents of the folder's one
589
+ `agents/` by id (an `agents/<id>/` with a `flow.json` of its own is a sub-flow),
590
+ `"tool": "<name>"` names `tools/<name>.json` beside the `flow.json`, and its
591
+ `AGENT.md` has frontmatter only (and may set `inputSchema`). A two-stage chain:
592
+
593
+ <!-- doc-test: folder brief AGENT.md -->
594
+ ```markdown
595
+ ---
596
+ name: brief
597
+ description: Researches a topic, then writes a short brief on it.
598
+ ---
599
+ ```
600
+
601
+ <!-- doc-test: folder brief flow.json -->
602
+ ```json
603
+ { "chain": [{ "agent": "researcher" }, { "agent": "writer" }] }
604
+ ```
605
+
606
+ <!-- doc-test: folder brief agents/researcher/AGENT.md -->
607
+ ```markdown
608
+ ---
609
+ name: researcher
610
+ description: Lists what matters about the topic.
611
+ ---
612
+ List the five facts about the topic a newcomer most needs, each with one sentence of context.
613
+ ```
614
+
615
+ <!-- doc-test: folder brief agents/writer/AGENT.md -->
616
+ ```markdown
617
+ ---
618
+ name: writer
619
+ description: Writes the brief.
620
+ ---
621
+ Write a brief of at most 200 words from the facts you are given, for a reader new to the topic.
622
+ ```
623
+
624
+ [`examples/agents/repo-brief-folder/`](../../examples/agents/repo-brief-folder/)
625
+ is a whole flow as a folder: a switch, a map, a parallel stage, a loop and an HTTP
626
+ tool stage. Without `flow.json`, each `agents/<id>/` is a subagent: the agent
627
+ calls it as the tool `<id>` with `{ task }`, one level deep. `plugins/<name>/`
628
+ folds a plugin's skills and `mcp.json` servers in as `.plugin()` does, and notes
629
+ what Nylorun does not run (hooks, commands).
630
+
631
+ `nylorun pull support[@3] [--out <dir>]` writes back the folder a version was
632
+ saved from, byte for byte. A version saved as JSON or from TypeScript has none:
633
+ `nylorun export --folder support[@3] [--out <dir>]` writes its folder from the
634
+ manifest instead (instructions as Markdown, tools, `mcp.json`, triggers,
635
+ `runtime.json`, subagents as `agents/<id>/`, and a flow as `flow.json` with its
636
+ agents), says whether it compiles back to the same manifest, and notes what it
637
+ writes differently (a skill's files, which the manifest names by hash only, are
638
+ left to copy in). Neither writes over a file with other bytes.
639
+
640
+ Or as three files (deprecated: `apply` warns, and `nylorun migrate folder
641
+ agents/triage --out <dir>` writes the agent folder, with its skills, offline):
500
642
 
501
643
  ```
502
644
  agents/triage/agent.manifest.json # { "manifestSchemaVersion": 8, "name": "triage",
@@ -519,8 +661,9 @@ against, uploading the files the Runtime does not hold (`PUT /v1/files/sha256:
519
661
  A manifest whose sections do not fit, or whose runtime misses what its harness
520
662
  `requires`, is an error: nothing is saved and the command exits 1. `--dry-run`
521
663
  prints the plans only; `--if-match <n>` saves only over version `n`.
522
- `nylorun apply agents/` applies every subfolder with an `agent.manifest.json`;
523
- every folder composes before anything is sent.
664
+ `nylorun apply agents/` applies every subfolder with an `AGENT.md` (or an
665
+ `agent.manifest.json`); every folder compiles, or composes, before anything is
666
+ sent.
524
667
 
525
668
  `nylorun agent-manifests list` shows each manifest's latest version, runtime
526
669
  kind, harness and the Agents made from it; `get <name>[@<n>]` prints a version,
@@ -536,7 +679,8 @@ manifest's fields become the runtime file, its `harness` the harness file's `id`
536
679
  and v7's `requires` stays in the harness file for `apply` to check. With no
537
680
  environment manifest the kind is `pod` when the agent requires one, `virtual`
538
681
  when it has skills or requires a sandbox, else `none`. It overwrites no file and
539
- prints the gaps to fix before `apply`.
682
+ prints the gaps to fix before `apply`. The three files are deprecated: `nylorun
683
+ migrate folder agents/triage --out <dir>` then writes them as an agent folder.
540
684
 
541
685
  ### `local reset` or `tenant reset`
542
686
 
package/dist/cli.js CHANGED
@@ -13,15 +13,29 @@ ${stackUsage}
13
13
  the sandbox backend the Tenant's Host offers
14
14
 
15
15
  Agent manifests:
16
- init <name> [--description <text>] write <name>/AGENT.md, a new agent folder
17
- check [<dir>...] compile each agent folder offline and print every problem
18
- by file, line and column (reads no Runtime)
19
- apply [<dir>...] [--dry-run] [--if-match <n>]
16
+ init <path> [--description <text>] [--example]
17
+ write <path>/AGENT.md, a new agent folder named after the
18
+ path's last segment; --example adds a tool, mcp.json and a
19
+ trigger
20
+ check [<dir>...] [--fix] [--json] compile each agent folder offline and print every problem
21
+ by file, line and column (reads no Runtime); --fix makes
22
+ the edits the fixable ones name
23
+ apply [<dir>...] [--dry-run] [--if-match <n>] [--agent [<id>]] [--watch [--save]]
20
24
  save the agent manifest each folder describes (its AGENT.md,
21
- or its agent.manifest.json), with its files (Runtime API)
25
+ or its agent.manifest.json), with its files (Runtime API);
26
+ --agent then makes or moves the Agent; --watch plans again
27
+ on each change
28
+ chat <agent> [--session <id>] [--message <text>]
29
+ talk to an Agent: send each line, print each reply
22
30
  migrate v8 <agent.json> [--runtime <environment-manifest.json>] [--name <name>] [--out <dir>]
23
31
  write the three manifest files from an agent manifest v7
24
32
  and an environment manifest v1 (reads no Runtime)
33
+ migrate folder <dir> [--out <dir>] write the agent folder of a three-file folder
34
+ (agent.manifest.json; reads no Runtime)
35
+ export --folder <name>[@<version>] [--out <dir>]
36
+ write the agent folder of a saved manifest (Runtime API)
37
+ pull <name>[@<version>] [--out <dir>]
38
+ write the folder a version was saved from (Runtime API)
25
39
 
26
40
  Groups, each with its own --help:
27
41
  agent-manifests list | get | versions | rm
@@ -126,6 +140,10 @@ async function main() {
126
140
  const [command, ...args] = process.argv.slice(2);
127
141
  if (!command || command === "--help" || command === "-h")
128
142
  return void console.log(usage);
143
+ if (command === "--version" || command === "-v" || command === "version") {
144
+ const { cliVersion } = await import("./stack/versions.js");
145
+ return void console.log(cliVersion());
146
+ }
129
147
  refuseNativeWindows();
130
148
  if (command === "sandbox") {
131
149
  const sub = args[0];
@@ -170,6 +188,9 @@ async function main() {
170
188
  command === "check" ||
171
189
  command === "init" ||
172
190
  command === "migrate" ||
191
+ command === "export" ||
192
+ command === "pull" ||
193
+ command === "chat" ||
173
194
  command === "agent-manifests" ||
174
195
  command === "agents" ||
175
196
  command === "sessions" ||
@@ -179,6 +200,9 @@ async function main() {
179
200
  check: async () => (await import("./client/folder.js")).checkCommand,
180
201
  init: async () => (await import("./client/folder.js")).initCommand,
181
202
  migrate: async () => (await import("./client/migrate.js")).migrateCommand,
203
+ export: async () => (await import("./client/convert.js")).exportCommand,
204
+ pull: async () => (await import("./client/convert.js")).pullCommand,
205
+ chat: async () => (await import("./client/chat.js")).chatCommand,
182
206
  "agent-manifests": async () => (await import("./client/agent-manifests.js")).agentManifestsCommand,
183
207
  agents: async () => (await import("./client/agents.js")).agentsCommand,
184
208
  sessions: async () => (await import("./client/sessions.js")).sessionsCommand,
@@ -1,4 +1,22 @@
1
+ /**
2
+ * `nylorun agents`: the Tenant's Agents (protocol 16: each is one version of an agent manifest
3
+ * made live, with one environment and one vault, and the sessions that run on it), through the
4
+ * Runtime API of the installation `target.ts` picks: create or find one by id from a saved
5
+ * manifest, move it to another version (`pin`, `track`, `put`; track T3) and apply a pending one
6
+ * (`restart`), fork it, stop, reset or delete it, keep and restore versions of its disk, and
7
+ * write its secrets. The manifests themselves are `agent-manifests.ts`
8
+ * and `apply.ts`. A secret's value comes from a file or standard input, never from the command
9
+ * line, and no command reads one back. None of them starts a local Tenant.
10
+ */
11
+ import type { AgentView } from "@nylorun/agents";
1
12
  import { type StackDeps } from "../stack/commands.js";
2
13
  export declare const agentsUsage: string;
14
+ /**
15
+ * The manifest an Agent runs, as the list prints it: `name@version`, the version it moves to
16
+ * (track T3), and whether it tracks.
17
+ */
18
+ export declare function manifestOf(agent: AgentView): string;
19
+ /** What a move left pending, for a person: the version, and what it waits for. */
20
+ export declare function pendingOf(agent: AgentView): string;
3
21
  /** `nylorun agents <command> ...` */
4
22
  export declare function agentsCommand(deps: StackDeps, args: readonly string[]): Promise<number>;
@@ -72,13 +72,13 @@ const SAVE_REMOVED = "nylorun agents save was removed in protocol 16: agents run
72
72
  * The manifest an Agent runs, as the list prints it: `name@version`, the version it moves to
73
73
  * (track T3), and whether it tracks.
74
74
  */
75
- function manifestOf(agent) {
75
+ export function manifestOf(agent) {
76
76
  const name = parseAgentManifestRef(agent.manifest)?.name ?? agent.manifest;
77
77
  const target = agent.targetVersion ? ` → ${agent.targetVersion}` : "";
78
78
  return `${name}@${agent.resolvedVersion}${target} ${agent.tracking === "tracking" ? "tracks" : "pinned"}`;
79
79
  }
80
80
  /** What a move left pending, for a person: the version, and what it waits for. */
81
- function pendingOf(agent) {
81
+ export function pendingOf(agent) {
82
82
  if (!agent.targetVersion)
83
83
  return "";
84
84
  return agent.waitingFor === "secrets"
@@ -0,0 +1,14 @@
1
+ import { type AgentView, type AgentsClient } from "@nylorun/agents";
2
+ import type { StackDeps } from "../stack/commands.js";
3
+ /**
4
+ * `--agent [<id>]`, or `--agent=<id>`, taken out of `args`. The word after `--agent` is its id
5
+ * unless it is a flag or names a directory under `cwd` (a folder to apply).
6
+ */
7
+ export declare function takeAgentFlag(args: readonly string[], cwd: string): {
8
+ args: string[];
9
+ agent?: {
10
+ id?: string;
11
+ };
12
+ };
13
+ /** Makes Agent `id` from manifest `name`, or moves it to the manifest's latest version, and says which. */
14
+ export declare function putAgent(deps: StackDeps, client: AgentsClient, label: string, id: string, name: string): Promise<AgentView>;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * `nylorun apply --agent [<id>]` (track T7): after a manifest is saved, or found unchanged, make the
3
+ * Agent that runs it, or move it to the latest version, as `nylorun agents put <id> --manifest
4
+ * <name>` does. The id defaults to the manifest's name. What happened is printed, with what the
5
+ * Agent needs a person for (an unset required secret).
6
+ */
7
+ import { statSync } from "node:fs";
8
+ import { resolve } from "node:path";
9
+ import { RuntimeError } from "@nylorun/agents";
10
+ import { manifestOf, pendingOf } from "./agents.js";
11
+ import { runtimeCall, usageError } from "./runtime.js";
12
+ /**
13
+ * `--agent [<id>]`, or `--agent=<id>`, taken out of `args`. The word after `--agent` is its id
14
+ * unless it is a flag or names a directory under `cwd` (a folder to apply).
15
+ */
16
+ export function takeAgentFlag(args, cwd) {
17
+ const rest = [];
18
+ let agent;
19
+ for (let index = 0; index < args.length; index += 1) {
20
+ const arg = args[index];
21
+ if (arg.startsWith("--agent=")) {
22
+ const id = arg.slice("--agent=".length);
23
+ if (id === "")
24
+ throw usageError("--agent= needs an Agent id.");
25
+ agent = { id };
26
+ continue;
27
+ }
28
+ if (arg !== "--agent") {
29
+ rest.push(arg);
30
+ continue;
31
+ }
32
+ const next = args[index + 1];
33
+ if (next !== undefined && !next.startsWith("-") && !isDirectory(resolve(cwd, next))) {
34
+ agent = { id: next };
35
+ index += 1;
36
+ }
37
+ else
38
+ agent = {};
39
+ }
40
+ return { args: rest, ...(agent ? { agent } : {}) };
41
+ }
42
+ function isDirectory(path) {
43
+ try {
44
+ return statSync(path).isDirectory();
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ /** Makes Agent `id` from manifest `name`, or moves it to the manifest's latest version, and says which. */
51
+ export async function putAgent(deps, client, label, id, name) {
52
+ let before;
53
+ try {
54
+ before = await client.agents.get(id);
55
+ }
56
+ catch (error) {
57
+ if (!(error instanceof RuntimeError && error.status === 404))
58
+ await runtimeCall(() => Promise.reject(error));
59
+ }
60
+ const agent = await runtimeCall(() => client.agents.put(id, { manifest: name }));
61
+ const what = !before
62
+ ? `Made Agent ${agent.id}`
63
+ : before.resolvedVersion !== agent.resolvedVersion || before.manifest !== agent.manifest || before.targetVersion !== agent.targetVersion
64
+ ? `Moved Agent ${agent.id} from ${manifestOf(before)}`
65
+ : `Agent ${agent.id} is unchanged`;
66
+ deps.err(`${what}: it runs ${manifestOf(agent)} on ${label}${pendingOf(agent)}.`);
67
+ for (const item of agent.attention ?? [])
68
+ if (!item.sessionId)
69
+ deps.err(` attention: ${item.reason}`);
70
+ return agent;
71
+ }
@@ -1,7 +1,14 @@
1
1
  import { type AgentManifestPlan } from "@nylorun/agents";
2
2
  import type { StackDeps } from "../stack/commands.js";
3
3
  export declare const applyUsage: string;
4
+ /** How `--watch` runs an apply (`watch.ts`). */
5
+ export interface ApplyOptions {
6
+ /** Plan, and save nothing. */
7
+ planOnly?: boolean;
8
+ /** `nylorun check` printed each folder's diagnostics already. */
9
+ checked?: boolean;
10
+ }
4
11
  /** A plan as lines: the move, then each change, warning and error. */
5
12
  export declare function planLines(plan: AgentManifestPlan): string[];
6
- /** `nylorun apply [dir…] [--dry-run] [--if-match <n>]` */
7
- export declare function applyCommand(deps: StackDeps, args: readonly string[]): Promise<number>;
13
+ /** `nylorun apply [dir…] [--dry-run] [--if-match <n>] [--agent [<id>]] [--watch [--save]]` */
14
+ export declare function applyCommand(deps: StackDeps, given: readonly string[], options?: ApplyOptions): Promise<number>;