@nylorun/agents 0.10.0-beta → 0.12.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 +53 -0
- package/README.md +24 -22
- package/dist/a2a/handler.js +1 -1
- package/dist/action-handler.d.ts +0 -1
- package/dist/action-handler.js +5 -9
- package/dist/ag-ui/handler.js +1 -1
- package/dist/client.js +1 -4
- package/dist/connection.d.ts +4 -3
- package/dist/connection.js +14 -18
- package/dist/delivery-token.d.ts +7 -2
- package/dist/delivery-token.js +12 -3
- package/dist/http.d.ts +5 -4
- package/dist/http.js +1 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# @nylorun/agents
|
|
2
2
|
|
|
3
|
+
## 0.12.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4b9906f: **Breaking: "Tenant" replaces "stack", and `nylorun start` works anywhere.** Each local installation holds one Tenant, and its name is the Tenant's name, so help, output, errors and docs say Tenant. See MIGRATION.md.
|
|
8
|
+
|
|
9
|
+
- **Breaking (`nylorun`): selection.** Every command acts on the Tenant `--tenant <name>` names (replaces `--name`, which is removed), else `NYLORUN_TENANT` (replaces `NYLORUN_STACK`), else the Project link's `tenant`; `start` in a project names a new one after the project directory. Outside a project, or with `start --no-link`, commands act on the Tenant `default`. In a project without a link, commands other than `start` exit 2 and list the machine's Tenants. A name starting with `tn_` (a Tenant id) is refused.
|
|
10
|
+
- **Breaking (`nylorun`): files.** Host roots are under `~/.nylorun/tenants/<name>/` (was `~/.nylorun/stacks/<name>/`) with `tenant.json` (was `stack.json`); the `.env` key is `NYLORUN_TENANT_NAME` (was `NYLORUN_STACK_NAME`); `NYLORUN_COMPOSE_PROJECT` replaces `NYLORUN_STACK_PROJECT`. Compose projects stay `nylorun-<name>`. Every command first moves 0.4 Host roots from `~/.nylorun/stacks/` to `~/.nylorun/tenants/` (renaming `stack.json` and the `.env` key), so they keep their volumes and keys. `nylorun ls` lists only directories with `tenant.json`.
|
|
11
|
+
- **Breaking (`nylorun`): removed.** `nylorun legacy` and all handling of the single stack of releases before 0.4; the hidden `nylorun stack <cmd>` alias; `nylorun doctor stack|runtime`. Output says Tenant: `ls` prints `TENANT` and JSON `{ "tenants": [...] }`, `status` prints the Tenant id on its own line, and `doctor`'s row is `tenant`.
|
|
12
|
+
- **Breaking: Project link format 3.** `.nylorun/link.json` is `{ "format": 3, "tenant", "tenantId", "hostUrl", "hostId" }`; `tenant` replaces `stack`. `@nylorun/agents`, `@nylorun/cli` and `@nylorun/admin` refuse an older link and name `npx nylorun start`, which rewrites it. `@nylorun/core`'s `ProjectLinkFileSchema` parses formats 0–3 with `tenant`.
|
|
13
|
+
- **Breaking (`@nylorun/admin`):** `createAdmin({ tenant })` replaces `{ stack }`, `tenantHostRoot(name)` replaces `stackHostRoot(name)`, and local resolution reads `NYLORUN_TENANT` and the link's `tenant`.
|
|
14
|
+
- `@nylorun/cli`: `status` and `endpoints` drop the `stack` line and JSON key; messages say Tenant. `@nylorun/agents`: a Runtime too old for the client says "update the Runtime (npx nylorun@latest start)". `@nylorun/studio`: setup hints say Tenant. `@nylorun/create-agent`: the next steps describe `npx nylorun@beta start` as this project's Tenant and its link.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Pin core to the tested release.
|
|
19
|
+
- Updated dependencies [4b9906f]
|
|
20
|
+
- @nylorun/core@0.11.0-beta
|
|
21
|
+
|
|
22
|
+
## 0.11.0-beta
|
|
23
|
+
|
|
24
|
+
### Major Changes
|
|
25
|
+
|
|
26
|
+
- 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.
|
|
27
|
+
|
|
28
|
+
- **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.
|
|
29
|
+
- **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.
|
|
30
|
+
- **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.
|
|
31
|
+
- **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.
|
|
32
|
+
- **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`.
|
|
33
|
+
- **`@nylorun/create-agent`:** the next steps are `npx nylorun start`, then `npm run dev`.
|
|
34
|
+
- `@nylorun/core`: `ProjectLinkFileSchema` accepts format 2 with `stack`, and `tenantId` is optional; `ERROR_CODES` loses `tenant_conflict` and `active_work`.
|
|
35
|
+
|
|
36
|
+
- 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.
|
|
37
|
+
|
|
38
|
+
- **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.
|
|
39
|
+
- **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.
|
|
40
|
+
- **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).
|
|
41
|
+
- **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.
|
|
42
|
+
- **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.
|
|
43
|
+
- **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).
|
|
44
|
+
- **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`.
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- Pin core to the tested release.
|
|
49
|
+
- Updated dependencies [fed780d]
|
|
50
|
+
- Updated dependencies [fed780d]
|
|
51
|
+
- Updated dependencies [7f4c3f1]
|
|
52
|
+
- Updated dependencies [5ca1923]
|
|
53
|
+
- Updated dependencies [5ca1923]
|
|
54
|
+
- @nylorun/core@0.10.0-beta
|
|
55
|
+
|
|
3
56
|
## 0.10.0-beta
|
|
4
57
|
|
|
5
58
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -24,33 +24,39 @@ The Runtime delivers each tool call, hook and workflow function of these agents
|
|
|
24
24
|
to `url`, signed with a short-lived **delivery token** that the handler checks
|
|
25
25
|
(Tenant, URL, Action, generation and body) before any code runs. `register`
|
|
26
26
|
saves the definitions, registers the URL and pings it through the Runtime. A
|
|
27
|
-
process that only serves Actions needs no key: pass `runtime: { url
|
|
28
|
-
|
|
27
|
+
process that only serves Actions needs no key: pass `runtime: { url }` and it
|
|
28
|
+
reads the Tenant's public keys. Mark a long tool
|
|
29
29
|
`tool({ …, background: true })`: the handler answers at once, heartbeats and
|
|
30
|
-
posts the result. `npx @nylorun/cli
|
|
31
|
-
|
|
30
|
+
posts the result. `npx @nylorun/cli endpoints` shows each endpoint and how its
|
|
31
|
+
deliveries are doing.
|
|
32
32
|
|
|
33
|
-
The URL must be one the Runtime can reach: `localhost` on
|
|
33
|
+
The URL must be one the Runtime can reach: `localhost` on a local Tenant
|
|
34
34
|
(its Runtime runs in Docker and maps `localhost` to this machine), a public URL
|
|
35
35
|
in production, or a tunnel (ngrok, Cloudflare Tunnel) for a remote Runtime.
|
|
36
36
|
|
|
37
37
|
`connectAgents` and executors were removed in protocol 3: mount
|
|
38
38
|
`createActionHandler` instead (see [MIGRATION.md](../MIGRATION.md)). The handler
|
|
39
|
-
finds the Runtime through the
|
|
40
|
-
that `npx
|
|
41
|
-
|
|
39
|
+
finds the Runtime through the two `NYLORUN_*` variables or the Project link
|
|
40
|
+
that `npx nylorun start` writes; with neither, `register` fails with
|
|
41
|
+
`connection_missing` and names those steps. See [MIGRATION.md](../MIGRATION.md#runtime-clients-and-admin-api-breaking-beta)
|
|
42
42
|
for upgrading from `nylorun serve`.
|
|
43
43
|
|
|
44
44
|
## Connection resolution
|
|
45
45
|
|
|
46
46
|
`resolveConnection` / `createClient()` / `createActionHandler({ agents })`:
|
|
47
47
|
|
|
48
|
-
1. Explicit `{ url,
|
|
49
|
-
2. Environment — if
|
|
50
|
-
|
|
51
|
-
3. Project link — `.nylorun/link.json` + `credentials.json` (the application
|
|
48
|
+
1. Explicit `{ url, key }`
|
|
49
|
+
2. Environment — if `NYLORUN_RUNTIME_URL` or `NYLORUN_SERVER_KEY` is set, both
|
|
50
|
+
must be present
|
|
51
|
+
3. Project link — `.nylorun/link.json` + `credentials.json` (the application
|
|
52
|
+
key), written by `npx nylorun start`. A link from an older nylorun
|
|
53
|
+
(format 0 to 2) fails with `connection_missing`: run `npx nylorun start` in
|
|
54
|
+
the project again.
|
|
52
55
|
|
|
53
|
-
Sources never mix. Partial environment fails with `connection_missing`.
|
|
56
|
+
Sources never mix. Partial environment fails with `connection_missing`. A
|
|
57
|
+
Runtime serves one Tenant, so nothing names it: the `tenant` option is gone
|
|
58
|
+
(protocol 5), and `NYLORUN_TENANT`, which picks a local Tenant for `nylorun`,
|
|
59
|
+
is ignored.
|
|
54
60
|
|
|
55
61
|
```ts
|
|
56
62
|
import { Agent, createActionHandler, createClient, tool } from "@nylorun/agents";
|
|
@@ -72,7 +78,6 @@ const assistant = Agent({ id: "assistant", name: "Assistant" })
|
|
|
72
78
|
const client = createClient({
|
|
73
79
|
url: process.env.NYLORUN_RUNTIME_URL,
|
|
74
80
|
key: process.env.NYLORUN_SERVER_KEY,
|
|
75
|
-
tenant: process.env.NYLORUN_TENANT,
|
|
76
81
|
});
|
|
77
82
|
await client.saveAgent(assistant, { implementationVersion: "app-1" });
|
|
78
83
|
const session = await client.createSession({
|
|
@@ -86,10 +91,7 @@ const history = await session.history();
|
|
|
86
91
|
const actions = createActionHandler({
|
|
87
92
|
agents: [assistant],
|
|
88
93
|
implementationVersion: "app-1",
|
|
89
|
-
runtime: {
|
|
90
|
-
url: process.env.NYLORUN_RUNTIME_URL!,
|
|
91
|
-
tenant: process.env.NYLORUN_TENANT!,
|
|
92
|
-
},
|
|
94
|
+
runtime: { url: process.env.NYLORUN_RUNTIME_URL! },
|
|
93
95
|
url: "https://app.example.com/nylorun/actions",
|
|
94
96
|
onError: console.error,
|
|
95
97
|
});
|
|
@@ -102,11 +104,11 @@ await createActionHandler({ agents: [assistant], client }).register({
|
|
|
102
104
|
|
|
103
105
|
```sh
|
|
104
106
|
eval "$(npx @nylorun/cli env)"
|
|
105
|
-
# → NYLORUN_RUNTIME_URL, NYLORUN_SERVER_KEY
|
|
107
|
+
# → NYLORUN_RUNTIME_URL, NYLORUN_SERVER_KEY
|
|
106
108
|
```
|
|
107
109
|
|
|
108
|
-
Every request sets `Nylorun-
|
|
109
|
-
|
|
110
|
+
Every request sets `Nylorun-Protocol` (5) and no `Nylorun-Tenant`: the Runtime
|
|
111
|
+
serves one Tenant. Before the first authenticated
|
|
110
112
|
request, `Transport` fetches `/health` once, checks protocol compatibility, and
|
|
111
113
|
throws `IncompatibleRuntimeError` / `incompatible_host` when the Host range or
|
|
112
114
|
required features do not match. Re-exports include `PROTOCOL_FEATURES`,
|
|
@@ -494,7 +496,7 @@ const { token, expiresAt } = await app.tokens.create({
|
|
|
494
496
|
});
|
|
495
497
|
```
|
|
496
498
|
|
|
497
|
-
The client sends it as `Authorization: Bearer <token
|
|
499
|
+
The client sends it as `Authorization: Bearer <token>`.
|
|
498
500
|
Tokens carry only `sessions:own`, `vaults:own` and `agents:read`, live at most
|
|
499
501
|
15 minutes, and see only `{ agentId, name, description }` of their role's
|
|
500
502
|
agents. A token that expired or was revoked answers `401` with
|
package/dist/a2a/handler.js
CHANGED
|
@@ -45,7 +45,7 @@ export function createA2aHandler(options) {
|
|
|
45
45
|
const client = await (options.client ?? createClient());
|
|
46
46
|
const features = await client.hostFeatures();
|
|
47
47
|
if (!features.includes(REQUIRED_FEATURE))
|
|
48
|
-
throw new Problem(502, `The Runtime does not support ${REQUIRED_FEATURE};
|
|
48
|
+
throw new Problem(502, `The Runtime does not support ${REQUIRED_FEATURE}; update the Runtime (npx nylorun@latest start).`, "runtime_feature_missing");
|
|
49
49
|
return client;
|
|
50
50
|
})();
|
|
51
51
|
ready.catch(() => {
|
package/dist/action-handler.d.ts
CHANGED
package/dist/action-handler.js
CHANGED
|
@@ -41,13 +41,12 @@ export function createActionHandler(options) {
|
|
|
41
41
|
if (request.method !== "POST")
|
|
42
42
|
return answer(405, "method_not_allowed", "An Action endpoint accepts POST only");
|
|
43
43
|
const body = new Uint8Array(await request.arrayBuffer());
|
|
44
|
-
const {
|
|
44
|
+
const { url, fetch, keys } = await verificationOf();
|
|
45
45
|
const token = request.headers.get(SIGNATURE_HEADER);
|
|
46
46
|
let claims;
|
|
47
47
|
try {
|
|
48
48
|
claims = await verifyDeliveryToken(token, {
|
|
49
49
|
keys: keys.lookup,
|
|
50
|
-
tenantId: tenant,
|
|
51
50
|
body,
|
|
52
51
|
...(audience === undefined ? {} : { audience }),
|
|
53
52
|
});
|
|
@@ -96,7 +95,7 @@ export function createActionHandler(options) {
|
|
|
96
95
|
agent,
|
|
97
96
|
token: token,
|
|
98
97
|
sandbox: delivery.sandbox,
|
|
99
|
-
runtime: { url,
|
|
98
|
+
runtime: { url, ...(fetch ? { fetch } : {}) },
|
|
100
99
|
report,
|
|
101
100
|
});
|
|
102
101
|
options.waitUntil?.(work);
|
|
@@ -106,7 +105,7 @@ export function createActionHandler(options) {
|
|
|
106
105
|
? createActionSandbox({
|
|
107
106
|
transport: (callbacks = callbacks
|
|
108
107
|
? callbacks.withKey(token)
|
|
109
|
-
: new Transport({ url,
|
|
108
|
+
: new Transport({ url, key: token, ...(fetch ? { fetch } : {}) })),
|
|
110
109
|
actionId: action.actionId,
|
|
111
110
|
signal: request.signal,
|
|
112
111
|
})
|
|
@@ -254,22 +253,19 @@ async function runInBackground(input) {
|
|
|
254
253
|
}
|
|
255
254
|
async function resolveVerification(options, clientOf) {
|
|
256
255
|
if (options.runtime) {
|
|
257
|
-
const { url,
|
|
256
|
+
const { url, fetch } = options.runtime;
|
|
258
257
|
return {
|
|
259
|
-
tenant,
|
|
260
258
|
url,
|
|
261
259
|
...(fetch ? { fetch } : {}),
|
|
262
|
-
keys: new JwksCache(options.jwks ?? { url,
|
|
260
|
+
keys: new JwksCache(options.jwks ?? { url, ...(fetch ? { fetch } : {}) }),
|
|
263
261
|
};
|
|
264
262
|
}
|
|
265
263
|
const { transport } = await clientOf();
|
|
266
264
|
return {
|
|
267
|
-
tenant: transport.tenant,
|
|
268
265
|
url: transport.url,
|
|
269
266
|
fetch: transport.fetcher,
|
|
270
267
|
keys: new JwksCache(options.jwks ?? {
|
|
271
268
|
url: transport.url,
|
|
272
|
-
tenant: transport.tenant,
|
|
273
269
|
key: transport.key,
|
|
274
270
|
fetch: transport.fetcher,
|
|
275
271
|
}),
|
package/dist/ag-ui/handler.js
CHANGED
|
@@ -65,7 +65,7 @@ export function createAgUiHandler(options) {
|
|
|
65
65
|
const features = await client.hostFeatures();
|
|
66
66
|
const missing = REQUIRED_FEATURES.filter((f) => !features.includes(f));
|
|
67
67
|
if (missing.length > 0)
|
|
68
|
-
throw new Problem(502, `The Runtime does not support ${missing.join(", ")};
|
|
68
|
+
throw new Problem(502, `The Runtime does not support ${missing.join(", ")}; update the Runtime (npx nylorun@latest start).`, "runtime_feature_missing");
|
|
69
69
|
return client;
|
|
70
70
|
})();
|
|
71
71
|
ready.catch(() => {
|
package/dist/client.js
CHANGED
|
@@ -2,15 +2,12 @@ export * from "./session-client.js";
|
|
|
2
2
|
import { AgentsClient } from "./session-client.js";
|
|
3
3
|
import { resolveConnection } from "./connection.js";
|
|
4
4
|
export function createClient(destination = {}) {
|
|
5
|
-
if (destination.url !== undefined ||
|
|
6
|
-
destination.key !== undefined ||
|
|
7
|
-
destination.tenant !== undefined) {
|
|
5
|
+
if (destination.url !== undefined || destination.key !== undefined) {
|
|
8
6
|
return new AgentsClient(destination);
|
|
9
7
|
}
|
|
10
8
|
return resolveConnection().then((connection) => new AgentsClient({
|
|
11
9
|
url: connection.url,
|
|
12
10
|
key: connection.key,
|
|
13
|
-
tenant: connection.tenant,
|
|
14
11
|
...(destination.fetch ? { fetch: destination.fetch } : {}),
|
|
15
12
|
}));
|
|
16
13
|
}
|
package/dist/connection.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ErrorCode } from "@nylorun/core/compatibility";
|
|
2
2
|
export interface ResolvedConnection {
|
|
3
3
|
url: string;
|
|
4
|
-
tenant: string;
|
|
5
4
|
key: string;
|
|
6
5
|
source: "options" | "environment" | "project-link";
|
|
7
6
|
}
|
|
@@ -9,10 +8,12 @@ export declare class ConnectionError extends Error {
|
|
|
9
8
|
readonly code: ErrorCode;
|
|
10
9
|
constructor(message: string);
|
|
11
10
|
}
|
|
12
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Resolve Tenant API connection: options → environment → project link (D§7.1). A connection is a
|
|
13
|
+
* Runtime URL and a key: the Runtime serves one Tenant, so nothing names it.
|
|
14
|
+
*/
|
|
13
15
|
export declare function resolveConnection(options?: {
|
|
14
16
|
url?: string;
|
|
15
|
-
tenant?: string;
|
|
16
17
|
key?: string;
|
|
17
18
|
cwd?: string;
|
|
18
19
|
}): Promise<ResolvedConnection>;
|
package/dist/connection.js
CHANGED
|
@@ -11,8 +11,8 @@ export class ConnectionError extends Error {
|
|
|
11
11
|
}
|
|
12
12
|
function missing(tried) {
|
|
13
13
|
throw new ConnectionError(`connection_missing: no Runtime connection found (tried ${tried.join(", ")}). ` +
|
|
14
|
-
`
|
|
15
|
-
`or set NYLORUN_RUNTIME_URL
|
|
14
|
+
`Run "npx nylorun start" in this project to start its Tenant and link it, ` +
|
|
15
|
+
`or set NYLORUN_RUNTIME_URL and NYLORUN_SERVER_KEY.`);
|
|
16
16
|
}
|
|
17
17
|
function stripTrailingSlash(url) {
|
|
18
18
|
return url.replace(/\/$/, "");
|
|
@@ -37,30 +37,31 @@ async function readProjectLink(startDir) {
|
|
|
37
37
|
throw error;
|
|
38
38
|
}
|
|
39
39
|
const link = ProjectLinkFileSchema.parse(JSON.parse(linkRaw));
|
|
40
|
+
// Formats 0 to 2 are from older releases.
|
|
41
|
+
if (link.format < 3)
|
|
42
|
+
throw new ConnectionError(`connection_missing: the Project link at ${linkPath} is from an older nylorun. ` +
|
|
43
|
+
`Run "npx nylorun start" in this project to link it again.`);
|
|
40
44
|
const credentials = ProjectCredentialsFileSchema.parse(JSON.parse(await readFile(join(nylorun, "credentials.json"), "utf8")));
|
|
41
45
|
return {
|
|
42
46
|
url: stripTrailingSlash(link.hostUrl),
|
|
43
|
-
tenant: link.tenantId,
|
|
44
47
|
key: credentials.applicationKey,
|
|
45
48
|
source: "project-link",
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Resolve Tenant API connection: options → environment → project link (D§7.1). A connection is a
|
|
54
|
+
* Runtime URL and a key: the Runtime serves one Tenant, so nothing names it.
|
|
55
|
+
*/
|
|
50
56
|
export async function resolveConnection(options) {
|
|
51
57
|
const tried = [];
|
|
52
58
|
const optionUrl = options?.url;
|
|
53
|
-
const optionTenant = options?.tenant;
|
|
54
59
|
const optionKey = options?.key;
|
|
55
|
-
const anyOption = optionUrl !== undefined ||
|
|
56
|
-
optionTenant !== undefined ||
|
|
57
|
-
optionKey !== undefined;
|
|
58
60
|
tried.push("options");
|
|
59
|
-
if (
|
|
60
|
-
if (optionUrl &&
|
|
61
|
+
if (optionUrl !== undefined || optionKey !== undefined) {
|
|
62
|
+
if (optionUrl && optionKey) {
|
|
61
63
|
return {
|
|
62
64
|
url: stripTrailingSlash(optionUrl),
|
|
63
|
-
tenant: optionTenant,
|
|
64
65
|
key: optionKey,
|
|
65
66
|
source: "options",
|
|
66
67
|
};
|
|
@@ -68,17 +69,12 @@ export async function resolveConnection(options) {
|
|
|
68
69
|
missing(tried.concat(["environment", "project-link"]));
|
|
69
70
|
}
|
|
70
71
|
const envUrl = env("NYLORUN_RUNTIME_URL");
|
|
71
|
-
const envTenant = env("NYLORUN_TENANT");
|
|
72
72
|
const envServerKey = env("NYLORUN_SERVER_KEY");
|
|
73
|
-
const anyEnv = envUrl !== undefined ||
|
|
74
|
-
envTenant !== undefined ||
|
|
75
|
-
envServerKey !== undefined;
|
|
76
73
|
tried.push("environment");
|
|
77
|
-
if (
|
|
78
|
-
if (envUrl &&
|
|
74
|
+
if (envUrl !== undefined || envServerKey !== undefined) {
|
|
75
|
+
if (envUrl && envServerKey) {
|
|
79
76
|
return {
|
|
80
77
|
url: stripTrailingSlash(envUrl),
|
|
81
|
-
tenant: envTenant,
|
|
82
78
|
key: envServerKey,
|
|
83
79
|
source: "environment",
|
|
84
80
|
};
|
package/dist/delivery-token.d.ts
CHANGED
|
@@ -22,9 +22,15 @@ export declare class DeliveryVerificationError extends Error {
|
|
|
22
22
|
}
|
|
23
23
|
/** Finds the public key for a `kid`, or `undefined` when the Tenant has none. */
|
|
24
24
|
export type KeyLookup = (kid: string) => Promise<CryptoKey | undefined>;
|
|
25
|
+
/**
|
|
26
|
+
* Verifies `token` against `body`. The keys are the installation's, so a valid signature already
|
|
27
|
+
* binds the issuer to its one Tenant: any `urn:nylorun:tenant:<id>` issuer is accepted (and
|
|
28
|
+
* returned in `iss`) unless `tenantId` names the one expected.
|
|
29
|
+
*/
|
|
25
30
|
export declare function verifyDeliveryToken(token: string | null, options: {
|
|
26
31
|
keys: KeyLookup;
|
|
27
|
-
|
|
32
|
+
/** When set, `iss` must name this Tenant. */
|
|
33
|
+
tenantId?: string;
|
|
28
34
|
body: Uint8Array;
|
|
29
35
|
/** When set, `aud` must equal it: the URL this endpoint was registered with. */
|
|
30
36
|
audience?: string;
|
|
@@ -45,7 +51,6 @@ export declare class JwksCache {
|
|
|
45
51
|
private pending;
|
|
46
52
|
constructor(source: {
|
|
47
53
|
url: string;
|
|
48
|
-
tenant: string;
|
|
49
54
|
key?: string;
|
|
50
55
|
fetch?: typeof fetch;
|
|
51
56
|
} | {
|
package/dist/delivery-token.js
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* only, so the SDK takes no JWT dependency: a JWS ES256 signature is the raw `r || s` pair
|
|
5
5
|
* WebCrypto's ECDSA verifies.
|
|
6
6
|
*/
|
|
7
|
-
import { PROTOCOL_HEADER, PROTOCOL_VERSION,
|
|
7
|
+
import { PROTOCOL_HEADER, PROTOCOL_VERSION, isTenantId } from "@nylorun/core/compatibility";
|
|
8
8
|
import { DELIVERY_TOKEN_TYPE, subjectTokenIssuer } from "@nylorun/core/contracts";
|
|
9
|
+
/** The issuer prefix of a Tenant's tokens: `urn:nylorun:tenant:<tenantId>`. */
|
|
10
|
+
const ISSUER_PREFIX = subjectTokenIssuer("");
|
|
9
11
|
/** Why a delivery was refused; `code` is sent back to the Runtime. */
|
|
10
12
|
export class DeliveryVerificationError extends Error {
|
|
11
13
|
code;
|
|
@@ -20,6 +22,11 @@ const SKEW_SECONDS = 30;
|
|
|
20
22
|
const FORBIDDEN_HEADERS = ["jku", "jwk", "x5u", "x5c", "x5t", "x5t#S256", "crit"];
|
|
21
23
|
/** The largest token accepted: well above a real one, well below a request limit. */
|
|
22
24
|
const MAX_TOKEN_LENGTH = 4096;
|
|
25
|
+
/**
|
|
26
|
+
* Verifies `token` against `body`. The keys are the installation's, so a valid signature already
|
|
27
|
+
* binds the issuer to its one Tenant: any `urn:nylorun:tenant:<id>` issuer is accepted (and
|
|
28
|
+
* returned in `iss`) unless `tenantId` names the one expected.
|
|
29
|
+
*/
|
|
23
30
|
export async function verifyDeliveryToken(token, options) {
|
|
24
31
|
if (!token)
|
|
25
32
|
throw new DeliveryVerificationError("signature_missing", "No delivery token");
|
|
@@ -50,7 +57,10 @@ export async function verifyDeliveryToken(token, options) {
|
|
|
50
57
|
typeof claims.exp !== "number" ||
|
|
51
58
|
typeof claims.jti !== "string")
|
|
52
59
|
throw invalid("Missing claims");
|
|
53
|
-
if (claims.iss
|
|
60
|
+
if (!claims.iss.startsWith(ISSUER_PREFIX) ||
|
|
61
|
+
!isTenantId(claims.iss.slice(ISSUER_PREFIX.length)))
|
|
62
|
+
throw invalid("The token was not issued by a Tenant");
|
|
63
|
+
if (options.tenantId !== undefined && claims.iss !== subjectTokenIssuer(options.tenantId))
|
|
54
64
|
throw invalid("The token is for another Tenant");
|
|
55
65
|
if (options.audience !== undefined && claims.aud !== options.audience)
|
|
56
66
|
throw invalid(`The token is for ${claims.aud}, not ${options.audience}`);
|
|
@@ -111,7 +121,6 @@ export class JwksCache {
|
|
|
111
121
|
}
|
|
112
122
|
async fetchKeys(source) {
|
|
113
123
|
const headers = {
|
|
114
|
-
[TENANT_HEADER]: source.tenant,
|
|
115
124
|
[PROTOCOL_HEADER]: String(PROTOCOL_VERSION),
|
|
116
125
|
};
|
|
117
126
|
if (source.key)
|
package/dist/http.d.ts
CHANGED
|
@@ -8,14 +8,17 @@ export interface TokenSource {
|
|
|
8
8
|
get(signal?: AbortSignal): Promise<string>;
|
|
9
9
|
invalidate(): void;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Where a client sends its requests. Nothing names a Tenant: the Runtime at `url` serves one
|
|
13
|
+
* (protocol 5).
|
|
14
|
+
*/
|
|
11
15
|
export interface Destination {
|
|
12
16
|
url?: string;
|
|
13
17
|
key?: string;
|
|
14
|
-
tenant?: string;
|
|
15
18
|
fetch?: typeof fetch;
|
|
16
19
|
/** Instead of `key`: subject tokens. The client then skips the `/health` check. */
|
|
17
20
|
token?: TokenSource;
|
|
18
|
-
/** A publishable key (Host feature `browser-access`)
|
|
21
|
+
/** A publishable key (Host feature `browser-access`): names the app and its origins. */
|
|
19
22
|
publishableKey?: string;
|
|
20
23
|
}
|
|
21
24
|
export declare function env(name: string): string | undefined;
|
|
@@ -38,8 +41,6 @@ export declare class Transport {
|
|
|
38
41
|
readonly url: string;
|
|
39
42
|
/** The Tenant key; empty for a client that uses subject tokens. */
|
|
40
43
|
readonly key: string;
|
|
41
|
-
/** The Tenant id; empty when a publishable key names it. */
|
|
42
|
-
readonly tenant: string;
|
|
43
44
|
readonly token: TokenSource | undefined;
|
|
44
45
|
readonly publishableKey: string | undefined;
|
|
45
46
|
readonly fetcher: typeof fetch;
|
package/dist/http.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PROTOCOL_FEATURES, PROTOCOL_HEADER, PROTOCOL_VERSION, PUBLISHABLE_KEY_HEADER,
|
|
1
|
+
import { PROTOCOL_FEATURES, PROTOCOL_HEADER, PROTOCOL_VERSION, PUBLISHABLE_KEY_HEADER, checkCompatibility, } from "@nylorun/core/compatibility";
|
|
2
2
|
export function env(name) {
|
|
3
3
|
return typeof process !== "undefined" ? process.env[name] : undefined;
|
|
4
4
|
}
|
|
@@ -56,8 +56,6 @@ export class Transport {
|
|
|
56
56
|
url;
|
|
57
57
|
/** The Tenant key; empty for a client that uses subject tokens. */
|
|
58
58
|
key;
|
|
59
|
-
/** The Tenant id; empty when a publishable key names it. */
|
|
60
|
-
tenant;
|
|
61
59
|
token;
|
|
62
60
|
publishableKey;
|
|
63
61
|
fetcher;
|
|
@@ -68,19 +66,15 @@ export class Transport {
|
|
|
68
66
|
const url = options.url ?? env("NYLORUN_RUNTIME_URL");
|
|
69
67
|
const token = options.token;
|
|
70
68
|
const key = token ? "" : options.key ?? env("NYLORUN_SERVER_KEY");
|
|
71
|
-
const tenant = options.tenant ?? (token ? undefined : env("NYLORUN_TENANT"));
|
|
72
69
|
if (!url || (!token && !key))
|
|
73
70
|
throw new Error("Set Runtime url and server key explicitly or via NYLORUN_RUNTIME_URL / NYLORUN_SERVER_KEY");
|
|
74
71
|
if (token && options.key)
|
|
75
72
|
throw new Error("Use a Tenant key or subject tokens, not both");
|
|
76
|
-
if (!tenant && !options.publishableKey)
|
|
77
|
-
throw new Error("Set tenant explicitly or via NYLORUN_TENANT");
|
|
78
73
|
const parsed = new URL(url);
|
|
79
74
|
if (!["http:", "https:"].includes(parsed.protocol))
|
|
80
75
|
throw new Error("Runtime requires an HTTP(S) URL");
|
|
81
76
|
this.url = url.replace(/\/$/, "");
|
|
82
77
|
this.key = key;
|
|
83
|
-
this.tenant = tenant ?? "";
|
|
84
78
|
this.token = token;
|
|
85
79
|
this.publishableKey = options.publishableKey;
|
|
86
80
|
// Browsers may not call `/health` (it refuses `Origin`); token clients rely on `426`.
|
|
@@ -171,8 +165,6 @@ export class Transport {
|
|
|
171
165
|
? await this.token.get(init.signal ?? undefined)
|
|
172
166
|
: this.key;
|
|
173
167
|
headers.set("Authorization", `Bearer ${bearer}`);
|
|
174
|
-
if (this.tenant)
|
|
175
|
-
headers.set(TENANT_HEADER, this.tenant);
|
|
176
168
|
if (this.publishableKey)
|
|
177
169
|
headers.set(PUBLISHABLE_KEY_HEADER, this.publishableKey);
|
|
178
170
|
headers.set(PROTOCOL_HEADER, String(PROTOCOL_VERSION));
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION,
|
|
1
|
+
export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION, PROTOCOL_HEADER, SUBJECT_HEADER, SCOPES_HEADER, TENANT_ID_PATTERN, isTenantId, newTenantId, newPrincipalId, checkCompatibility, compareVersions, ERROR_CODES, } from "@nylorun/core/compatibility";
|
|
2
2
|
export type { ProtocolFeature, ProtocolRange, Compatibility, ErrorCode, } from "@nylorun/core/compatibility";
|
|
3
3
|
export { Agent, AgentBuilder } from "./builder.js";
|
|
4
4
|
export { AgentBuildError, AgentLifecycleError, Loop, Chain, Switch, Parallel, Map, VerdictSchema, isVerdict, withInstructions, withoutTools, WorkflowBuildError, isBuiltWorkflow, capability, CapabilityBuilder, flow, tool, defineSchema, ToolError, } from "@nylorun/core/define";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Definition authoring and wire contracts are the only harness runtime imports.
|
|
2
|
-
export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION,
|
|
2
|
+
export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION, PROTOCOL_HEADER, SUBJECT_HEADER, SCOPES_HEADER, TENANT_ID_PATTERN, isTenantId, newTenantId, newPrincipalId, checkCompatibility, compareVersions, ERROR_CODES, } from "@nylorun/core/compatibility";
|
|
3
3
|
export { Agent, AgentBuilder } from "./builder.js";
|
|
4
4
|
export { AgentBuildError, AgentLifecycleError, Loop, Chain, Switch, Parallel, Map, VerdictSchema, isVerdict, withInstructions, withoutTools, WorkflowBuildError, isBuiltWorkflow, capability, CapabilityBuilder, flow, tool, defineSchema, ToolError, } from "@nylorun/core/define";
|
|
5
5
|
export { SUBJECT_SCOPES } from "@nylorun/core/contracts";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0-beta",
|
|
4
4
|
"description": "Nylorun agent definitions, session client and Action endpoint",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"test": "vitest run --passWithNoTests"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@nylorun/core": "0.
|
|
50
|
+
"@nylorun/core": "0.11.0-beta",
|
|
51
51
|
"gray-matter": "^4.0.3"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|