@nylorun/cli 0.5.0-beta → 0.7.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 +167 -0
- package/README.md +47 -55
- package/dist/access/commands.d.ts +24 -0
- package/dist/access/commands.js +144 -0
- package/dist/cli.js +40 -39
- package/dist/doctor.d.ts +7 -0
- package/dist/doctor.js +11 -6
- package/dist/home.d.ts +3 -3
- package/dist/home.js +3 -3
- package/dist/installation/commands.d.ts +20 -0
- package/dist/installation/commands.js +146 -0
- package/dist/model/configure.d.ts +12 -1
- package/dist/model/configure.js +55 -7
- package/dist/model/host-model.d.ts +7 -11
- package/dist/model/host-model.js +7 -86
- package/dist/project/connection.d.ts +13 -0
- package/dist/project/connection.js +18 -0
- package/dist/project/credentials.d.ts +4 -12
- package/dist/project/credentials.js +6 -36
- package/dist/project/env.d.ts +1 -1
- package/dist/project/env.js +2 -3
- package/dist/project/link.d.ts +10 -17
- package/dist/project/link.js +28 -60
- package/package.json +5 -5
- package/dist/project/create-tenant.d.ts +0 -28
- package/dist/project/create-tenant.js +0 -66
- package/dist/project/seed.d.ts +0 -25
- package/dist/project/seed.js +0 -96
- package/dist/tenant/commands.d.ts +0 -4
- package/dist/tenant/commands.js +0 -345
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,172 @@
|
|
|
1
1
|
# @nylorun/cli
|
|
2
2
|
|
|
3
|
+
## 0.7.0-beta
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 5ca1923: **Clients for one Tenant per installation: a stack per project, nothing selects a Tenant.** Upgrade these with the Runtime; they speak protocol 5. Existing stacks are left as they are: see MIGRATION.md.
|
|
8
|
+
|
|
9
|
+
- **Breaking (`nylorun`): one stack per project.** `nylorun start` in a project creates the project's stack (named after the project directory, or `--name`; Host root `~/.nylorun/stacks/<name>/`, Compose project `nylorun-<name>`, its own free ports and volumes), waits for its Runtime to create the stack's Tenant, writes the Project link (`.nylorun/link.json` format 2: `stack`, `hostUrl`, `hostId`, `tenantId`) and `.nylorun/credentials.json` (the key of the derived principal `project`, derived from the stack's admin key), and seeds the model provider from the project's `.env`. `nylorun ls` lists the machine's stacks and `nylorun delete <name>` removes one with its volumes and Host root. `nylorun status` shows the stack's Tenant; `nylorun studio` opens it. The old single stack under `~/.nylorun` is never touched: `start` notes it, and `nylorun legacy stop|delete` handles it. Every stack command takes `--name <stack>` (or `NYLORUN_STACK`, or the Project link's stack); `start --no-link` starts a stack without linking the directory; `nylorun reset` resets the selected stack only. The runtime container's healthcheck is now `/health`, so a Tenant that cannot open is reported by `start` from the Admin status at once instead of after a 300 s wait. `NYLORUN_HOME` still overrides the Host root. Stacks start and stop only when you say so.
|
|
10
|
+
- **Breaking (`@nylorun/cli`): no Tenant commands.** `nylo tenant create|use|list|current|delete` are removed; `nylo status`, `nylo reset` and `nylo endpoints` replace `nylo tenant status|reset|endpoints` on the linked installation. `nylo env` prints `NYLORUN_RUNTIME_URL` and `NYLORUN_SERVER_KEY` only. `nylo` no longer writes Project links.
|
|
11
|
+
- **Breaking (`@nylorun/agents`): no Tenant to name.** The `tenant` option (`createClient`, `Transport`, `resolveConnection`, `createActionHandler({ runtime })`, `JwksCache`) and `NYLORUN_TENANT` are gone, and no request sends `Nylorun-Tenant`; a connection is a URL and a key. A Project link of format 0 or 1 is refused with `connection_missing`, naming `npx nylorun start`. `verifyDeliveryToken`'s `tenantId` is optional: without it any Tenant issuer is accepted, since the installation's keys bind it. `TENANT_HEADER` is no longer re-exported.
|
|
12
|
+
- **Breaking (`@nylorun/admin`): status only.** `createTenant`, `listTenants`, `getTenant` and `deleteTenant` are removed; `status().tenant` names the Host's Tenant, and `deriveTenantKey` / `deriveStudioToken` derive its keys. Local Host resolution reads the stack's Host root (`stack` option, `NYLORUN_STACK`, or the Project link's `stack`); `NYLORUN_HOME` and `home` still override it. `stackHostRoot(name)` is exported.
|
|
13
|
+
- **Breaking (`@nylorun/studio`): Studio serves its installation's Tenant.** The Tenant picker, list and create are gone, with `/_studio/tenants`; `/` opens `/tenants/<id>`. The `/tenants/:tenant` routes and the login token's `tenant` claim stay for embedders and must name that Tenant. The proxy sends no `Nylorun-Tenant`.
|
|
14
|
+
- **`@nylorun/create-agent`:** the next steps are `npx nylorun start`, then `npm run dev`.
|
|
15
|
+
- `@nylorun/core`: `ProjectLinkFileSchema` accepts format 2 with `stack`, and `tenantId` is optional; `ERROR_CODES` loses `tenant_conflict` and `active_work`.
|
|
16
|
+
|
|
17
|
+
- 5ca1923: **One Tenant per installation: a database per Tenant, protocol 5.** A Runtime serves exactly one Tenant, the one its Postgres database holds. Two Tenants are two installations.
|
|
18
|
+
|
|
19
|
+
- **Breaking: fresh start.** The Tenant's state is in the fixed schema `nylorun` of its own database and its record in `nylorun_streams`, keyed by session (no `tenant_id`). A database written by an earlier Runtime (`tenant_<id>` schemas, or a record keyed by Tenant) is refused: the Host stays up but not ready, and `/v1/admin/status` names the cause `database-layout-old`. Point the Runtime at a new database (with the local stack, a new stack); the old one is never changed.
|
|
20
|
+
- **The Host creates its Tenant** on first start, in the migration transaction: `NYLORUN_TENANT_ID` (default a new id), `NYLORUN_TENANT_NAME` (default `default`), the Studio principal and the derived principals of `NYLORUN_DERIVED_PRINCIPALS` (comma-separated, default `project`), whose keys the admin key derives (`deriveTenantKey`). Later starts open the same Tenant and add derived principals configured since.
|
|
21
|
+
- **Breaking: no Tenant catalog.** `/v1/admin/tenants` and `/v1/admin/tenants/{tenantId}` are gone (404). `AdminStatus.tenants[]` is replaced by `AdminStatus.tenant` (`id`, `name`, `state: open | unavailable`, `envelope`, and `cause` when it could not be opened). `CreateTenantRequestSchema`, `AdminTenantSchema`, `AdminTenantStatusSchema`, `AdminTenantListSchema` and `QuarantineSchema` leave `@nylorun/core`; `HostTenantSchema` and `TenantCauseSchema` replace them. `@nylorun/admin`'s `listTenants`, `getTenant`, `deleteTenant` and `createTenant` are removed (see below).
|
|
22
|
+
- **Readiness instead of quarantine.** A Tenant that cannot be opened (`schema-too-new`, `kek-missing`, `migration-failed`, `envelope-invalid`, `database-layout-old`, …) fails `/ready` (check `tenant`, which replaces `discovery`) and is reported with its repair in `/v1/admin/status` and the log; every Tenant request gets the opaque 404. A failure outside it (Postgres unreachable) is retried.
|
|
23
|
+
- **Protocol 5.** `PROTOCOL_VERSION = 5`; the Host serves protocols 4 and 5 for one release. Clients no longer require `runtime-tenants`; the Host still advertises it. No request needs `Nylorun-Tenant`: a request without it reaches the Host's Tenant, and one naming another Tenant (or a malformed one), or a publishable key of another Tenant, gets the opaque 404. The OpenAPI documents drop the header parameter and the Admin Tenant routes.
|
|
24
|
+
- **Paths.** The Tenant directory is `<Host root>/tenant/` (was `tenants/<id>/`); `trash/` and the SQLite move to it are gone. The gates service serves its database's Tenant, and its `Nylorun-Tenant` header is optional (when sent, it must name that Tenant).
|
|
25
|
+
- **Breaking: `startEphemeralRuntime` needs a database; the in-memory Session Store is removed.** `StartEphemeralRuntimeOptions.database` is required: a Postgres URL, for which the Runtime opens a pool and ends it on `close()`, or a pool the caller ends. It creates its Tenant in that database through the same bootstrap as a Host, or serves the Tenant the database already holds; the data stays after `close()`, so give each test Tenant a database of its own. Durable Streams and scheduling stay in process. See `MIGRATION.md`.
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Pin agents to the tested release.
|
|
30
|
+
- Pin admin to the tested release.
|
|
31
|
+
- Updated dependencies [5ca1923]
|
|
32
|
+
- Updated dependencies [5ca1923]
|
|
33
|
+
- Updated dependencies
|
|
34
|
+
- Updated dependencies
|
|
35
|
+
- @nylorun/agents@0.11.0-beta
|
|
36
|
+
- @nylorun/admin@0.7.0-beta
|
|
37
|
+
|
|
38
|
+
## 0.6.0-beta
|
|
39
|
+
|
|
40
|
+
### Minor Changes
|
|
41
|
+
|
|
42
|
+
- 4282d5f: **Breaking: executors are removed; protocol 3.** The Runtime delivers every Action (tool, hook, `fn`, `verify`) to the Action endpoint an agent registers. It no longer offers Actions for executors to claim. See `MIGRATION.md`, "Action endpoints replace executors".
|
|
43
|
+
|
|
44
|
+
- **Core.** `PROTOCOL_VERSION` is 3 and a Host serves only protocol 3. `action-endpoints` is a protocol feature instead of an optional Host feature. Removed:
|
|
45
|
+
|
|
46
|
+
- the executor, claim and Action-list schemas;
|
|
47
|
+
- `action_result` from `SessionCommandSchema`;
|
|
48
|
+
- the `claimed` Action status, `claimId` and `leaseExpiresAt`.
|
|
49
|
+
|
|
50
|
+
New: `ActionResultReceiptSchema`, the receipt of `POST /v1/actions/:id/result`, which is `AcceptedResponse` without `requestId`.
|
|
51
|
+
|
|
52
|
+
- **Runtime.** Removed:
|
|
53
|
+
|
|
54
|
+
- `PUT`/`GET /v1/executors`, `DELETE /v1/executors/:agentId`, `GET /v1/executors/connect`;
|
|
55
|
+
- `GET /v1/actions`, `POST /v1/actions/:id/claim`, and the executor form of `POST /v1/actions/:id/heartbeat`;
|
|
56
|
+
- the `tenant/work` stream;
|
|
57
|
+
- claim expiry;
|
|
58
|
+
- executor credentials.
|
|
59
|
+
|
|
60
|
+
`POST /v1/actions/:id/sandbox/:tool` takes the delivery token only. Tenant summaries report `inFlightDeliveries` instead of `connectedExecutors`. Tenant status lists each agent's endpoint and has an `endpoints` check instead of `executors`.
|
|
61
|
+
|
|
62
|
+
Postgres migration 6 drops the `executors` table. Actions an executor had claimed are handled like lost deliveries: a tool becomes `uncertain`, and a hook, `fn` or `verify` is delivered again.
|
|
63
|
+
|
|
64
|
+
- **Agents.** Removed: `connectAgents`, the `@nylorun/agents/executor` subpath, derived executor keys and `NYLORUN_EXECUTOR_KEY`. Serve agents with `createActionHandler` and call `register({ url })`.
|
|
65
|
+
- **CLI.** Executor keys are gone from Project credentials. `nylo tenant endpoints` shows each endpoint and its health.
|
|
66
|
+
|
|
67
|
+
- 82d95ef: **Action endpoints: background tools, CLI and Studio.**
|
|
68
|
+
|
|
69
|
+
- **Background tools (core, agents).** `tool({ …, background: true })` marks a tool that runs longer than an endpoint's timeout. The option is code-only and never serialized into the manifest. `createActionHandler` answers its delivery at once with `202`, runs the tool, heartbeats on the deadline the Runtime returns (each time with the newest delivery token), and posts the outcome. A heartbeat answered `409` (cancelled, lost or sent again) aborts the tool's `ctx.signal`, and nothing is posted. The new `waitUntil` option hands the background work to platforms that end a request's work with its response.
|
|
70
|
+
- **CLI.** `nylo tenant endpoints [--json]` lists each agent's Action endpoint and how it is doing, and `nylo tenant endpoints ping <agent>` pings one through the Runtime.
|
|
71
|
+
- **Studio.** Shows `action.delivered` ("Action delivered") and `action.delivery_failed` ("Delivery failed", with the endpoint's error and when it retries).
|
|
72
|
+
|
|
73
|
+
- 50d0fb5: **Browser access: web pages and apps call the Runtime with a publishable key.** A page ships a publishable key and gets subject tokens from its app server; the Runtime answers it directly, with CORS (optional Host feature `browser-access`).
|
|
74
|
+
|
|
75
|
+
- **Publishable keys.** `nr_pub_<tenantId>_…`, sent in `Nylorun-Key`, name the Tenant and one app, with an origin allowlist (exact origins, or `http://localhost:*` and `http://127.0.0.1:*` for development; none for native apps). `GET`/`POST /v1/access/publishable-keys`, `PUT`/`DELETE …/:id`. A key alone grants the policy's `anon` role, at most the public agent list, and reaches no session or vault. Postgres migration 4.
|
|
76
|
+
- **Host.** With browser access on, requests with an `Origin` reach Tenant routes; `/health`, `/ready` and admin routes still refuse them. Preflights for browser routes (agents, sessions, vaults, AG-UI, JWKS) are answered from the route alone and grant no credentials; the actual request must carry a publishable key whose allowlist names the origin, and only then do responses (JSON, errors, `401`, `429`, event streams) carry CORS headers. A disallowed origin or unknown key gets the opaque `404`. Tenant and executor keys sent with an `Origin` are refused before they are looked up. `Nylorun-Tenant` may be left out when `Nylorun-Key` names the Tenant; both must agree when both are sent. Browser access is on in the stack (`NYLORUN_BROWSER_ACCESS=off` turns it off) and off for a Host started from `host.json` unless `browserAccess` is true.
|
|
77
|
+
- **JWKS.** `GET /v1/access/jwks` is readable by any caller that reaches the Tenant.
|
|
78
|
+
- **Agents SDK.** `@nylorun/agents/browser`: `createBrowserClient({ url, publishableKey, token })` keeps subject tokens in memory, refreshes them a minute before expiry or after `401 token_expired`, one fetch at a time, and creates sessions and vaults owned by the token's subject; it loads no Node module. `createTokenEndpoint()` is the app server's token route. `client.access.publishableKeys` manages keys. The transport accepts a `token` source and a `publishableKey`, and event streams the Runtime ends at token expiry reconnect at once. The Tenant API client classes move to a module with no Node imports; `@nylorun/agents` and `/client` export the same names.
|
|
79
|
+
- **CLI.** `nylo access keys list|create|set-origins|revoke`.
|
|
80
|
+
|
|
81
|
+
- 6ab4c59: **Long sessions on any model: compaction.** A session whose history outgrows the model's context window keeps going, on a 16k local model as on a 1M hosted one.
|
|
82
|
+
|
|
83
|
+
- **Compaction.**
|
|
84
|
+
- **When.** Before each model call the engine estimates the prompt: the last reported usage, plus about four characters per token for what came after. If the estimate would not leave room for the reply, the engine first compacts: it asks the model to summarize the older history, then keeps about the newest 20,000 tokens (at most 30% of the window) verbatim.
|
|
85
|
+
- **What it keeps.** The cut never separates a tool call from its result. The current turn's request is always kept. A later compaction merges with the earlier summary.
|
|
86
|
+
- **Overflow.** If a provider still reports a context overflow, the engine compacts once and asks again.
|
|
87
|
+
- **Storage.** The summary is a `compaction` transcript entry that replaces the older entries in the session state; the event log keeps the full history. The summary call is a journaled model effect, so replays are deterministic.
|
|
88
|
+
- **New event.** `context.compacted` (`trigger`, `tokensBefore`, `tokensAfter`).
|
|
89
|
+
- **Custom endpoints.**
|
|
90
|
+
- **Settings.** Model Settings take `settings: { contextWindow, maxTokens, reasoning, compat }` for a custom OpenAI-compatible provider (vLLM, SGLang, llama.cpp, Ollama, LM Studio). `compat` is passed to pi-ai: `thinkingFormat`, `thinkingTokenBudgetField`, `chatTemplateKwargs` and the rest.
|
|
91
|
+
- **Defaults.** Without settings, a custom endpoint is assumed to have a 32k window and an 8k output limit. They used to be 128k and 16k.
|
|
92
|
+
- **Where to set them.** `nylo configure` asks for the window and output limit. Studio's Model Settings shows all four fields.
|
|
93
|
+
- **Storage.**
|
|
94
|
+
- Model effects no longer journal the model request next to the call, so each call's prompt is stored once.
|
|
95
|
+
- When a turn ends, its model effects are slimmed to their identity and status; the transcript holds the answers.
|
|
96
|
+
- Session storage now grows with the window, not with the square of the session's length.
|
|
97
|
+
- **Core.**
|
|
98
|
+
- `TranscriptEntry` adds `compaction` (`TranscriptCompactionEntry`).
|
|
99
|
+
- `ModelAdapterContext.compaction` marks a summary call.
|
|
100
|
+
- `CustomModelSettings` / `CustomModelSettingsSchema` describe the custom endpoint settings.
|
|
101
|
+
|
|
102
|
+
- 50d0fb5: **Subject tokens: a person's own credential for the Runtime.** An app server mints a short-lived token for one signed-in person, and their app calls the Runtime directly (optional Host feature `subject-tokens`). Requests with application keys and subject headers are unchanged.
|
|
103
|
+
|
|
104
|
+
- **Runtime.** `POST /v1/tokens` (application key only) mints an ES256 JWT for a subject and a role, valid 60–900 seconds. The Tenant API accepts it as a bearer and resolves its scopes and agents from the role on every request. Forged, foreign or malformed tokens get the opaque `404`; an expired token, a revoked subject, a revoked key or a removed role gets `401 token_expired` with `WWW-Authenticate`. Tokens carry only `agents:read`, `sessions:own` and `vaults:own`; they may not set session `info`, send `message.manifest` or store OAuth refresh credentials, and `GET /v1/agents` shows them `{ agentId, name, description }` of their role's agents only.
|
|
105
|
+
- **Access policy.** `GET`/`PUT /v1/access/policy`: roles with token scopes, an agent allowlist and limits (`turnsPerHour`, `concurrentTurns`, answered with `429 limit_exceeded` and `Retry-After`). Without roles nothing is minted.
|
|
106
|
+
- **Signing keys.** Per Tenant, the private key sealed with the vault KEK: `GET /v1/access/signing-keys`, `POST …/rotate` (refused while the previous key may still verify live tokens; `force` for incidents), `POST …/:kid/revoke`, `GET /v1/access/jwks`. A Tenant with signing keys and no KEK is quarantined `kek-missing`.
|
|
107
|
+
- **Revocation.** `POST /v1/access/revocations` ends a subject's tokens; their open event streams end with `event: nylorun.closed` on every process. A stream opened with a token also ends when the token expires.
|
|
108
|
+
- Postgres migration 3 adds `signing_keys`, `subject_epochs`, `subject_usage` and an index on the session owner and status. New error codes `token_expired` and `limit_exceeded`.
|
|
109
|
+
- **Agents SDK.** `client.tokens.create()`, `client.access.getPolicy()`/`putPolicy()`/`revokeSubject()`/`jwks()` and `client.access.signingKeys.list()`/`rotate()`/`revoke()`, each checking the Host feature first.
|
|
110
|
+
- **CLI.** `nylo access policy get|set|init`, `nylo access signing-keys list|rotate|revoke`, `nylo access revoke <subject>` and `nylo access token` for trying the API.
|
|
111
|
+
|
|
112
|
+
### Patch Changes
|
|
113
|
+
|
|
114
|
+
- f39b79f: **`nylo doctor sandbox` shows the Tenant's default sandbox**: `none`, `virtual`, or a Tenant sandbox that sessions naming no sandbox get.
|
|
115
|
+
- 6ab4c59: **Model calls don't strand sessions.** A model provider failure is now a known outcome, not a lost call. The Runtime retries what can be retried, and otherwise fails the turn with `model.<code>`, so the session accepts the next message instead of sitting `uncertain` until it is cancelled.
|
|
116
|
+
|
|
117
|
+
- **Runtime.**
|
|
118
|
+
|
|
119
|
+
- **Upgrade.** The model adapter moves to pi-ai 0.99.1 and always streams.
|
|
120
|
+
- **Per-call settings.**
|
|
121
|
+
- Every call carries the session id, so OpenAI and other providers reuse the prompt cache and route to the same backend.
|
|
122
|
+
- Provider auth no longer reads the process environment.
|
|
123
|
+
- Rate limits, overloads, timeouts and transient errors are retried: 3 attempts with backoff, honouring `Retry-After`.
|
|
124
|
+
- A stream that produces nothing for 300 s is aborted and retried. `TenantConfig.modelCall` sets attempts, backoff, the idle timeout and the request timeout.
|
|
125
|
+
- **Failures.** Anything else fails the turn with one of these codes:
|
|
126
|
+
|
|
127
|
+
- `model.context_overflow`, `model.rate_limited`, `model.overloaded`, `model.timeout`, `model.transient`
|
|
128
|
+
- `model.content_policy`, `model.auth` (whose message says where to fix the credential)
|
|
129
|
+
- `model.invalid_request`, `model.invalid_output`
|
|
130
|
+
|
|
131
|
+
Only a call whose outcome was lost, such as a Worker dying mid-call, is still `uncertain`.
|
|
132
|
+
|
|
133
|
+
- **Structured output.** A structured final answer is repaired (control characters, a Markdown code fence) before it is parsed.
|
|
134
|
+
- **Model history.** Replayed history keeps the model that produced each message, so a model switch no longer sends one model's signatures or tool-call ids to another. Reasoning from OpenAI-compatible servers (`reasoning_content`, `reasoning`) is sent back only within the turn that produced it.
|
|
135
|
+
|
|
136
|
+
- **Events.**
|
|
137
|
+
- `message.assistant` adds `model` (`provider`, `model`), `finishReason` and `usage`.
|
|
138
|
+
- A new `model.failed` transcript event (`code`, `message`, `retryable`) is written instead of `message.assistant` when a call fails.
|
|
139
|
+
- **Core and harness.**
|
|
140
|
+
- New types and helpers: `ModelFailureOutcome`, `ModelFailureCode`, `MODEL_FAILURE_CODES`, `isModelFailureOutcome`, `ModelProducer`.
|
|
141
|
+
- `PromptItem` assistant messages may carry `producer`.
|
|
142
|
+
- `ModelUsage` adds `cacheWriteTokens`.
|
|
143
|
+
- A model adapter may return a failure outcome.
|
|
144
|
+
- The durable engine version is `hosted-3`: a turn that is running when the Runtime is upgraded fails once with `execution.incompatible`, and the next message works.
|
|
145
|
+
- **CLI.**
|
|
146
|
+
- `nylo configure` passes a stable installation id to OAuth logins that need one (OpenAI "Sign in with ChatGPT"), stored as `cli-installation-id` in the Host root.
|
|
147
|
+
- A custom OpenAI-compatible provider now prompts for its API key instead of failing.
|
|
148
|
+
|
|
149
|
+
- Pin agents to the tested release.
|
|
150
|
+
- Pin admin to the tested release.
|
|
151
|
+
- Updated dependencies [c7614a4]
|
|
152
|
+
- Updated dependencies [5f23047]
|
|
153
|
+
- Updated dependencies [4282d5f]
|
|
154
|
+
- Updated dependencies [82d95ef]
|
|
155
|
+
- Updated dependencies [e28b8a9]
|
|
156
|
+
- Updated dependencies [50d0fb5]
|
|
157
|
+
- Updated dependencies [50d0fb5]
|
|
158
|
+
- Updated dependencies [c121144]
|
|
159
|
+
- Updated dependencies [50d0fb5]
|
|
160
|
+
- Updated dependencies [c121144]
|
|
161
|
+
- Updated dependencies [9546ac7]
|
|
162
|
+
- Updated dependencies [9d52189]
|
|
163
|
+
- Updated dependencies [9d52189]
|
|
164
|
+
- Updated dependencies [50d0fb5]
|
|
165
|
+
- Updated dependencies
|
|
166
|
+
- Updated dependencies
|
|
167
|
+
- @nylorun/agents@0.10.0-beta
|
|
168
|
+
- @nylorun/admin@0.6.0-beta
|
|
169
|
+
|
|
3
170
|
## 0.5.0-beta
|
|
4
171
|
|
|
5
172
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,84 +1,75 @@
|
|
|
1
1
|
# @nylorun/cli
|
|
2
2
|
|
|
3
|
-
The Runtime client, command `nylo`: it acts on
|
|
4
|
-
stack
|
|
5
|
-
local stack is [`nylorun`](../nylorun/README.md)'s job; the two
|
|
6
|
-
independent and never call each other. Depends on
|
|
7
|
-
`@nylorun/admin` only among Nylorun packages. Vocabulary:
|
|
3
|
+
The Runtime client, command `nylo`: it acts on the one Tenant of an
|
|
4
|
+
installation, a local stack or any Runtime reachable by URL and key. Setting up
|
|
5
|
+
and running the local stack is [`nylorun`](../nylorun/README.md)'s job; the two
|
|
6
|
+
packages are independent and never call each other. Depends on
|
|
7
|
+
`@nylorun/agents` and `@nylorun/admin` only among Nylorun packages. Vocabulary:
|
|
8
8
|
[runtime/src/CONTEXT.md](../runtime/src/CONTEXT.md).
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
|
-
npx nylorun
|
|
12
|
-
npx @nylorun/cli
|
|
13
|
-
npx @nylorun/cli tenant use <id> # or: link a Tenant created in Studio
|
|
11
|
+
npx nylorun start # in the project: its stack, its Tenant and the Project link
|
|
12
|
+
npx @nylorun/cli status # the linked Tenant
|
|
14
13
|
```
|
|
15
14
|
|
|
16
15
|
## Commands
|
|
17
16
|
|
|
18
17
|
```sh
|
|
19
|
-
nylo
|
|
20
|
-
nylo
|
|
21
|
-
nylo
|
|
18
|
+
nylo status [--json] # the Tenant, its checks and counts, and the link's stack
|
|
19
|
+
nylo reset [--sessions|--sandboxes|--all] [--yes]
|
|
20
|
+
nylo endpoints [--json]|ping <agent> # the registered Action endpoints and their health
|
|
21
|
+
nylo access … # access policy, publishable and signing keys, subject tokens
|
|
22
|
+
nylo configure # set or replace the Tenant's model provider
|
|
22
23
|
nylo env # export lines for the linked Project
|
|
23
24
|
nylo doctor sandbox [--json] # sandbox backend via the Tenant API
|
|
24
25
|
```
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
`npm run dev` (`tsx watch src/main.ts`).
|
|
27
|
+
Every command acts on the linked installation: the Project link and
|
|
28
|
+
credentials (below), or `NYLORUN_RUNTIME_URL` and `NYLORUN_SERVER_KEY` when the
|
|
29
|
+
Project has no link. An installation serves one Tenant, so nothing selects it.
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Local stack commands (`up`, `down`, `start`, `stop`, `logs`, `studio`) exit 2
|
|
32
|
+
naming `npx nylorun <command>`. `nylo tenant …` exits 2: `npx nylorun start`
|
|
33
|
+
creates the stack, its Tenant and the link, and `nylo status|reset|endpoints`
|
|
34
|
+
replace `nylo tenant status|reset|endpoints`. `nylorun dev` was removed: run
|
|
35
|
+
`npx nylorun start` once, then the project's own `npm run dev`
|
|
36
|
+
(`tsx watch src/main.ts`).
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
`NYLORUN_ADMIN_KEY`, else from the local Host root (`NYLORUN_HOME` or
|
|
35
|
-
`~/.nylorun`: `host.json` and the admin key that `nylorun up` wrote). With no
|
|
36
|
-
Runtime answering, it exits 6 and names `npx nylorun up`.
|
|
38
|
+
## `nylo status`
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
Reads the Tenant API status (`GET /v1/tenant`) and prints the Tenant, the
|
|
41
|
+
stack the link names, the Runtime URL, the checks, the counts and the sandbox
|
|
42
|
+
backend. When the Tenant is not open it does not answer; `nylo status` then
|
|
43
|
+
asks the Admin API (`/v1/admin/status`, through the local stack's Host root or
|
|
44
|
+
`NYLORUN_ADMIN_URL` and `NYLORUN_ADMIN_KEY`) and prints why, with the repair.
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
2. Writes the format-1 link and credentials (see below). A Project that is
|
|
42
|
-
already linked is refused: use `nylo tenant use` or `nylo tenant delete`.
|
|
43
|
-
3. Seeds the Tenant from `.env`: `NYLORUN_SANDBOX`, and the model provider from
|
|
44
|
-
`MODEL_PROVIDER`, `MODEL`, `MODEL_PROVIDER_API_KEY` (or a credential in
|
|
45
|
-
`.nylorun/auth.json`) into the Tenant vault. Without them it says to set the
|
|
46
|
-
provider in Studio or with `nylo configure`.
|
|
46
|
+
## `nylo reset`
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
## `nylo tenant use <name-or-id>`
|
|
52
|
-
|
|
53
|
-
Links the Project to another Tenant on the local Host. It uses the first key
|
|
54
|
-
that the Tenant accepts:
|
|
55
|
-
|
|
56
|
-
1. The Project's `.nylorun/credentials.json`.
|
|
57
|
-
2. A key it kept when the Project last left that Tenant
|
|
58
|
-
(`.nylorun/credentials.<tenantId>.json`).
|
|
59
|
-
3. The key of the derived principal `project`, computed from this machine's
|
|
60
|
-
admin key. Every Tenant created in Studio registers that principal, so
|
|
61
|
-
Studio's **Connect your code** step needs only this command.
|
|
62
|
-
|
|
63
|
-
When it replaces an application key (shown only once, when the Tenant was
|
|
64
|
-
created), it keeps that key as `.nylorun/credentials.<tenantId>.json`, so
|
|
65
|
-
`nylo tenant use <that id>` switches back.
|
|
48
|
+
Clears the Tenant's sessions (the default), its sandboxes, or all its data
|
|
49
|
+
(`--all`), after draining work in flight. `--all` asks first; pass `--yes` when
|
|
50
|
+
not in a terminal. The Project link and credentials are kept.
|
|
66
51
|
|
|
67
52
|
## Project link
|
|
68
53
|
|
|
69
|
-
A **Project** stores only:
|
|
54
|
+
`npx nylorun start` writes it; `nylo` only reads it. A **Project** stores only:
|
|
70
55
|
|
|
71
|
-
- `.nylorun/link.json`: `{ format, hostUrl, hostId, tenantId }`
|
|
72
|
-
|
|
73
|
-
|
|
56
|
+
- `.nylorun/link.json`: `{ format: 2, stack, hostUrl, hostId, tenantId }`
|
|
57
|
+
(`tenantId` is information)
|
|
58
|
+
- `.nylorun/credentials.json`: the key of the derived principal `project` and
|
|
59
|
+
its id (0600)
|
|
74
60
|
- `.nylorun/.gitignore` containing `*`
|
|
75
61
|
|
|
76
|
-
|
|
77
|
-
|
|
62
|
+
A format 0 or 1 link named a Tenant on an older multi-Tenant Host: `nylo`
|
|
63
|
+
refuses it and says to run `npx nylorun start`, which starts the project's own
|
|
64
|
+
stack and links it again.
|
|
65
|
+
|
|
66
|
+
`createActionHandler` and `createClient` in `@nylorun/agents` read the link (or
|
|
67
|
+
the two variables), so the project's `npm run dev` and `npm start` need no
|
|
68
|
+
Nylorun tool.
|
|
78
69
|
|
|
79
70
|
```sh
|
|
80
71
|
eval "$(npx @nylorun/cli env)"
|
|
81
|
-
# → NYLORUN_RUNTIME_URL, NYLORUN_SERVER_KEY
|
|
72
|
+
# → NYLORUN_RUNTIME_URL, NYLORUN_SERVER_KEY
|
|
82
73
|
```
|
|
83
74
|
|
|
84
75
|
## Exit codes
|
|
@@ -95,8 +86,9 @@ eval "$(npx @nylorun/cli env)"
|
|
|
95
86
|
|
|
96
87
|
| Symptom | What to do |
|
|
97
88
|
| --- | --- |
|
|
98
|
-
| No Runtime answers | `npx nylorun
|
|
99
|
-
|
|
|
89
|
+
| No Runtime answers | `npx nylorun start`, then `npx nylorun status` |
|
|
90
|
+
| Tenant not open | `nylo status` shows the cause and its `repair` |
|
|
91
|
+
| Old Project link refused | `npx nylorun start` in the project |
|
|
100
92
|
| `426` from the Runtime | Upgrade the CLI, or pin a matching older set |
|
|
101
93
|
|
|
102
94
|
See [MIGRATION.md](../MIGRATION.md).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type AgentsClient } from "@nylorun/agents";
|
|
2
|
+
export declare const accessUsage = "nylo access <policy|keys|signing-keys|revoke|token>\n\n policy get print the access policy\n policy set <file> replace it with a JSON file\n policy init write a starter \"user\" role (sessions:own agents:read, every agent,\n 60 turns per hour, 2 at once)\n signing-keys list list the signing keys\n signing-keys rotate [--force] rotate; --force signs outstanding tokens out\n signing-keys revoke <kid> revoke a previous or standby key\n keys list list the publishable keys\n keys create --name <n> [--origin <o>]\u2026\n a publishable key for a web page or an app\n (origins: https://app.example.com or http://localhost:*)\n keys set-origins <id> [<o>\u2026] replace a key's origins ([] for native apps only)\n keys revoke <id> revoke a publishable key\n revoke <subject> end a subject's tokens and open streams\n token --subject <s> --role <r> [--ttl <seconds>]\n mint a subject token (for trying the API with curl)";
|
|
3
|
+
/** The starter policy `policy init` writes. */
|
|
4
|
+
export declare const STARTER_POLICY: {
|
|
5
|
+
version: 1;
|
|
6
|
+
roles: {
|
|
7
|
+
user: {
|
|
8
|
+
scopes: ("agents:read" | "sessions:own")[];
|
|
9
|
+
agents: "*";
|
|
10
|
+
limits: {
|
|
11
|
+
turnsPerHour: number;
|
|
12
|
+
concurrentTurns: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
anon: {
|
|
17
|
+
scopes: never[];
|
|
18
|
+
agents: never[];
|
|
19
|
+
};
|
|
20
|
+
tokens: {
|
|
21
|
+
maxTtlSeconds: number;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare function accessCommand(input: readonly string[], client?: () => Promise<AgentsClient>): Promise<void>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nylo access`: the linked Tenant's access policy, signing keys and revocations, and a
|
|
3
|
+
* development command that mints a subject token (Host feature `subject-tokens`). Uses the
|
|
4
|
+
* Project's application key, like every other Tenant command.
|
|
5
|
+
*/
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
import { createClient, resolveConnection, } from "@nylorun/agents";
|
|
8
|
+
import { CliError } from "../errors.js";
|
|
9
|
+
export const accessUsage = `nylo access <policy|keys|signing-keys|revoke|token>
|
|
10
|
+
|
|
11
|
+
policy get print the access policy
|
|
12
|
+
policy set <file> replace it with a JSON file
|
|
13
|
+
policy init write a starter "user" role (sessions:own agents:read, every agent,
|
|
14
|
+
60 turns per hour, 2 at once)
|
|
15
|
+
signing-keys list list the signing keys
|
|
16
|
+
signing-keys rotate [--force] rotate; --force signs outstanding tokens out
|
|
17
|
+
signing-keys revoke <kid> revoke a previous or standby key
|
|
18
|
+
keys list list the publishable keys
|
|
19
|
+
keys create --name <n> [--origin <o>]…
|
|
20
|
+
a publishable key for a web page or an app
|
|
21
|
+
(origins: https://app.example.com or http://localhost:*)
|
|
22
|
+
keys set-origins <id> [<o>…] replace a key's origins ([] for native apps only)
|
|
23
|
+
keys revoke <id> revoke a publishable key
|
|
24
|
+
revoke <subject> end a subject's tokens and open streams
|
|
25
|
+
token --subject <s> --role <r> [--ttl <seconds>]
|
|
26
|
+
mint a subject token (for trying the API with curl)`;
|
|
27
|
+
/** The starter policy `policy init` writes. */
|
|
28
|
+
export const STARTER_POLICY = {
|
|
29
|
+
version: 1,
|
|
30
|
+
roles: {
|
|
31
|
+
user: {
|
|
32
|
+
scopes: ["sessions:own", "agents:read"],
|
|
33
|
+
agents: "*",
|
|
34
|
+
limits: { turnsPerHour: 60, concurrentTurns: 2 },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
anon: { scopes: [], agents: [] },
|
|
38
|
+
tokens: { maxTtlSeconds: 600 },
|
|
39
|
+
};
|
|
40
|
+
const usageError = (message = accessUsage) => new CliError(message, 2);
|
|
41
|
+
async function linkedClient() {
|
|
42
|
+
let connection;
|
|
43
|
+
try {
|
|
44
|
+
connection = await resolveConnection();
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw new CliError(error instanceof Error ? error.message : String(error), 1);
|
|
48
|
+
}
|
|
49
|
+
return createClient({ url: connection.url, key: connection.key });
|
|
50
|
+
}
|
|
51
|
+
const print = (value) => console.log(JSON.stringify(value, null, 2));
|
|
52
|
+
function option(args, name) {
|
|
53
|
+
const index = args.indexOf(name);
|
|
54
|
+
if (index === -1)
|
|
55
|
+
return undefined;
|
|
56
|
+
const value = args[index + 1];
|
|
57
|
+
if (!value || value.startsWith("--"))
|
|
58
|
+
throw usageError(`${name} requires a value.`);
|
|
59
|
+
args.splice(index, 2);
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
export async function accessCommand(input, client = linkedClient) {
|
|
63
|
+
const [topic, action, ...rest] = input;
|
|
64
|
+
const args = [...rest];
|
|
65
|
+
if (topic === "policy") {
|
|
66
|
+
if (action === "get" && args.length === 0)
|
|
67
|
+
return print(await (await client()).access.getPolicy());
|
|
68
|
+
if (action === "init" && args.length === 0)
|
|
69
|
+
return print(await (await client()).access.putPolicy(STARTER_POLICY));
|
|
70
|
+
if (action === "set" && args.length === 1) {
|
|
71
|
+
let parsed;
|
|
72
|
+
try {
|
|
73
|
+
parsed = JSON.parse(await readFile(args[0], "utf8"));
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new CliError(`Could not read ${args[0]}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
77
|
+
}
|
|
78
|
+
// Accept the file as the policy itself or as `{ policy }`, as `policy get` prints it.
|
|
79
|
+
const candidate = parsed && typeof parsed === "object" && "policy" in parsed
|
|
80
|
+
? parsed.policy
|
|
81
|
+
: parsed;
|
|
82
|
+
// The Runtime validates it and names what is wrong.
|
|
83
|
+
return print(await (await client()).access.putPolicy(candidate));
|
|
84
|
+
}
|
|
85
|
+
throw usageError();
|
|
86
|
+
}
|
|
87
|
+
if (topic === "signing-keys") {
|
|
88
|
+
const keys = async () => (await client()).access.signingKeys;
|
|
89
|
+
if (action === "list" && args.length === 0)
|
|
90
|
+
return print(await (await keys()).list());
|
|
91
|
+
if (action === "rotate") {
|
|
92
|
+
const force = args[0] === "--force";
|
|
93
|
+
if (args.length > (force ? 1 : 0))
|
|
94
|
+
throw usageError();
|
|
95
|
+
return print(await (await keys()).rotate({ force }));
|
|
96
|
+
}
|
|
97
|
+
if (action === "revoke" && args.length === 1)
|
|
98
|
+
return print(await (await keys()).revoke(args[0]));
|
|
99
|
+
throw usageError();
|
|
100
|
+
}
|
|
101
|
+
if (topic === "keys") {
|
|
102
|
+
const keys = async () => (await client()).access.publishableKeys;
|
|
103
|
+
if (action === "list" && args.length === 0)
|
|
104
|
+
return print(await (await keys()).list());
|
|
105
|
+
if (action === "create") {
|
|
106
|
+
const name = option(args, "--name");
|
|
107
|
+
const origins = [];
|
|
108
|
+
for (let origin = option(args, "--origin"); origin; origin = option(args, "--origin"))
|
|
109
|
+
origins.push(origin);
|
|
110
|
+
if (!name || args.length > 0)
|
|
111
|
+
throw usageError();
|
|
112
|
+
return print(await (await keys()).create({ name, origins }));
|
|
113
|
+
}
|
|
114
|
+
if (action === "set-origins" && args.length >= 1) {
|
|
115
|
+
const [keyId, ...origins] = args;
|
|
116
|
+
return print(await (await keys()).update(keyId, { origins }));
|
|
117
|
+
}
|
|
118
|
+
if (action === "revoke" && args.length === 1)
|
|
119
|
+
return print(await (await keys()).revoke(args[0]));
|
|
120
|
+
throw usageError();
|
|
121
|
+
}
|
|
122
|
+
if (topic === "revoke") {
|
|
123
|
+
if (!action || args.length > 0)
|
|
124
|
+
throw usageError();
|
|
125
|
+
return print(await (await client()).access.revokeSubject(action));
|
|
126
|
+
}
|
|
127
|
+
if (topic === "token") {
|
|
128
|
+
const all = [action, ...args].filter((arg) => arg !== undefined);
|
|
129
|
+
const subject = option(all, "--subject");
|
|
130
|
+
const role = option(all, "--role");
|
|
131
|
+
const ttl = option(all, "--ttl");
|
|
132
|
+
if (!subject || !role || all.length > 0)
|
|
133
|
+
throw usageError();
|
|
134
|
+
const ttlSeconds = ttl === undefined ? undefined : Number(ttl);
|
|
135
|
+
if (ttlSeconds !== undefined && !Number.isInteger(ttlSeconds))
|
|
136
|
+
throw usageError("--ttl must be a whole number of seconds.");
|
|
137
|
+
return print(await (await client()).tokens.create({
|
|
138
|
+
subject,
|
|
139
|
+
role,
|
|
140
|
+
...(ttlSeconds === undefined ? {} : { ttlSeconds }),
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
throw usageError();
|
|
144
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -5,24 +5,35 @@ import { putHostModel } from "./model/host-model.js";
|
|
|
5
5
|
import { CliError } from "./errors.js";
|
|
6
6
|
import { findProjectRoot } from "./project/root.js";
|
|
7
7
|
import { printLinkedEnvExports } from "./project/env.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
const usage = `nylo <
|
|
8
|
+
import { linkedConnection } from "./project/connection.js";
|
|
9
|
+
import { accessCommand } from "./access/commands.js";
|
|
10
|
+
import { endpointsCommand, resetCommand, statusCommand, } from "./installation/commands.js";
|
|
11
|
+
const usage = `nylo <status|reset|endpoints|access|configure|env|doctor>
|
|
12
12
|
|
|
13
|
-
Runtime client
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
Runtime client for the linked installation and its one Tenant (the Project link that
|
|
14
|
+
npx nylorun start writes, or NYLORUN_RUNTIME_URL and NYLORUN_SERVER_KEY):
|
|
15
|
+
status [--json] the Tenant, its checks and counts, and the stack
|
|
16
|
+
reset [--sessions|--sandboxes|--all] [--yes]
|
|
17
|
+
clear the Tenant's sessions, sandboxes or all its data
|
|
18
|
+
endpoints [--json]|ping <agent> the registered Action endpoints and their health
|
|
19
|
+
access policy get|set <file>|init the access policy for subject tokens (nylo access --help)
|
|
20
|
+
access keys list|create|set-origins|revoke publishable keys for web pages and apps
|
|
21
|
+
access signing-keys list|rotate|revoke the Tenant's token signing keys
|
|
22
|
+
access revoke <subject> end a subject's tokens and open streams
|
|
23
|
+
access token --subject <s> --role <r> mint a subject token for trying the API
|
|
17
24
|
configure set the linked Tenant's model provider
|
|
18
25
|
env print the linked Project's NYLORUN_* variables as exports
|
|
19
26
|
doctor sandbox [--json] show which sandbox backend this Tenant's Host offers
|
|
20
27
|
|
|
21
|
-
The local stack is managed by the nylorun package: npx nylorun
|
|
28
|
+
The local stack is managed by the nylorun package: npx nylorun start in a project creates
|
|
29
|
+
its stack, its Tenant and the Project link.`;
|
|
22
30
|
/** Local stack commands, which moved to the nylorun package. */
|
|
23
31
|
const STACK_COMMANDS = new Set([
|
|
24
|
-
"up", "down", "start", "stop", "
|
|
32
|
+
"up", "down", "start", "stop", "logs", "studio", "stack", "runtime", "restart", "run",
|
|
25
33
|
]);
|
|
34
|
+
const TENANT_REMOVED = `nylo tenant was removed: an installation serves one Tenant.
|
|
35
|
+
Run "npx nylorun start" in your project to create its stack, its Tenant and the Project link.
|
|
36
|
+
Then use nylo status, nylo reset and nylo endpoints on the linked installation.`;
|
|
26
37
|
function parseFlags(args, allowed = {}) {
|
|
27
38
|
const booleans = new Set();
|
|
28
39
|
const values = new Map();
|
|
@@ -58,25 +69,6 @@ function parseFlags(args, allowed = {}) {
|
|
|
58
69
|
return { rest, booleans, values };
|
|
59
70
|
}
|
|
60
71
|
const usageError = (message) => new CliError(message, 2);
|
|
61
|
-
async function resolveLinkedAuth(projectRoot) {
|
|
62
|
-
const link = await readProjectLink(projectRoot);
|
|
63
|
-
const credentials = await readProjectCredentials(projectRoot);
|
|
64
|
-
if (link && credentials) {
|
|
65
|
-
return {
|
|
66
|
-
url: link.hostUrl,
|
|
67
|
-
key: credentials.applicationKey,
|
|
68
|
-
tenantId: link.tenantId,
|
|
69
|
-
tenantName: link.tenantId,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
const url = process.env.NYLORUN_RUNTIME_URL?.trim();
|
|
73
|
-
const key = process.env.NYLORUN_SERVER_KEY?.trim();
|
|
74
|
-
const tenantId = process.env.NYLORUN_TENANT?.trim();
|
|
75
|
-
if (url && key && tenantId) {
|
|
76
|
-
return { url, key, tenantId, tenantName: tenantId };
|
|
77
|
-
}
|
|
78
|
-
throw new CliError(`No Project link in ${projectRoot}. Run nylo tenant create, or set NYLORUN_RUNTIME_URL, NYLORUN_SERVER_KEY and NYLORUN_TENANT.`, 1);
|
|
79
|
-
}
|
|
80
72
|
async function main() {
|
|
81
73
|
const [command, ...args] = process.argv.slice(2);
|
|
82
74
|
if (!command || command === "--help" || command === "-h")
|
|
@@ -84,7 +76,20 @@ async function main() {
|
|
|
84
76
|
if (process.platform === "win32")
|
|
85
77
|
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);
|
|
86
78
|
if (command === "tenant")
|
|
87
|
-
|
|
79
|
+
throw usageError(TENANT_REMOVED);
|
|
80
|
+
if (command === "status")
|
|
81
|
+
return await statusCommand(args);
|
|
82
|
+
if (command === "reset")
|
|
83
|
+
return await resetCommand(args);
|
|
84
|
+
if (command === "endpoints")
|
|
85
|
+
return await endpointsCommand(args);
|
|
86
|
+
if (command === "access") {
|
|
87
|
+
if (args[0] === "--help" || args[0] === "-h" || args.length === 0) {
|
|
88
|
+
const { accessUsage } = await import("./access/commands.js");
|
|
89
|
+
return void console.log(accessUsage);
|
|
90
|
+
}
|
|
91
|
+
return await accessCommand(args);
|
|
92
|
+
}
|
|
88
93
|
if (command === "env") {
|
|
89
94
|
if (args.length)
|
|
90
95
|
throw usageError("Usage: nylo env");
|
|
@@ -100,7 +105,7 @@ async function main() {
|
|
|
100
105
|
return;
|
|
101
106
|
}
|
|
102
107
|
if (command === "dev")
|
|
103
|
-
throw usageError(
|
|
108
|
+
throw usageError('nylorun dev was removed: run "npx nylorun start" once in your project, then your project\'s npm run dev.');
|
|
104
109
|
if (STACK_COMMANDS.has(command))
|
|
105
110
|
throw usageError(`The local stack moved to the nylorun package: npx nylorun ${command}`);
|
|
106
111
|
if (command === "configure") {
|
|
@@ -108,24 +113,20 @@ async function main() {
|
|
|
108
113
|
if (flags.rest.length)
|
|
109
114
|
throw usageError(usage);
|
|
110
115
|
const projectRoot = findProjectRoot() ?? process.cwd();
|
|
111
|
-
const auth = await
|
|
116
|
+
const auth = await linkedConnection(projectRoot);
|
|
112
117
|
const controller = new AbortController();
|
|
113
118
|
const cancel = (signal) => controller.abort(new ConfigurationCancelled(signal));
|
|
114
119
|
process.once("SIGINT", () => cancel("SIGINT"));
|
|
115
120
|
process.once("SIGTERM", () => cancel("SIGTERM"));
|
|
116
121
|
const health = await fetch(`${auth.url}/health`).catch(() => undefined);
|
|
117
122
|
if (!health?.ok)
|
|
118
|
-
throw new CliError(`No Runtime is listening at ${auth.url}. Start the local stack with "npx nylorun
|
|
119
|
-
const catalog = await fetchModelCatalog({
|
|
120
|
-
url: auth.url,
|
|
121
|
-
key: auth.key,
|
|
122
|
-
tenantId: auth.tenantId,
|
|
123
|
-
});
|
|
123
|
+
throw new CliError(`No Runtime is listening at ${auth.url}. Start the local stack with "npx nylorun start".`, 6);
|
|
124
|
+
const catalog = await fetchModelCatalog({ url: auth.url, key: auth.key });
|
|
124
125
|
const prompted = await configureProvider({
|
|
125
126
|
signal: controller.signal,
|
|
126
127
|
catalog,
|
|
127
128
|
});
|
|
128
|
-
await putHostModel(auth.url, auth.key, prompted
|
|
129
|
+
await putHostModel(auth.url, auth.key, prompted);
|
|
129
130
|
return;
|
|
130
131
|
}
|
|
131
132
|
throw usageError(usage);
|