@nylorun/cli 0.3.0-beta → 0.4.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 +50 -1
- package/README.md +55 -78
- package/dist/{runtime/baseline.js → baseline.js} +0 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +34 -115
- package/dist/doctor.d.ts +1 -12
- package/dist/doctor.js +6 -96
- package/dist/home.d.ts +6 -0
- package/dist/home.js +15 -0
- package/dist/model/host-model.js +1 -1
- package/dist/project/create-tenant.d.ts +3 -1
- package/dist/project/create-tenant.js +3 -2
- package/dist/project/credentials.js +1 -1
- package/dist/project/env.d.ts +3 -0
- package/dist/project/env.js +21 -0
- package/dist/project/link.js +1 -1
- package/dist/project/root.js +2 -1
- package/dist/project/seed.d.ts +6 -0
- package/dist/project/seed.js +9 -7
- package/dist/tenant/commands.js +73 -14
- package/package.json +6 -9
- package/dist/dev-entry.d.ts +0 -5
- package/dist/dev-entry.js +0 -7
- package/dist/dev.d.ts +0 -47
- package/dist/dev.js +0 -278
- package/dist/launcher.d.ts +0 -5
- package/dist/launcher.js +0 -7
- package/dist/project/attach.d.ts +0 -32
- package/dist/project/attach.js +0 -241
- package/dist/runtime/commands.d.ts +0 -16
- package/dist/runtime/commands.js +0 -292
- package/dist/runtime/ephemeral.d.ts +0 -37
- package/dist/runtime/ephemeral.js +0 -84
- package/dist/runtime/exit-codes.d.ts +0 -9
- package/dist/runtime/exit-codes.js +0 -43
- package/dist/runtime/index.d.ts +0 -8
- package/dist/runtime/index.js +0 -6
- package/dist/runtime/launcher.d.ts +0 -81
- package/dist/runtime/launcher.js +0 -243
- package/dist/runtime/progress.d.ts +0 -10
- package/dist/runtime/progress.js +0 -8
- package/dist/runtime/version.d.ts +0 -6
- package/dist/runtime/version.js +0 -27
- /package/dist/{runtime/baseline.d.ts → baseline.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# @nylorun/cli
|
|
2
2
|
|
|
3
|
+
## 0.4.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- bf1c2da: **The local Runtime and Studio run as a Docker Compose stack that the CLI manages; Studio ships only as its image (breaking beta).**
|
|
8
|
+
|
|
9
|
+
- `nylorun start` writes `<Host root>/stack/compose.yaml` and `.env` (mode 0600) and starts Postgres, Restate, s2-lite, the Runtime and Studio on loopback ports, with the Runtime and Studio images this CLI pins (`nylorun.runtime`, `nylorun.studio`; `NYLORUN_RUNTIME_IMAGE` and `NYLORUN_STUDIO_IMAGE` override them). `nylorun stop` keeps the volumes; `nylorun status [--json] [--env]` reports services and health; `nylorun reset [--yes]` deletes the volumes and every Tenant.
|
|
10
|
+
- `nylorun dev` starts the stack if it is not running, creates the Project's Tenant on first run, opens Studio on that Tenant through a single-use login URL (`next=/tenants/<id>`), and runs the application with `NYLORUN_RUNTIME_URL=http://localhost:<port>`. `--no-open` prints the URL only; `--no-studio` skips Studio. `--local-ui` is removed (exit 2).
|
|
11
|
+
- `nylorun logs` and `nylorun studio` are the stack commands (`nylorun stack <command>` still works). `nylorun studio` lands on the linked Project's Tenant.
|
|
12
|
+
- `nylorun runtime up|down|restart|run|status|logs` and the `up`/`down` aliases are removed; they exit 2 and name `nylorun start|stop|status|logs`. `nylorun runtime status --env` is now `nylorun status --env`.
|
|
13
|
+
- `nylorun doctor` checks Node 24+, Docker, Compose v2 and the stack's health; `doctor runtime` is an alias of it.
|
|
14
|
+
- `@nylorun/studio` is private and ships only as `ghcr.io/nylorun/studio`: `startStudio`, the hosted (`local.nylorun.studio`) and local UI modes, pairing, the `nylorun-studio` bin and the UI bundle download are removed.
|
|
15
|
+
- `npm create @nylorun/agent` no longer adds `@nylorun/studio` or a `studio` script, checks for Docker with Compose v2 instead of a global `@nylorun/runtime`, and accepts `--no-studio` only as a deprecated no-op.
|
|
16
|
+
|
|
17
|
+
- bf1c2da: **`nylorun dev --ephemeral` runs on the Docker stack, with a Tenant-level fixture model (breaking beta).**
|
|
18
|
+
|
|
19
|
+
- `nylorun dev --ephemeral` creates a temporary Tenant through `@nylorun/admin` (no Project link written), seeds it from `.env` with the fixture model, opens Studio on it and runs the watcher; the Tenant is deleted with its active work cancelled when the watcher ends, Ctrl-C included. It needs a Runtime that advertises `tenant-fixture-model`.
|
|
20
|
+
- `PUT /v1/tenant/config/seed` accepts `fixtureModel: true`, stored as Tenant setting `model.fixture`: that Tenant's model calls use the Runtime's fixture model while other Tenants on the Host keep theirs. `HOST_PROTOCOL` advertises the new optional feature `tenant-fixture-model` (`OPTIONAL_HOST_FEATURES` in `@nylorun/core/compatibility`); clients do not require it.
|
|
21
|
+
- `startEphemeralRuntime()` keeps its signature but its Tenants live in memory instead of SQLite under the Host root; nothing survives `close()`.
|
|
22
|
+
- Closing a Tenant waits for running advances at most the advance grace period (30 s by default) and then abandons them; their lease lapses and the next advance takes over.
|
|
23
|
+
- A Worker stop, Tenant close or ended Restate attempt no longer fails or cancels the turn it interrupts: outcomes already returned are recorded, nothing is settled, and the next advance resumes the turn from its checkpoint. Only a user cancel settles `cancelled`; an advance deadline fails the turn with the deadline's message.
|
|
24
|
+
|
|
25
|
+
- ba1b239: **`nylorun` sets up the local stack; `@nylorun/cli` becomes the Runtime client `nylo` (breaking beta).**
|
|
26
|
+
|
|
27
|
+
- New unscoped package **`nylorun`**: `npx nylorun up` sets up the Docker stack on the first run and starts it after that, from any directory; `npx nylorun down` stops it (volumes are kept). `up` and `down` are aliases of `start` and `stop`. It also owns `status`, `logs`, `studio`, `reset` and `doctor`, pins the Runtime and Studio images (`package.json` `nylorun.runtime` / `nylorun.studio`), depends on `@nylorun/core` only, and never creates Tenants.
|
|
28
|
+
- **`@nylorun/cli`** is the Runtime client with the command **`nylo`**: `nylo tenant create [name]` (creates the Tenant; in a project, writes the Project link and seeds the model provider and sandbox from `.env`), `nylo tenant current|list|use|status|reset|delete`, `nylo configure`, `nylo env` (was `nylorun status --env`) and `nylo doctor sandbox`. It no longer provides the `nylorun` command or the stack commands.
|
|
29
|
+
- **Removed:** `nylorun dev` and `nylorun dev --ephemeral`. Link once with `nylo tenant create`, then run the project's own `npm run dev`. Moved commands exit 2 and name their replacement.
|
|
30
|
+
- **Starter:** the generated project depends on `@nylorun/agents` only (no Nylorun devDependency); `dev` is `tsx watch --env-file-if-exists=.env src/main.ts`. `npm create @nylorun/agent` installs the project and prints the next steps (`npx nylorun up`, `npx @nylorun/cli tenant create`, `npm run dev`) instead of starting development; `--no-open` is accepted and ignored.
|
|
31
|
+
- `connectAgents` names those steps when it finds no Runtime connection. Runtime repair hints, model errors and core's sandbox message name `nylo` and `nylorun up`.
|
|
32
|
+
|
|
33
|
+
- bf1c2da: **The microsandbox backend is removed; the Runtime runs sandbox tools on the virtual backend only.** The optional `microsandbox` dependency is gone. `sandbox.backend` and `NYLORUN_SANDBOX` accept `auto` or `virtual`, and `auto` selects `virtual`. A Tenant that stored `microsandbox` reads it as `auto`. `nylorun doctor sandbox` and the `nylorun dev` banner report only the virtual shell.
|
|
34
|
+
- bf1c2da: **Tenants can register a Studio principal.** `CreateTenantRequest` gains optional `studioCredentialHash` behind the new protocol feature `studio-principal`; the Runtime stores it as application principal `studio`, and idempotent create compares it too. `@nylorun/admin` exports `deriveStudioToken(adminKey, tenantId)` (HMAC-SHA256 over `nylorun/studio/v1`, NUL, Tenant id) and `createTenant` sends the hash of that key, so Studio can reach any Tenant's API with a key derived from the admin key. Clients require the new feature, so upgrade the Runtime with them.
|
|
35
|
+
- 1d84b3e: **Native Windows is no longer supported; Windows developers use WSL2.** Nylorun runs on macOS and Linux. On native Windows, `nylorun` and `npm create @nylorun/agent` stop with WSL2 guidance. Install Node 24 and Docker (Docker Desktop's WSL integration) inside your WSL distribution and keep projects in its Linux filesystem. The Windows-only process handling (`taskkill`, `.cmd` shims, `npm.cmd`) is removed. `nylorun doctor` reports WSL as `Linux (WSL: <distribution>)`.
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- 1d84b3e: Opening the browser no longer crashes the CLI when no opener is installed (no `xdg-open` on a minimal Linux or WSL): it reports that and leaves the printed Studio URL to open by hand. Inside WSL, the CLI opens the Windows browser with `wslview`.
|
|
40
|
+
- Pin agents to the tested release.
|
|
41
|
+
- Pin admin to the tested release.
|
|
42
|
+
- Updated dependencies [ba1b239]
|
|
43
|
+
- Updated dependencies [bf1c2da]
|
|
44
|
+
- Updated dependencies [bf1c2da]
|
|
45
|
+
- Updated dependencies
|
|
46
|
+
- Updated dependencies
|
|
47
|
+
- @nylorun/agents@0.7.0-beta
|
|
48
|
+
- @nylorun/admin@0.3.0-beta
|
|
49
|
+
|
|
3
50
|
## 0.3.0-beta
|
|
4
51
|
|
|
5
52
|
### Minor Changes
|
|
@@ -9,7 +56,9 @@
|
|
|
9
56
|
- Dependencies: `@nylorun/agents` and `@nylorun/admin` only (no `@nylorun/runtime`, no `@nylorun/studio`).
|
|
10
57
|
- `nylorun runtime …` finds `nylorun-runtime` on PATH and checks its launcher and Host protocol; a missing or incompatible Runtime exits 1 with the install command for the recommended version (`package.json` `nylorun.runtime`). Nothing is downloaded. `nylorun doctor runtime` checks the prerequisites.
|
|
11
58
|
- `nylorun dev` runs the application entry under `tsx watch`; creates Tenants through `@nylorun/admin`.
|
|
12
|
-
- **Removed:** `nylorun serve
|
|
59
|
+
- **Removed:** `nylorun serve` and the in-process Project runner. `nylorun studio`
|
|
60
|
+
remains the Project-aware Studio command, and `nylorun dev --no-studio`
|
|
61
|
+
remains the headless development path.
|
|
13
62
|
- Install as a **devDependency**; production `start` is `node dist/src/main.js`.
|
|
14
63
|
|
|
15
64
|
- c49efed: **Breaking (pre-1.0 minor):** Replace a single SQLite Runtime per Project or home directory with a **Runtime Host** that serves isolated **Tenants**, selected by `Nylorun-Tenant` and negotiated with `Nylorun-Protocol` (protocol `2`, feature `runtime-tenants`). Vocabulary: Host root + Tenant + Project link.
|
package/README.md
CHANGED
|
@@ -1,108 +1,85 @@
|
|
|
1
1
|
# @nylorun/cli
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The Runtime client, command `nylo`: it acts on a Runtime's Tenants, the local
|
|
4
|
+
stack's or any Runtime reachable by URL and key. Setting up and running the
|
|
5
|
+
local stack is [`nylorun`](../nylorun/README.md)'s job; the two packages are
|
|
6
|
+
independent and never call each other. Depends on `@nylorun/agents` and
|
|
7
|
+
`@nylorun/admin` only among Nylorun packages. Vocabulary:
|
|
6
8
|
[runtime/src/CONTEXT.md](../runtime/src/CONTEXT.md).
|
|
7
9
|
|
|
8
|
-
Prerequisites, installed by the developer (the CLI never downloads them):
|
|
9
|
-
|
|
10
10
|
```sh
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
nylorun doctor runtime # checks both
|
|
11
|
+
npx nylorun up # the local stack (nylorun)
|
|
12
|
+
npx @nylorun/cli tenant create # this project's Tenant, linked in .nylorun/
|
|
14
13
|
```
|
|
15
14
|
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
16
17
|
```sh
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
nylorun runtime restart # restart onto the installed Runtime
|
|
23
|
-
nylorun runtime run # attached foreground Host
|
|
24
|
-
nylorun dev [entry] # up → link/create Tenant → tsx watch entry
|
|
25
|
-
nylorun dev --ephemeral # temporary Host root + one Tenant
|
|
26
|
-
nylorun dev --local-ui # also start Studio with a local dashboard
|
|
27
|
-
nylorun studio [--local-ui] # start Studio (launch URL + proxy token)
|
|
28
|
-
nylorun configure # replace model credential on the linked Tenant
|
|
29
|
-
nylorun tenant list|delete|status|reset
|
|
30
|
-
nylorun doctor runtime # prerequisites: Node 24+, installed Runtime
|
|
31
|
-
nylorun doctor sandbox # sandbox backend via Tenant API
|
|
18
|
+
nylo tenant create [name] # create a Tenant; in a Project, link it and seed it from .env
|
|
19
|
+
nylo tenant current|list [--json]|use <name-or-id>|status [--json]|reset|delete
|
|
20
|
+
nylo configure # set or replace the model provider on the linked Tenant
|
|
21
|
+
nylo env # export lines for the linked Project
|
|
22
|
+
nylo doctor sandbox [--json] # sandbox backend via the Tenant API
|
|
32
23
|
```
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
##
|
|
60
|
-
|
|
61
|
-
The **Host root** is `NYLORUN_HOME` or `~/.nylorun` (resolved absolute once).
|
|
62
|
-
It holds `host.json`, admin credentials and every Tenant; the Runtime itself
|
|
63
|
-
is installed by npm. Isolation is per **Tenant**, not per Project directory.
|
|
25
|
+
Local stack commands (`up`, `down`, `start`, `stop`, `status`, `logs`,
|
|
26
|
+
`studio`, `reset`) exit 2 naming `npx nylorun <command>`. `nylorun dev` was
|
|
27
|
+
removed: link once with `nylo tenant create`, then run the project's own
|
|
28
|
+
`npm run dev` (`tsx watch src/main.ts`).
|
|
29
|
+
|
|
30
|
+
## `nylo tenant create`
|
|
31
|
+
|
|
32
|
+
The Admin API connection resolves from `NYLORUN_ADMIN_URL` and
|
|
33
|
+
`NYLORUN_ADMIN_KEY`, else from the local Host root (`NYLORUN_HOME` or
|
|
34
|
+
`~/.nylorun`: `host.json` and the admin key that `nylorun up` wrote). With no
|
|
35
|
+
Runtime answering, it exits 6 and names `npx nylorun up`.
|
|
36
|
+
|
|
37
|
+
Inside a Project (the nearest `.nylorun/` or `package.json`):
|
|
38
|
+
|
|
39
|
+
1. Creates the Tenant, named after `package.json` unless a name is given.
|
|
40
|
+
2. Writes the format-1 link and credentials (see below). A Project that is
|
|
41
|
+
already linked is refused: use `nylo tenant use` or `nylo tenant delete`.
|
|
42
|
+
3. Seeds the Tenant from `.env`: `NYLORUN_SANDBOX`, and the model provider from
|
|
43
|
+
`MODEL_PROVIDER`, `MODEL`, `MODEL_PROVIDER_API_KEY` (or a credential in
|
|
44
|
+
`.nylorun/auth.json`) into the Tenant vault. Without them it says to set the
|
|
45
|
+
provider in Studio or with `nylo configure`.
|
|
46
|
+
|
|
47
|
+
Outside a Project it creates the Tenant and prints the three `NYLORUN_*`
|
|
48
|
+
exports once; the Host keeps only a hash of the application key.
|
|
49
|
+
|
|
50
|
+
## Project link
|
|
64
51
|
|
|
65
52
|
A **Project** stores only:
|
|
66
53
|
|
|
67
|
-
- `.nylorun/link.json
|
|
68
|
-
- `.nylorun/credentials.json
|
|
54
|
+
- `.nylorun/link.json`: `{ format, hostUrl, hostId, tenantId }`
|
|
55
|
+
- `.nylorun/credentials.json`: application key and principal id (0600), no
|
|
69
56
|
executor tokens
|
|
70
57
|
- `.nylorun/.gitignore` containing `*`
|
|
71
58
|
|
|
59
|
+
`connectAgents` in `@nylorun/agents` reads the link (or the three variables),
|
|
60
|
+
so the project's `npm run dev` and `npm start` need no Nylorun tool.
|
|
61
|
+
|
|
72
62
|
```sh
|
|
73
|
-
eval "$(npx nylorun
|
|
63
|
+
eval "$(npx @nylorun/cli env)"
|
|
74
64
|
# → NYLORUN_RUNTIME_URL, NYLORUN_SERVER_KEY, NYLORUN_TENANT
|
|
75
65
|
```
|
|
76
66
|
|
|
77
|
-
Port defaults to `8787` on loopback. On first Host setup, if that port is
|
|
78
|
-
taken, the launcher picks a free loopback port and persists it. Explicit
|
|
79
|
-
`--port` is strict.
|
|
80
|
-
|
|
81
67
|
## Exit codes
|
|
82
68
|
|
|
83
69
|
| Code | Meaning |
|
|
84
70
|
| --- | --- |
|
|
85
|
-
| 0 | Success
|
|
86
|
-
| 1 | Generic failure
|
|
87
|
-
| 2 | Usage error |
|
|
88
|
-
|
|
|
89
|
-
| 4 | Port held by another process |
|
|
90
|
-
| 5 | Protocol / feature incompatible with this CLI |
|
|
91
|
-
| 7 | The Host did not become ready |
|
|
71
|
+
| 0 | Success |
|
|
72
|
+
| 1 | Generic failure |
|
|
73
|
+
| 2 | Usage error, or a moved or removed command |
|
|
74
|
+
| 6 | No Runtime at the linked or local URL |
|
|
92
75
|
| 130 / 143 | SIGINT / SIGTERM |
|
|
93
76
|
|
|
94
|
-
Install the CLI as a **devDependency**. Generated applications keep
|
|
95
|
-
`@nylorun/agents` alone in production dependencies.
|
|
96
|
-
|
|
97
77
|
## Troubleshooting
|
|
98
78
|
|
|
99
79
|
| Symptom | What to do |
|
|
100
80
|
| --- | --- |
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
See [package architecture](../docs/design/package-architecture.md) and
|
|
108
|
-
[MIGRATION.md](../MIGRATION.md#runtime-clients-and-admin-api-breaking-beta).
|
|
81
|
+
| No Runtime answers | `npx nylorun up`, then `npx nylorun status` |
|
|
82
|
+
| Quarantined Tenant | `nylo tenant status` shows the reason and `repair` |
|
|
83
|
+
| `426` from the Runtime | Upgrade the CLI, or pin a matching older set |
|
|
84
|
+
|
|
85
|
+
See [MIGRATION.md](../MIGRATION.md).
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./
|
|
2
|
+
import "./baseline.js";
|
package/dist/cli.js
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import { join } from "node:path";
|
|
2
|
+
import "./baseline.js";
|
|
5
3
|
import { ConfigurationCancelled, configureProvider, fetchModelCatalog, } from "./model/configure.js";
|
|
6
4
|
import { putHostModel } from "./model/host-model.js";
|
|
7
|
-
import { develop, developmentPreflight, startStudio } from "./dev.js";
|
|
8
5
|
import { CliError } from "./errors.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { printLinkedEnvExports } from "./project/attach.js";
|
|
6
|
+
import { findProjectRoot } from "./project/root.js";
|
|
7
|
+
import { printLinkedEnvExports } from "./project/env.js";
|
|
12
8
|
import { readLink as readProjectLink } from "./project/link.js";
|
|
13
9
|
import { readCredentials as readProjectCredentials } from "./project/credentials.js";
|
|
14
10
|
import { tenantCommand } from "./tenant/commands.js";
|
|
15
|
-
|
|
16
|
-
const usage = `nylorun <runtime|up|down|logs|dev|studio|configure|doctor|tenant>
|
|
11
|
+
const usage = `nylo <tenant|configure|env|doctor>
|
|
17
12
|
|
|
18
|
-
|
|
13
|
+
Runtime client (the local stack's Runtime, or any Runtime by URL and key):
|
|
14
|
+
tenant create [name] create a Tenant; in a Project, link it and seed it from .env
|
|
15
|
+
tenant current|list [--json]|use <name-or-id>|status [--json]|reset|delete
|
|
16
|
+
configure set the linked Tenant's model provider
|
|
17
|
+
env print the linked Project's NYLORUN_* variables as exports
|
|
18
|
+
doctor sandbox [--json] show which sandbox backend this Tenant's Host offers
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
tenant current|list [--json]|use <name-or-id>|status [--json]|reset|delete`;
|
|
20
|
+
The local stack is managed by the nylorun package: npx nylorun up|down|status|logs|studio`;
|
|
21
|
+
/** Local stack commands, which moved to the nylorun package. */
|
|
22
|
+
const STACK_COMMANDS = new Set([
|
|
23
|
+
"up", "down", "start", "stop", "status", "logs", "studio", "reset", "stack", "runtime", "restart", "run",
|
|
24
|
+
]);
|
|
26
25
|
function parseFlags(args, allowed = {}) {
|
|
27
26
|
const booleans = new Set();
|
|
28
27
|
const values = new Map();
|
|
@@ -58,14 +57,6 @@ function parseFlags(args, allowed = {}) {
|
|
|
58
57
|
return { rest, booleans, values };
|
|
59
58
|
}
|
|
60
59
|
const usageError = (message) => new CliError(message, 2);
|
|
61
|
-
function parsePort(value) {
|
|
62
|
-
if (value === undefined || !/^\d+$/u.test(value))
|
|
63
|
-
throw usageError(`Invalid --port: ${value ?? "(missing)"}`);
|
|
64
|
-
const port = Number(value);
|
|
65
|
-
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
66
|
-
throw usageError(`Invalid --port: ${value}`);
|
|
67
|
-
return port;
|
|
68
|
-
}
|
|
69
60
|
async function resolveLinkedAuth(projectRoot) {
|
|
70
61
|
const link = await readProjectLink(projectRoot);
|
|
71
62
|
const credentials = await readProjectCredentials(projectRoot);
|
|
@@ -83,106 +74,34 @@ async function resolveLinkedAuth(projectRoot) {
|
|
|
83
74
|
if (url && key && tenantId) {
|
|
84
75
|
return { url, key, tenantId, tenantName: tenantId };
|
|
85
76
|
}
|
|
86
|
-
throw new CliError(`No Project link in ${projectRoot}. Run
|
|
77
|
+
throw new CliError(`No Project link in ${projectRoot}. Run nylo tenant create, or set NYLORUN_RUNTIME_URL, NYLORUN_SERVER_KEY and NYLORUN_TENANT.`, 1);
|
|
87
78
|
}
|
|
88
79
|
async function main() {
|
|
89
|
-
const [
|
|
90
|
-
if (!
|
|
80
|
+
const [command, ...args] = process.argv.slice(2);
|
|
81
|
+
if (!command || command === "--help" || command === "-h")
|
|
91
82
|
return void console.log(usage);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
down: "down",
|
|
95
|
-
logs: "logs",
|
|
96
|
-
};
|
|
97
|
-
const command = rawCommand in aliases ? "runtime" : rawCommand;
|
|
98
|
-
const args = rawCommand in aliases ? [aliases[rawCommand], ...rawArgs] : rawArgs;
|
|
83
|
+
if (process.platform === "win32")
|
|
84
|
+
throw new CliError("Nylorun does not run on native Windows. Use WSL2: install Node 24 and Docker (Docker Desktop's WSL integration) inside your WSL distribution and run nylorun there (https://learn.microsoft.com/windows/wsl/install).", 1);
|
|
99
85
|
if (command === "tenant")
|
|
100
86
|
return await tenantCommand(args);
|
|
101
|
-
if (command === "
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
await printLinkedEnvExports(root);
|
|
107
|
-
},
|
|
108
|
-
});
|
|
87
|
+
if (command === "env") {
|
|
88
|
+
if (args.length)
|
|
89
|
+
throw usageError("Usage: nylo env");
|
|
90
|
+
await printLinkedEnvExports(findProjectRoot() ?? process.cwd());
|
|
91
|
+
return;
|
|
109
92
|
}
|
|
110
93
|
if (command === "doctor") {
|
|
111
94
|
const [topic, ...options] = args;
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const json = options.includes("--json");
|
|
117
|
-
if (topic === "runtime")
|
|
118
|
-
await doctorRuntime({ json });
|
|
119
|
-
else
|
|
120
|
-
await doctorSandbox({ json });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (command === "dev") {
|
|
124
|
-
const flags = parseFlags(args, {
|
|
125
|
-
booleans: ["--ephemeral", "--local-ui", "--no-studio", "--no-open"],
|
|
126
|
-
});
|
|
127
|
-
if (flags.rest.length > 1)
|
|
128
|
-
throw usageError(usage);
|
|
129
|
-
if (flags.booleans.has("--local-ui") && flags.booleans.has("--no-studio"))
|
|
130
|
-
throw usageError("--local-ui cannot be combined with --no-studio.");
|
|
131
|
-
requireProjectRoot();
|
|
132
|
-
developmentPreflight([
|
|
133
|
-
...flags.rest,
|
|
134
|
-
...[...flags.booleans],
|
|
135
|
-
]);
|
|
136
|
-
process.exitCode = await develop({
|
|
137
|
-
...(flags.rest[0] ? { entry: flags.rest[0] } : {}),
|
|
138
|
-
flags: [...flags.booleans],
|
|
139
|
-
});
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (command === "serve") {
|
|
143
|
-
throw usageError("nylorun serve was removed. Use nylorun dev [entry] in development, or node dist/src/main.js with NYLORUN_RUNTIME_URL, NYLORUN_TENANT and NYLORUN_SERVER_KEY.");
|
|
144
|
-
}
|
|
145
|
-
if (command === "studio") {
|
|
146
|
-
const flags = parseFlags(args, {
|
|
147
|
-
booleans: ["--local-ui", "--no-open"],
|
|
148
|
-
values: ["--port"],
|
|
149
|
-
});
|
|
150
|
-
if (flags.rest.length)
|
|
151
|
-
throw usageError(usage);
|
|
152
|
-
const projectRoot = findProjectRoot() ?? process.cwd();
|
|
153
|
-
// Surface missing Studio early with the same Install message as preflight.
|
|
154
|
-
try {
|
|
155
|
-
createRequire(join(projectRoot, "package.json")).resolve("@nylorun/studio");
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
throw new Error("Install @nylorun/studio to use the Studio dashboard.");
|
|
159
|
-
}
|
|
160
|
-
const auth = await resolveLinkedAuth(projectRoot);
|
|
161
|
-
const localUi = flags.booleans.has("--local-ui");
|
|
162
|
-
// I2: startStudio default is hosted; `--local-ui` forces local + cacheDir.
|
|
163
|
-
const dashboard = await startStudio({
|
|
164
|
-
runtimeUrl: auth.url,
|
|
165
|
-
serverKey: auth.key,
|
|
166
|
-
tenant: { id: auth.tenantId, name: auth.tenantName },
|
|
167
|
-
open: !flags.booleans.has("--no-open"),
|
|
168
|
-
localUi,
|
|
169
|
-
cacheDir: resolveHome(),
|
|
170
|
-
projectRoot,
|
|
171
|
-
...(flags.values.has("--port")
|
|
172
|
-
? { port: parsePort(flags.values.get("--port")) }
|
|
173
|
-
: {}),
|
|
174
|
-
});
|
|
175
|
-
console.log(`Studio ${dashboard.launchUrl}`);
|
|
176
|
-
if (!localUi && dashboard.launchUrl.startsWith("https://local.nylorun.studio")) {
|
|
177
|
-
console.log(`Safari or offline: nylorun studio --local-ui`);
|
|
178
|
-
}
|
|
179
|
-
await new Promise((resolve, reject) => {
|
|
180
|
-
const close = () => void dashboard.close().then(resolve, reject);
|
|
181
|
-
process.once("SIGINT", close);
|
|
182
|
-
process.once("SIGTERM", close);
|
|
183
|
-
});
|
|
95
|
+
if (topic !== "sandbox" || options.some((option) => option !== "--json"))
|
|
96
|
+
throw usageError("Usage: nylo doctor sandbox [--json]. Check the local stack with npx nylorun doctor.");
|
|
97
|
+
const { doctorSandbox } = await import("./doctor.js");
|
|
98
|
+
await doctorSandbox({ json: options.includes("--json") });
|
|
184
99
|
return;
|
|
185
100
|
}
|
|
101
|
+
if (command === "dev")
|
|
102
|
+
throw usageError("nylorun dev was removed: run nylo tenant create once in your project, then your project's npm run dev.");
|
|
103
|
+
if (STACK_COMMANDS.has(command))
|
|
104
|
+
throw usageError(`The local stack moved to the nylorun package: npx nylorun ${command}`);
|
|
186
105
|
if (command === "configure") {
|
|
187
106
|
const flags = parseFlags(args);
|
|
188
107
|
if (flags.rest.length)
|
|
@@ -195,7 +114,7 @@ async function main() {
|
|
|
195
114
|
process.once("SIGTERM", () => cancel("SIGTERM"));
|
|
196
115
|
const health = await fetch(`${auth.url}/health`).catch(() => undefined);
|
|
197
116
|
if (!health?.ok)
|
|
198
|
-
throw new CliError(`No Runtime
|
|
117
|
+
throw new CliError(`No Runtime is listening at ${auth.url}. Start the local stack with "npx nylorun up".`, 6);
|
|
199
118
|
const catalog = await fetchModelCatalog({
|
|
200
119
|
url: auth.url,
|
|
201
120
|
key: auth.key,
|
package/dist/doctor.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type AgentManifest } from "@nylorun/agents";
|
|
2
1
|
export type SandboxReport = {
|
|
3
2
|
preference: string;
|
|
4
3
|
backend: string | null;
|
|
@@ -13,17 +12,7 @@ export type SandboxReport = {
|
|
|
13
12
|
}[];
|
|
14
13
|
defaultImage?: string;
|
|
15
14
|
};
|
|
16
|
-
/**
|
|
17
|
-
* `nylorun doctor runtime`: check the two prerequisites (Node 24+ and an
|
|
18
|
-
* installed `@nylorun/runtime`) and print the fix for each one that fails.
|
|
19
|
-
* Exits 1 when a prerequisite is missing; installs nothing.
|
|
20
|
-
*/
|
|
21
|
-
export declare function doctorRuntime(options: {
|
|
22
|
-
json: boolean;
|
|
23
|
-
}): Promise<void>;
|
|
24
|
-
/** `nylorun doctor sandbox`: Tenant sandbox report via the Tenant API (F2-4). */
|
|
15
|
+
/** `nylo doctor sandbox`: Tenant sandbox report via the Tenant API (F2-4). */
|
|
25
16
|
export declare function doctorSandbox(options: {
|
|
26
17
|
json: boolean;
|
|
27
18
|
}): Promise<void>;
|
|
28
|
-
/** One line for the dev banner, or undefined when no connected agent declares a sandbox. */
|
|
29
|
-
export declare function sandboxBanner(runtimeUrl: string, serverKey: string, manifests: readonly AgentManifest[], tenantId: string): Promise<string | undefined>;
|
package/dist/doctor.js
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import { release } from "node:os";
|
|
2
|
-
import {
|
|
2
|
+
import { createClient, resolveConnection } from "@nylorun/agents";
|
|
3
3
|
import { CliError } from "./errors.js";
|
|
4
|
-
import { launcher, resolveHome, runtimeInstallCommand } from "./runtime/launcher.js";
|
|
5
|
-
/** Oldest Node the Runtime runs on (it needs node:sqlite). */
|
|
6
|
-
const MIN_NODE_MAJOR = 24;
|
|
7
|
-
const LABEL = {
|
|
8
|
-
microsandbox: "microsandbox VM",
|
|
9
|
-
virtual: "virtual shell",
|
|
10
|
-
};
|
|
11
4
|
function platformLine() {
|
|
12
5
|
const os = process.platform === "darwin"
|
|
13
6
|
? "macOS"
|
|
14
|
-
: process.
|
|
15
|
-
?
|
|
7
|
+
: process.env.WSL_DISTRO_NAME
|
|
8
|
+
? `Linux (WSL: ${process.env.WSL_DISTRO_NAME})`
|
|
16
9
|
: process.platform;
|
|
17
10
|
return `${os} (kernel ${release()}) · ${process.arch}`;
|
|
18
11
|
}
|
|
@@ -25,54 +18,7 @@ async function fetchSandboxReport(options) {
|
|
|
25
18
|
});
|
|
26
19
|
return client.transport.json("/v1/tenant/sandbox", "GET", undefined);
|
|
27
20
|
}
|
|
28
|
-
/**
|
|
29
|
-
* `nylorun doctor runtime`: check the two prerequisites (Node 24+ and an
|
|
30
|
-
* installed `@nylorun/runtime`) and print the fix for each one that fails.
|
|
31
|
-
* Exits 1 when a prerequisite is missing; installs nothing.
|
|
32
|
-
*/
|
|
33
|
-
export async function doctorRuntime(options) {
|
|
34
|
-
const nodeOk = Number(process.versions.node.split(".")[0]) >= MIN_NODE_MAJOR;
|
|
35
|
-
let runtime;
|
|
36
|
-
try {
|
|
37
|
-
const handle = await launcher(resolveHome());
|
|
38
|
-
runtime = { ok: true, ...handle.runtime };
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
runtime = {
|
|
42
|
-
ok: false,
|
|
43
|
-
problem: error instanceof Error ? error.message : String(error),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
if (options.json) {
|
|
47
|
-
console.log(JSON.stringify({
|
|
48
|
-
node: { version: process.versions.node, ok: nodeOk },
|
|
49
|
-
runtime,
|
|
50
|
-
install: runtimeInstallCommand(),
|
|
51
|
-
}, null, 2));
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
const rows = [
|
|
55
|
-
[
|
|
56
|
-
"node",
|
|
57
|
-
nodeOk
|
|
58
|
-
? `✓ ${process.versions.node}`
|
|
59
|
-
: `✗ ${process.versions.node}: install Node ${MIN_NODE_MAJOR} or newer`,
|
|
60
|
-
],
|
|
61
|
-
[
|
|
62
|
-
"runtime",
|
|
63
|
-
runtime.ok
|
|
64
|
-
? `✓ ${runtime.version} · ${runtime.bin}`
|
|
65
|
-
: `✗ ${runtime.problem.split("\n")[0]}\n ${runtimeInstallCommand()}`,
|
|
66
|
-
],
|
|
67
|
-
];
|
|
68
|
-
const width = Math.max(...rows.map(([key]) => key.length)) + 2;
|
|
69
|
-
for (const [key, value] of rows)
|
|
70
|
-
console.log(` ${key.padEnd(width)}${value}`);
|
|
71
|
-
}
|
|
72
|
-
if (!nodeOk || !runtime.ok)
|
|
73
|
-
process.exitCode = 1;
|
|
74
|
-
}
|
|
75
|
-
/** `nylorun doctor sandbox`: Tenant sandbox report via the Tenant API (F2-4). */
|
|
21
|
+
/** `nylo doctor sandbox`: Tenant sandbox report via the Tenant API (F2-4). */
|
|
76
22
|
export async function doctorSandbox(options) {
|
|
77
23
|
let report;
|
|
78
24
|
try {
|
|
@@ -96,7 +42,7 @@ export async function doctorSandbox(options) {
|
|
|
96
42
|
rows.push([
|
|
97
43
|
"preference",
|
|
98
44
|
report.preference === "auto"
|
|
99
|
-
? "auto (seed Tenant sandbox.backend via
|
|
45
|
+
? "auto (seed Tenant sandbox.backend via nylo tenant create / .env NYLORUN_SANDBOX)"
|
|
100
46
|
: report.preference,
|
|
101
47
|
]);
|
|
102
48
|
rows.push([
|
|
@@ -109,41 +55,5 @@ export async function doctorSandbox(options) {
|
|
|
109
55
|
for (const [key, value] of rows)
|
|
110
56
|
console.log(` ${key.padEnd(width)}${value}`);
|
|
111
57
|
if (report.backend === "virtual")
|
|
112
|
-
console.log("\n The virtual shell emulates bash in the Runtime process; it is not a VM boundary
|
|
113
|
-
" For hardware isolation use macOS on Apple Silicon or Linux with KVM.");
|
|
114
|
-
}
|
|
115
|
-
/** One line for the dev banner, or undefined when no connected agent declares a sandbox. */
|
|
116
|
-
export async function sandboxBanner(runtimeUrl, serverKey, manifests, tenantId) {
|
|
117
|
-
const capability = manifests
|
|
118
|
-
.flatMap((manifest) => manifest.capabilities)
|
|
119
|
-
.find((item) => item.sandbox);
|
|
120
|
-
if (!capability)
|
|
121
|
-
return undefined;
|
|
122
|
-
let report;
|
|
123
|
-
try {
|
|
124
|
-
const response = await fetch(`${runtimeUrl}/v1/tenant/sandbox`, {
|
|
125
|
-
headers: {
|
|
126
|
-
authorization: `Bearer ${serverKey}`,
|
|
127
|
-
[TENANT_HEADER]: tenantId,
|
|
128
|
-
[PROTOCOL_HEADER]: String(PROTOCOL_VERSION),
|
|
129
|
-
},
|
|
130
|
-
signal: AbortSignal.timeout(10_000),
|
|
131
|
-
});
|
|
132
|
-
if (response.ok)
|
|
133
|
-
report = (await response.json());
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
/* ignore */
|
|
137
|
-
}
|
|
138
|
-
if (!report)
|
|
139
|
-
return undefined;
|
|
140
|
-
const doctor = "run `npx nylorun doctor sandbox` for options";
|
|
141
|
-
if (!report.backend)
|
|
142
|
-
return `sandbox: unavailable (${report.reason}) · ${doctor}`;
|
|
143
|
-
const image = capability.sandbox?.image ?? report.defaultImage;
|
|
144
|
-
const network = capability.sandbox?.network?.preset ?? "dev";
|
|
145
|
-
const fellBack = report.preference === "auto" && report.backend !== report.probes[0]?.name;
|
|
146
|
-
return fellBack
|
|
147
|
-
? `sandbox: ${LABEL[report.backend] ?? report.backend} (${report.reason}) · ${doctor}`
|
|
148
|
-
: `sandbox: ${LABEL[report.backend] ?? report.backend}${report.backend === "microsandbox" && image ? ` · image ${image}` : ""} · network: ${network}`;
|
|
58
|
+
console.log("\n The virtual shell emulates bash in the Runtime process; it is not a VM boundary.");
|
|
149
59
|
}
|
package/dist/home.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Host root: an explicit home, `NYLORUN_HOME`, or `~/.nylorun`. The stack
|
|
3
|
+
* bind-mounts it into the Runtime and Studio containers, and `@nylorun/admin`
|
|
4
|
+
* reads `host.json` and the admin key from it.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveHome(home?: string, env?: Readonly<Record<string, string | undefined>>): string;
|
package/dist/home.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* The Host root: an explicit home, `NYLORUN_HOME`, or `~/.nylorun`. The stack
|
|
5
|
+
* bind-mounts it into the Runtime and Studio containers, and `@nylorun/admin`
|
|
6
|
+
* reads `host.json` and the admin key from it.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveHome(home, env = process.env) {
|
|
9
|
+
if (home !== undefined && home.trim() !== "")
|
|
10
|
+
return resolve(home);
|
|
11
|
+
const fromEnv = env.NYLORUN_HOME?.trim();
|
|
12
|
+
if (fromEnv)
|
|
13
|
+
return resolve(fromEnv);
|
|
14
|
+
return resolve(join(homedir(), ".nylorun"));
|
|
15
|
+
}
|
package/dist/model/host-model.js
CHANGED
|
@@ -69,7 +69,7 @@ export async function ensureHostModel(options) {
|
|
|
69
69
|
await putHostModel(options.runtimeUrl, options.serverKey, prompted, options.tenantId);
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
|
-
throw new Error("Model provider is not configured. Run
|
|
72
|
+
throw new Error("Model provider is not configured. Run nylo configure in a terminal to set it up, or open Studio.");
|
|
73
73
|
}
|
|
74
74
|
function seedFromEnv(env, root) {
|
|
75
75
|
const provider = env.MODEL_PROVIDER?.trim();
|