@nylorun/cli 0.4.2-beta → 0.5.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 +14 -0
- package/README.md +17 -0
- package/dist/cli.js +2 -1
- package/dist/project/credentials.d.ts +4 -3
- package/dist/project/credentials.js +7 -6
- package/dist/project/link.d.ts +5 -1
- package/dist/project/link.js +6 -2
- package/dist/tenant/commands.js +38 -14
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @nylorun/cli
|
|
2
2
|
|
|
3
|
+
## 0.5.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- db956bc: Studio creates Tenants. While the Host has none, Studio asks for a name and creates the first one. A Tenant with no agents shows **Connect your code**: its model provider, the `npx @nylorun/cli tenant use <id>` command, and `npm run dev`. It switches to the agent list when the first agent registers.
|
|
8
|
+
|
|
9
|
+
Every Tenant Studio creates registers the derived principal `project` (`PROJECT_PRINCIPAL_ID` in `@nylorun/admin`). `nylo tenant use` now falls back to that key, derived from the local admin key, so a Project links a Studio-created Tenant with no stored key. When it replaces a one-time application key, it keeps that key as `.nylorun/credentials.<tenantId>.json`, and `nylo tenant use <that id>` switches back. `nylorun up` again offers Studio for creating the first Tenant.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Pin admin to the tested release.
|
|
14
|
+
- Updated dependencies [db956bc]
|
|
15
|
+
- @nylorun/admin@0.5.0-beta
|
|
16
|
+
|
|
3
17
|
## 0.4.2-beta
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ independent and never call each other. Depends on `@nylorun/agents` and
|
|
|
10
10
|
```sh
|
|
11
11
|
npx nylorun up # the local stack (nylorun)
|
|
12
12
|
npx @nylorun/cli tenant create # this project's Tenant, linked in .nylorun/
|
|
13
|
+
npx @nylorun/cli tenant use <id> # or: link a Tenant created in Studio
|
|
13
14
|
```
|
|
14
15
|
|
|
15
16
|
## Commands
|
|
@@ -47,6 +48,22 @@ Inside a Project (the nearest `.nylorun/` or `package.json`):
|
|
|
47
48
|
Outside a Project it creates the Tenant and prints the three `NYLORUN_*`
|
|
48
49
|
exports once; the Host keeps only a hash of the application key.
|
|
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.
|
|
66
|
+
|
|
50
67
|
## Project link
|
|
51
68
|
|
|
52
69
|
A **Project** stores only:
|
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,8 @@ const usage = `nylo <tenant|configure|env|doctor>
|
|
|
12
12
|
|
|
13
13
|
Runtime client (the local stack's Runtime, or any Runtime by URL and key):
|
|
14
14
|
tenant create [name] create a Tenant; in a Project, link it and seed it from .env
|
|
15
|
-
tenant
|
|
15
|
+
tenant use <name-or-id> link this Project to a Tenant, e.g. one created in Studio
|
|
16
|
+
tenant current|list [--json]|status [--json]|reset|delete
|
|
16
17
|
configure set the linked Tenant's model provider
|
|
17
18
|
env print the linked Project's NYLORUN_* variables as exports
|
|
18
19
|
doctor sandbox [--json] show which sandbox backend this Tenant's Host offers
|
|
@@ -9,10 +9,11 @@ export interface ProjectCredentials {
|
|
|
9
9
|
/** Present only on format 0 files; ignored by version 1. */
|
|
10
10
|
executors?: Record<string, string>;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
/** The Project's credentials, or with `tenantId` the key kept for that Tenant. */
|
|
13
|
+
export declare function readCredentials(projectRoot: string, tenantId?: string): Promise<ProjectCredentials | undefined>;
|
|
13
14
|
export declare function writeCredentials(projectRoot: string, credentials: {
|
|
14
15
|
applicationKey: string;
|
|
15
16
|
principalId: string;
|
|
16
17
|
format?: 0 | 1;
|
|
17
|
-
}): Promise<void>;
|
|
18
|
-
export declare function removeCredentials(projectRoot: string): Promise<void>;
|
|
18
|
+
}, tenantId?: string): Promise<void>;
|
|
19
|
+
export declare function removeCredentials(projectRoot: string, tenantId?: string): Promise<void>;
|
|
@@ -2,8 +2,9 @@ import { chmod, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { CliError } from "../errors.js";
|
|
4
4
|
import { credentialsPath, ensureProjectNylorunDir, } from "./link.js";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/** The Project's credentials, or with `tenantId` the key kept for that Tenant. */
|
|
6
|
+
export async function readCredentials(projectRoot, tenantId) {
|
|
7
|
+
const path = credentialsPath(projectRoot, tenantId);
|
|
7
8
|
try {
|
|
8
9
|
const value = JSON.parse(await readFile(path, "utf8"));
|
|
9
10
|
if (typeof value?.applicationKey !== "string" ||
|
|
@@ -40,9 +41,9 @@ export async function readCredentials(projectRoot) {
|
|
|
40
41
|
throw error;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
export async function writeCredentials(projectRoot, credentials) {
|
|
44
|
+
export async function writeCredentials(projectRoot, credentials, tenantId) {
|
|
44
45
|
await ensureProjectNylorunDir(projectRoot);
|
|
45
|
-
const path = credentialsPath(projectRoot);
|
|
46
|
+
const path = credentialsPath(projectRoot, tenantId);
|
|
46
47
|
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
47
48
|
// Version 1 writes format 1 without executors (D§3.7).
|
|
48
49
|
const body = `${JSON.stringify({
|
|
@@ -59,6 +60,6 @@ export async function writeCredentials(projectRoot, credentials) {
|
|
|
59
60
|
await rm(temporary, { force: true });
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
|
-
export async function removeCredentials(projectRoot) {
|
|
63
|
-
await rm(credentialsPath(projectRoot), { force: true });
|
|
63
|
+
export async function removeCredentials(projectRoot, tenantId) {
|
|
64
|
+
await rm(credentialsPath(projectRoot, tenantId), { force: true });
|
|
64
65
|
}
|
package/dist/project/link.d.ts
CHANGED
|
@@ -7,7 +7,11 @@ export interface ProjectLink {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function nylorunDir(projectRoot: string): string;
|
|
9
9
|
export declare function linkPath(projectRoot: string): string;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* `.nylorun/credentials.json`, or with `tenantId` the key `nylo tenant use`
|
|
12
|
+
* kept for a Tenant the Project was linked to before (`credentials.<id>.json`).
|
|
13
|
+
*/
|
|
14
|
+
export declare function credentialsPath(projectRoot: string, tenantId?: string): string;
|
|
11
15
|
/**
|
|
12
16
|
* Create `.nylorun/` mode 0700 with a private `.gitignore` containing `*`.
|
|
13
17
|
* The Project's own `.gitignore` is never edited.
|
package/dist/project/link.js
CHANGED
|
@@ -9,8 +9,12 @@ export function nylorunDir(projectRoot) {
|
|
|
9
9
|
export function linkPath(projectRoot) {
|
|
10
10
|
return join(nylorunDir(projectRoot), "link.json");
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* `.nylorun/credentials.json`, or with `tenantId` the key `nylo tenant use`
|
|
14
|
+
* kept for a Tenant the Project was linked to before (`credentials.<id>.json`).
|
|
15
|
+
*/
|
|
16
|
+
export function credentialsPath(projectRoot, tenantId) {
|
|
17
|
+
return join(nylorunDir(projectRoot), tenantId === undefined ? "credentials.json" : `credentials.${tenantId}.json`);
|
|
14
18
|
}
|
|
15
19
|
/**
|
|
16
20
|
* Create `.nylorun/` mode 0700 with a private `.gitignore` containing `*`.
|
package/dist/tenant/commands.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { createAdmin } from "@nylorun/admin";
|
|
3
|
+
import { PROJECT_PRINCIPAL_ID, createAdmin, } from "@nylorun/admin";
|
|
4
4
|
import { createClient, isTenantId } from "@nylorun/agents";
|
|
5
5
|
import { CliError } from "../errors.js";
|
|
6
6
|
import { resolveHome } from "../home.js";
|
|
7
|
-
import { readCredentials, removeCredentials, } from "../project/credentials.js";
|
|
7
|
+
import { readCredentials, removeCredentials, writeCredentials, } from "../project/credentials.js";
|
|
8
8
|
import { readLink, removeLink, writeLink, } from "../project/link.js";
|
|
9
9
|
import { findProjectRoot, requireProjectRoot } from "../project/root.js";
|
|
10
10
|
import { createProjectTenant, defaultTenantName, } from "../project/create-tenant.js";
|
|
@@ -144,20 +144,44 @@ export async function tenantCommand(args) {
|
|
|
144
144
|
const tenants = await admin.listTenants();
|
|
145
145
|
const selected = matchTenant(tenants, nameOrId);
|
|
146
146
|
console.warn("Sharing a Tenant shares executor registrations across Projects that link to it.");
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
const authorizes = async (key) => {
|
|
148
|
+
try {
|
|
149
|
+
await createClient({ url: admin.url, key, tenant: selected.id }).transport.json("/v1/tenant", "GET");
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const link = await readLink(root);
|
|
157
|
+
const current = await readCredentials(root);
|
|
158
|
+
const kept = await readCredentials(root, selected.id);
|
|
159
|
+
// The Project's own key, then one kept when it last left this Tenant, then
|
|
160
|
+
// the key derived from this machine's admin key (Tenants Studio creates).
|
|
161
|
+
let chosen;
|
|
162
|
+
for (const candidate of [current, kept])
|
|
163
|
+
if (!chosen && candidate && (await authorizes(candidate.applicationKey)))
|
|
164
|
+
chosen = candidate;
|
|
165
|
+
if (!chosen) {
|
|
166
|
+
const derived = admin.deriveTenantKey(selected.id, PROJECT_PRINCIPAL_ID);
|
|
167
|
+
if (await authorizes(derived))
|
|
168
|
+
chosen = { format: 1, applicationKey: derived, principalId: PROJECT_PRINCIPAL_ID };
|
|
150
169
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
key: credentials.applicationKey,
|
|
154
|
-
tenant: selected.id,
|
|
155
|
-
});
|
|
156
|
-
try {
|
|
157
|
-
await client.transport.json("/v1/tenant", "GET");
|
|
170
|
+
if (!chosen) {
|
|
171
|
+
throw new CliError(`No key of this Project authorizes Tenant ${selected.id}, and it has no derived "${PROJECT_PRINCIPAL_ID}" principal (Tenants created in Studio have one). Link a Tenant created in Studio, or create one with nylo tenant create.`, 1);
|
|
158
172
|
}
|
|
159
|
-
|
|
160
|
-
|
|
173
|
+
if (chosen !== current) {
|
|
174
|
+
// An application key is shown only once: keep the one being replaced.
|
|
175
|
+
if (current &&
|
|
176
|
+
link &&
|
|
177
|
+
link.tenantId !== selected.id &&
|
|
178
|
+
current.principalId !== PROJECT_PRINCIPAL_ID) {
|
|
179
|
+
await writeCredentials(root, current, link.tenantId);
|
|
180
|
+
console.warn(`Kept the key for Tenant ${link.tenantId} in .nylorun/credentials.${link.tenantId}.json; nylo tenant use ${link.tenantId} switches back.`);
|
|
181
|
+
}
|
|
182
|
+
await writeCredentials(root, chosen);
|
|
183
|
+
if (chosen === kept)
|
|
184
|
+
await removeCredentials(root, selected.id);
|
|
161
185
|
}
|
|
162
186
|
await writeLink(root, {
|
|
163
187
|
format: 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-beta",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Nylorun Runtime client: Tenants, Project links and model providers",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@nylorun/agents": "0.9.0-beta",
|
|
34
|
-
"@nylorun/admin": "0.
|
|
34
|
+
"@nylorun/admin": "0.5.0-beta",
|
|
35
35
|
"@earendil-works/pi-ai": "0.87.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|