@nylorun/runtime 0.31.0-beta → 0.33.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 +63 -0
- package/dist/api/components.d.ts +100 -0
- package/dist/api/components.js +4 -1
- package/dist/api/http/routes/agent-manifests.d.ts +2 -1
- package/dist/api/http/routes/agent-manifests.js +29 -2
- package/dist/api/http/routes/sessions.js +63 -2
- package/dist/api/openapi.js +4 -0
- package/dist/gates/handler.js +2 -2
- package/dist/gates/in-process.d.ts +4 -3
- package/dist/gates/in-process.js +11 -5
- package/dist/gates/tenant-vaults.d.ts +4 -3
- package/dist/gates/tenant-vaults.js +2 -2
- package/dist/harness-api/start.js +1 -1
- package/dist/host/main.js +2 -0
- package/dist/host/stack-config.d.ts +5 -0
- package/dist/host/stack-config.js +15 -0
- package/dist/management-openapi.json +90 -8
- package/dist/model/descriptor.d.ts +5 -4
- package/dist/model/descriptor.js +4 -3
- package/dist/model/pi-model.js +17 -1
- package/dist/openapi.json +880 -2
- package/dist/tenant/agent-manifests.d.ts +6 -1
- package/dist/tenant/agent-manifests.js +50 -8
- package/dist/tenant/agents.d.ts +4 -3
- package/dist/tenant/agents.js +26 -5
- package/dist/tenant/context.d.ts +6 -1
- package/dist/tenant/session-model.d.ts +16 -0
- package/dist/tenant/session-model.js +46 -0
- package/dist/vault/host-identity.d.ts +24 -0
- package/dist/vault/host-identity.js +35 -0
- package/dist/vault/host-model.d.ts +9 -5
- package/dist/vault/host-model.js +30 -19
- package/dist/vault/service.d.ts +18 -2
- package/dist/vault/service.js +52 -9
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.33.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 95f98f1: A model can use the Host's own identity (ADR-71, Host feature `model-host-identity`). `PUT /v1/tenant/model` takes `auth: { type: "host_identity", project, location }` for `google-vertex`. It keeps no secret, and the model gate calls Agent Platform with the Host's Google Application Default Credentials: on Google Cloud, the attached service account from the metadata server. It's off unless the operator lists the provider in `NYLORUN_MODEL_HOST_IDENTITY` on the process that runs the gates, which `nylorun start` passes from its shell to the `gateway` container. Every Tenant on that Host may use it. `nylorun tenant models set --provider google-vertex --model <id> --host-identity --project <id> --location <location>` sets it with no key.
|
|
8
|
+
- d99b3ac: A session can have its own model (optional Host feature `session-model`). `PUT /v1/sessions/{id}/model` chooses one of a connected provider's models for that session's turns, `DELETE` clears it, and `GET` answers the model the next turn uses (`source: "session"` or `"tenant"`). The Tenant's model and every other session's stay as they are. The Model Gate calls the session's model on its provider's credential (a refreshed OAuth credential is written back to that provider), `turn.start.model` describes it, and the usage ledger records it. A choice names a connected provider and a model its catalog lists, is set by the application only (a trusted issuer's token can read it, not change it), and is refused while a turn runs or waits (`409 session_busy`); while its provider is disconnected the session uses the Tenant's model. The SDK adds `session.model()`, `setModel({ provider, model })` and `clearModel()`.
|
|
9
|
+
|
|
10
|
+
Studio's model picker under the message box now sets the model of that session only, instead of the Tenant's: "Tenant model" clears the session's choice, the picker is locked while a turn runs, it groups models by provider, and its search keeps what is typed. A Runtime without `session-model` shows no picker.
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 683de1a: The model catalog comes from pi-ai 1.3.0, which adds Gemini 4 Argon: `google-vertex/gemini-4-argon` on Google's Agent Platform (Vertex AI) and `google/gemini-4-argon` on the Gemini API, with a 1,048,576-token context and thinking. `nylorun tenant models set --provider google-vertex --model gemini-4-argon` takes a Google Cloud API key for the Agent Platform API; the Runtime still reads no ambient Google credentials.
|
|
15
|
+
- Pin core to the tested release.
|
|
16
|
+
- Pin harness to the tested release.
|
|
17
|
+
- Updated dependencies [95f98f1]
|
|
18
|
+
- Updated dependencies [d99b3ac]
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @nylorun/core@0.29.0-beta
|
|
21
|
+
- @nylorun/harness@0.29.5-beta
|
|
22
|
+
|
|
23
|
+
## 0.32.0-beta
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- b3dad06: Both ends of the agent folder loop (track T7).
|
|
28
|
+
|
|
29
|
+
- `nylorun init <path>` names the agent after the path's last segment (`init agents/hello`). `--example` adds `tools/get_order.json`, `mcp.json` (a `Bearer ${ORDERS_MCP_TOKEN}` header) and `triggers/new-order.md`, explained in the folder's README.md, and the result passes `nylorun check`. The first run in a project (the nearest directory with `.git`) writes `.gitattributes` (`* text=auto eol=lf`), ignores `.nylorun/credentials.json` in `.gitignore`, and maps the folder files to their JSON Schemas in `.vscode/settings.json`, merged into an existing file. Its hint names `apply --agent` and `chat`.
|
|
30
|
+
- `nylorun apply --agent [<id>]` makes the Agent from the manifest after a save (or on an unchanged one), or moves it, as `nylorun agents put` does, and prints what it needs a person for.
|
|
31
|
+
- `nylorun apply --watch [--save]` checks and plans again on each change to the folders (and the files their `runtime.json` extends); it saves only with `--save`.
|
|
32
|
+
- A plan's change to the instructions prints their text diff, `-` and `+` lines.
|
|
33
|
+
- `nylorun chat <agent> [--session <id>] [--message <text>]` opens or reuses a session, sends `--message` or each line of standard input, and prints the reply as it comes.
|
|
34
|
+
- `nylorun check --json` prints `{ folders: [{ path, ok, manifest?, diagnostics }] }` for CI, with the same exit codes. `check` says "1 file", and `nylorun --version` prints the version.
|
|
35
|
+
- `packFolder` (`@nylorun/agents`) leaves out what the folder's `.nyloignore` names (gitignore rules), and resolves `extends` in `runtime.json`: the packed file is the merge, the folder's own keys winning, with `.nylorun/origin.json` naming the files it came from; a missing file or a cycle is a `FolderError`. `ignoreMatcher` is exported.
|
|
36
|
+
- `session.approve(id, approved)` and `session.respond(id, value)` take no options: each makes its own idempotency key.
|
|
37
|
+
- The Runtime's Agent view names each required secret of the version it runs that has no value, as an attention item (`secret_unset: required secret ORDERS_TOKEN unset`, state `input_required`), until it is set.
|
|
38
|
+
- The compiler's refusal of an unresolved `extends` says to resolve it before uploading.
|
|
39
|
+
|
|
40
|
+
- b3dad06: Compare two versions' agent folders, and set what a folder may hold per Tenant (track T7).
|
|
41
|
+
|
|
42
|
+
- **`GET /v1/agent-manifests/{name}/source/diff?from=<v>&to=<v>`** answers the files added, removed and changed (by SHA-256) from one version's source to another's, each list sorted by path, and how many stayed the same (`AgentManifestSourceDiff` in `@nylorun/core/contracts`). A version saved as JSON has no source (`404`); a `from` or `to` that is not a version number is `400`. `client.agentManifests.sourceDiff(name, from, to)` in `@nylorun/agents` calls it.
|
|
43
|
+
- **Folder limits are Tenant settings**: the Runtime limits `folderFiles` (2,000), `folderBytes` (50 MiB) and `folderTextFileBytes` (1 MiB), T6's fixed values, set with `PUT /v1/tenant/limits` like the others. A folder save with more files or bytes is `413 limit_exceeded` (`details.limit` names the limit), and the compiler holds each Markdown or JSON file to `folderTextFileBytes` (`422 folder_invalid`).
|
|
44
|
+
- `compileAgentFolder({ entries, files, name, limits })` takes the limits as an optional input (`AgentFolderLimits`); each left out is `AGENT_FOLDER_LIMITS`'.
|
|
45
|
+
- `@nylorun/agents` also exports the types `AgentManifestSource`, `AgentManifestSourceDiff`, `AgentManifestSourceSummary` and `AgentFolderDiagnostic`, and `AGENT_FOLDER_MEDIA_TYPE`.
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- 498d972: `nylorun check --fix` makes the edits the compiler's diagnostics carry (track T7). A diagnostic one edit fixes has a `fix` (`AgentFolderFix`, in `AgentFolderDiagnostic` and the Runtime API's): `rename_key` for an unknown key with exactly one did-you-mean (in `AGENT.md`, a trigger, a `SKILL.md`, a tool file, `runtime.json`, `mcp.json`, `flow.json` and a JSON Schema's keywords), at its line and column, and none when two keys are as close or the key it would be is already there; `crlf` for a file with CRLF line ends, which is now a `crlf` note (it is read as LF, as before); and `move_skill_secrets` for `secrets` in a root skill's `SKILL.md`, when `AGENT.md` lists none for the skill, or lists them all. Messages, manifests and hashes are unchanged. `applyFolderFixes` in `@nylorun/core/folder` makes them on text: the key token renamed with every other byte kept, LF line ends, and the secrets moved to `AGENT.md`'s `skills` block as `migrate folder` writes it, skipping (with why) a fix whose text is no longer where it was.
|
|
50
|
+
|
|
51
|
+
`nylorun check` marks each fixable problem `(fixable with --fix)` and writes nothing. `check --fix` makes the edits in the folder's files, prints each change by file, and checks again until nothing is left to fix; it leaves a file whose bytes changed since it was checked (writing nothing when one changes while it fixes), and a `runtime.json` that `extends` another. `check --json` gives each diagnostic's `fix`, and with `--fix` each folder's `fixed` and `unfixed`.
|
|
52
|
+
|
|
53
|
+
- Pin core to the tested release.
|
|
54
|
+
- Pin harness to the tested release.
|
|
55
|
+
- Updated dependencies [498d972]
|
|
56
|
+
- Updated dependencies [d23304e]
|
|
57
|
+
- Updated dependencies [b3dad06]
|
|
58
|
+
- Updated dependencies [b3dad06]
|
|
59
|
+
- Updated dependencies [b3dad06]
|
|
60
|
+
- Updated dependencies [498d972]
|
|
61
|
+
- Updated dependencies [b3dad06]
|
|
62
|
+
- Updated dependencies
|
|
63
|
+
- @nylorun/core@0.28.0-beta
|
|
64
|
+
- @nylorun/harness@0.29.4-beta
|
|
65
|
+
|
|
3
66
|
## 0.31.0-beta
|
|
4
67
|
|
|
5
68
|
### Minor Changes
|
package/dist/api/components.d.ts
CHANGED
|
@@ -541,6 +541,33 @@ export declare const AgentManifestSource: z.ZodObject<{
|
|
|
541
541
|
sha256: z.ZodString;
|
|
542
542
|
}, z.core.$strict>>;
|
|
543
543
|
}, z.core.$strict>;
|
|
544
|
+
export declare const AgentManifestSourceDiff: z.ZodObject<{
|
|
545
|
+
name: z.ZodString;
|
|
546
|
+
from: z.ZodNumber;
|
|
547
|
+
to: z.ZodNumber;
|
|
548
|
+
added: z.ZodArray<z.ZodObject<{
|
|
549
|
+
path: z.ZodString;
|
|
550
|
+
size: z.ZodNumber;
|
|
551
|
+
sha256: z.ZodString;
|
|
552
|
+
}, z.core.$strict>>;
|
|
553
|
+
removed: z.ZodArray<z.ZodObject<{
|
|
554
|
+
path: z.ZodString;
|
|
555
|
+
size: z.ZodNumber;
|
|
556
|
+
sha256: z.ZodString;
|
|
557
|
+
}, z.core.$strict>>;
|
|
558
|
+
changed: z.ZodArray<z.ZodObject<{
|
|
559
|
+
path: z.ZodString;
|
|
560
|
+
from: z.ZodObject<{
|
|
561
|
+
size: z.ZodNumber;
|
|
562
|
+
sha256: z.ZodString;
|
|
563
|
+
}, z.core.$strict>;
|
|
564
|
+
to: z.ZodObject<{
|
|
565
|
+
size: z.ZodNumber;
|
|
566
|
+
sha256: z.ZodString;
|
|
567
|
+
}, z.core.$strict>;
|
|
568
|
+
}, z.core.$strict>>;
|
|
569
|
+
unchanged: z.ZodNumber;
|
|
570
|
+
}, z.core.$strict>;
|
|
544
571
|
export declare const AgentManifestView: z.ZodObject<{
|
|
545
572
|
name: z.ZodString;
|
|
546
573
|
version: z.ZodNumber;
|
|
@@ -792,6 +819,22 @@ export declare const AgentManifestPlan: z.ZodObject<{
|
|
|
792
819
|
line: z.ZodOptional<z.ZodNumber>;
|
|
793
820
|
column: z.ZodOptional<z.ZodNumber>;
|
|
794
821
|
pointer: z.ZodOptional<z.ZodString>;
|
|
822
|
+
fix: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
823
|
+
kind: z.ZodLiteral<"rename_key">;
|
|
824
|
+
file: z.ZodString;
|
|
825
|
+
line: z.ZodNumber;
|
|
826
|
+
column: z.ZodNumber;
|
|
827
|
+
from: z.ZodString;
|
|
828
|
+
to: z.ZodString;
|
|
829
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
830
|
+
kind: z.ZodLiteral<"crlf">;
|
|
831
|
+
file: z.ZodString;
|
|
832
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
833
|
+
kind: z.ZodLiteral<"move_skill_secrets">;
|
|
834
|
+
file: z.ZodString;
|
|
835
|
+
skill: z.ZodString;
|
|
836
|
+
secrets: z.ZodArray<z.ZodString>;
|
|
837
|
+
}, z.core.$strict>], "kind">>;
|
|
795
838
|
}, z.core.$strict>>>;
|
|
796
839
|
compiler: z.ZodOptional<z.ZodString>;
|
|
797
840
|
}, z.core.$strict>;
|
|
@@ -925,6 +968,22 @@ export declare const SaveAgentManifestResponse: z.ZodObject<{
|
|
|
925
968
|
line: z.ZodOptional<z.ZodNumber>;
|
|
926
969
|
column: z.ZodOptional<z.ZodNumber>;
|
|
927
970
|
pointer: z.ZodOptional<z.ZodString>;
|
|
971
|
+
fix: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
972
|
+
kind: z.ZodLiteral<"rename_key">;
|
|
973
|
+
file: z.ZodString;
|
|
974
|
+
line: z.ZodNumber;
|
|
975
|
+
column: z.ZodNumber;
|
|
976
|
+
from: z.ZodString;
|
|
977
|
+
to: z.ZodString;
|
|
978
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
979
|
+
kind: z.ZodLiteral<"crlf">;
|
|
980
|
+
file: z.ZodString;
|
|
981
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
982
|
+
kind: z.ZodLiteral<"move_skill_secrets">;
|
|
983
|
+
file: z.ZodString;
|
|
984
|
+
skill: z.ZodString;
|
|
985
|
+
secrets: z.ZodArray<z.ZodString>;
|
|
986
|
+
}, z.core.$strict>], "kind">>;
|
|
928
987
|
}, z.core.$strict>>>;
|
|
929
988
|
}, z.core.$strict>;
|
|
930
989
|
export declare const ListAgentManifestsResponse: z.ZodObject<{
|
|
@@ -1917,6 +1976,9 @@ export declare const PutTenantLimitsRequest: z.ZodObject<{
|
|
|
1917
1976
|
flowConcurrency: z.ZodOptional<z.ZodNumber>;
|
|
1918
1977
|
flowMapItems: z.ZodOptional<z.ZodNumber>;
|
|
1919
1978
|
flowLoopIterations: z.ZodOptional<z.ZodNumber>;
|
|
1979
|
+
folderFiles: z.ZodOptional<z.ZodNumber>;
|
|
1980
|
+
folderBytes: z.ZodOptional<z.ZodNumber>;
|
|
1981
|
+
folderTextFileBytes: z.ZodOptional<z.ZodNumber>;
|
|
1920
1982
|
}, z.core.$strict>>;
|
|
1921
1983
|
requestId: z.ZodOptional<z.ZodString>;
|
|
1922
1984
|
}, z.core.$strict>;
|
|
@@ -1992,6 +2054,9 @@ export declare const TenantLimitsView: z.ZodObject<{
|
|
|
1992
2054
|
flowConcurrency: z.ZodNumber;
|
|
1993
2055
|
flowMapItems: z.ZodNumber;
|
|
1994
2056
|
flowLoopIterations: z.ZodNumber;
|
|
2057
|
+
folderFiles: z.ZodNumber;
|
|
2058
|
+
folderBytes: z.ZodNumber;
|
|
2059
|
+
folderTextFileBytes: z.ZodNumber;
|
|
1995
2060
|
}, z.core.$strict>;
|
|
1996
2061
|
}, z.core.$strict>;
|
|
1997
2062
|
export declare const ArtifactTree: z.ZodObject<{
|
|
@@ -2356,6 +2421,30 @@ export declare const SessionView: z.ZodObject<{
|
|
|
2356
2421
|
error: z.ZodUnknown;
|
|
2357
2422
|
}, z.core.$strict>>;
|
|
2358
2423
|
}, z.core.$strict>;
|
|
2424
|
+
export declare const PutSessionModelRequest: z.ZodObject<{
|
|
2425
|
+
provider: z.ZodString;
|
|
2426
|
+
model: z.ZodString;
|
|
2427
|
+
}, z.core.$strict>;
|
|
2428
|
+
export declare const SessionModelView: z.ZodUnion<readonly [z.ZodObject<{
|
|
2429
|
+
configured: z.ZodLiteral<false>;
|
|
2430
|
+
choice: z.ZodOptional<z.ZodObject<{
|
|
2431
|
+
provider: z.ZodString;
|
|
2432
|
+
model: z.ZodString;
|
|
2433
|
+
}, z.core.$strict>>;
|
|
2434
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2435
|
+
configured: z.ZodLiteral<true>;
|
|
2436
|
+
source: z.ZodEnum<{
|
|
2437
|
+
session: "session";
|
|
2438
|
+
tenant: "tenant";
|
|
2439
|
+
}>;
|
|
2440
|
+
provider: z.ZodString;
|
|
2441
|
+
model: z.ZodString;
|
|
2442
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
2443
|
+
choice: z.ZodOptional<z.ZodObject<{
|
|
2444
|
+
provider: z.ZodString;
|
|
2445
|
+
model: z.ZodString;
|
|
2446
|
+
}, z.core.$strict>>;
|
|
2447
|
+
}, z.core.$strict>]>;
|
|
2359
2448
|
export declare const LiveEvent: z.ZodObject<{
|
|
2360
2449
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
2361
2450
|
eventId: z.ZodString;
|
|
@@ -13392,6 +13481,7 @@ export declare const TenantStatus: z.ZodObject<{
|
|
|
13392
13481
|
model: z.ZodString;
|
|
13393
13482
|
authType: z.ZodEnum<{
|
|
13394
13483
|
api_key: "api_key";
|
|
13484
|
+
host_identity: "host_identity";
|
|
13395
13485
|
oauth: "oauth";
|
|
13396
13486
|
workload: "workload";
|
|
13397
13487
|
}>;
|
|
@@ -13557,6 +13647,10 @@ export declare const SeedTenantConfigRequest: z.ZodObject<{
|
|
|
13557
13647
|
expires: z.ZodNumber;
|
|
13558
13648
|
}, z.core.$loose>, z.ZodObject<{
|
|
13559
13649
|
type: z.ZodLiteral<"workload">;
|
|
13650
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13651
|
+
type: z.ZodLiteral<"host_identity">;
|
|
13652
|
+
project: z.ZodString;
|
|
13653
|
+
location: z.ZodString;
|
|
13560
13654
|
}, z.core.$strict>], "type">;
|
|
13561
13655
|
}, z.core.$strict>>;
|
|
13562
13656
|
fixtureModel: z.ZodOptional<z.ZodLiteral<true>>;
|
|
@@ -13815,6 +13909,7 @@ export declare const ListProvidersResponse: z.ZodObject<{
|
|
|
13815
13909
|
model: z.ZodString;
|
|
13816
13910
|
authType: z.ZodEnum<{
|
|
13817
13911
|
api_key: "api_key";
|
|
13912
|
+
host_identity: "host_identity";
|
|
13818
13913
|
oauth: "oauth";
|
|
13819
13914
|
workload: "workload";
|
|
13820
13915
|
}>;
|
|
@@ -13862,6 +13957,7 @@ export declare const HostModelView: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
13862
13957
|
model: z.ZodString;
|
|
13863
13958
|
authType: z.ZodEnum<{
|
|
13864
13959
|
api_key: "api_key";
|
|
13960
|
+
host_identity: "host_identity";
|
|
13865
13961
|
oauth: "oauth";
|
|
13866
13962
|
workload: "workload";
|
|
13867
13963
|
}>;
|
|
@@ -13930,6 +14026,10 @@ export declare const PutHostModelRequest: z.ZodObject<{
|
|
|
13930
14026
|
expires: z.ZodNumber;
|
|
13931
14027
|
}, z.core.$loose>, z.ZodObject<{
|
|
13932
14028
|
type: z.ZodLiteral<"workload">;
|
|
14029
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
14030
|
+
type: z.ZodLiteral<"host_identity">;
|
|
14031
|
+
project: z.ZodString;
|
|
14032
|
+
location: z.ZodString;
|
|
13933
14033
|
}, z.core.$strict>], "type">;
|
|
13934
14034
|
}, z.core.$strict>;
|
|
13935
14035
|
export declare const SelectHostModelRequest: z.ZodObject<{
|
package/dist/api/components.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* global registry.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import { QueuedResponseSchema, TriggerListSchema, MemoryListSchema, MemorySchema, PutMemoryRequestSchema, MemoryVersionPageSchema, MemoryVersionDetailSchema, TriggerRunPageSchema, RunTriggerResponseSchema, WebhookSecretResponseSchema, WebhookAcceptedResponseSchema, AgentManifestV8Schema, EnvironmentSecretSlotsSchema, DeleteAgentManifestResponseSchema, AgentManifestPlanSchema, AgentManifestVersionsSchema, AgentManifestViewSchema, ListAgentManifestsResponseSchema, PutAgentManifestRequestSchema, PutAgentFolderRequestSchema, AgentManifestSourceSchema, PutAgentSecretValueRequestSchema, SaveAgentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, AgentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutAgentSecretRequestSchema, AgentSecretViewSchema, ListAgentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, AgentViewSchema, AgentSnapshotSchema, RestoreAgentRequestSchema, ForkAgentRequestSchema, AgentForkPlanSchema, ForkAgentResponseSchema, PutAgentDryRunResponseSchema, RestartAgentRequestSchema, AgentRestoreSchema, AgentDiskVersionsSchema, ListAgentsResponseSchema, DeleteAgentResponseSchema, ListAgentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, PutTenantSkillsRequestSchema, PutTenantLimitsRequestSchema, TenantLimitsViewSchema, TenantArtifactsViewSchema, TenantSkillsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
|
|
8
|
+
import { PutSessionModelRequestSchema, SessionModelViewSchema, QueuedResponseSchema, TriggerListSchema, MemoryListSchema, MemorySchema, PutMemoryRequestSchema, MemoryVersionPageSchema, MemoryVersionDetailSchema, TriggerRunPageSchema, RunTriggerResponseSchema, WebhookSecretResponseSchema, WebhookAcceptedResponseSchema, AgentManifestV8Schema, EnvironmentSecretSlotsSchema, DeleteAgentManifestResponseSchema, AgentManifestPlanSchema, AgentManifestVersionsSchema, AgentManifestViewSchema, ListAgentManifestsResponseSchema, PutAgentManifestRequestSchema, PutAgentFolderRequestSchema, AgentManifestSourceSchema, AgentManifestSourceDiffSchema, PutAgentSecretValueRequestSchema, SaveAgentManifestResponseSchema, SessionListItemSchema, ModelCallSchema, SessionPageSchema, SessionManifestViewSchema, HistoryPageSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ModelCallExportPageSchema, AgentPageSchema, ToolCallSchema, ToolCallsPageSchema, TurnTraceSchema, JwksSchema, SigningKeyListSchema, SigningKeyViewSchema, RotateSigningKeysRequestSchema, RevokeSigningKeyRequestSchema, MeResponseSchema, TenantStatusSchema, ResetTenantRequestSchema, ResetTenantResponseSchema, SeedTenantConfigRequestSchema, SeedTenantConfigResponseSchema, HostModelCatalogSchema, TenantSandboxViewSchema, ModelUsageTotalsSchema, ModelBudgetsSchema, PutModelBudgetsRequestSchema, ToolPolicySchema, PutToolPolicyRequestSchema, PutModelInputsRequestSchema, ModelInputsViewSchema, PutTenantEnvironmentsRequestSchema, ListProvidersResponseSchema, HostModelViewSchema, PutHostModelRequestSchema, SelectHostModelRequestSchema, PutAgentSecretRequestSchema, AgentSecretViewSchema, ListAgentSecretsResponseSchema, McpPreviewRequestSchema, McpPreviewSchema, CredentialCoverageRequestSchema, CredentialCoverageSchema, DeletedResponseSchema, ListSessionsResponseSchema, LiveEventSchema, PutAgentRequestSchema, PutSessionRequestSchema, SessionItemsResponseSchema, SessionViewSchema, StreamClosedFrameSchema, AcceptedResponseSchema, SandboxToolOutcomeSchema, AgentViewSchema, AgentSnapshotSchema, RestoreAgentRequestSchema, ForkAgentRequestSchema, AgentForkPlanSchema, ForkAgentResponseSchema, PutAgentDryRunResponseSchema, RestartAgentRequestSchema, AgentRestoreSchema, AgentDiskVersionsSchema, ListAgentsResponseSchema, DeleteAgentResponseSchema, ListAgentEventsResponseSchema, ArtifactViewSchema, ArtifactListItemSchema, ArtifactPageSchema, ArtifactVersionViewSchema, ListArtifactsResponseSchema, UploadArtifactResponseSchema, DefinitionFileViewSchema, DeleteArtifactResponseSchema, CreateArtifactLinkRequestSchema, ArtifactLinkSchema, PutTenantArtifactsRequestSchema, PutTenantSkillsRequestSchema, PutTenantLimitsRequestSchema, TenantLimitsViewSchema, TenantArtifactsViewSchema, TenantSkillsViewSchema, ArtifactTreeSchema, ArtifactDiffSchema, SessionCommandSchema, ListOperatorKeysResponseSchema, PutOperatorKeyResponseSchema, DeleteOperatorKeyResponseSchema, OperatorKeySchema, ProtocolRejectedResponseSchema, RejectedResponseSchema, EVENT_SCHEMAS, EVENT_TYPES, } from "@nylorun/core/contracts";
|
|
9
9
|
function named(id, schema) {
|
|
10
10
|
return schema.meta({ id });
|
|
11
11
|
}
|
|
@@ -23,6 +23,7 @@ export const AgentManifest = named("AgentManifest", AgentManifestV8Schema);
|
|
|
23
23
|
export const PutAgentManifestRequest = named("PutAgentManifestRequest", PutAgentManifestRequestSchema);
|
|
24
24
|
export const PutAgentFolderRequest = named("PutAgentFolderRequest", PutAgentFolderRequestSchema);
|
|
25
25
|
export const AgentManifestSource = named("AgentManifestSource", AgentManifestSourceSchema);
|
|
26
|
+
export const AgentManifestSourceDiff = named("AgentManifestSourceDiff", AgentManifestSourceDiffSchema);
|
|
26
27
|
export const AgentManifestView = named("AgentManifestView", AgentManifestViewSchema);
|
|
27
28
|
export const AgentManifestPlan = named("AgentManifestPlan", AgentManifestPlanSchema);
|
|
28
29
|
export const SaveAgentManifestResponse = named("SaveAgentManifestResponse", SaveAgentManifestResponseSchema);
|
|
@@ -76,6 +77,8 @@ export const WebhookAcceptedResponse = named("WebhookAcceptedResponse", WebhookA
|
|
|
76
77
|
export const ListSessionsResponse = named("ListSessionsResponse", ListSessionsResponseSchema);
|
|
77
78
|
export const PutSessionRequest = named("PutSessionRequest", PutSessionRequestSchema);
|
|
78
79
|
export const SessionView = named("SessionView", SessionViewSchema);
|
|
80
|
+
export const PutSessionModelRequest = named("PutSessionModelRequest", PutSessionModelRequestSchema);
|
|
81
|
+
export const SessionModelView = named("SessionModelView", SessionModelViewSchema);
|
|
79
82
|
export const LiveEvent = named("LiveEvent", LiveEventSchema);
|
|
80
83
|
/** `environment.state` → `EnvironmentStateEvent`. */
|
|
81
84
|
export function eventComponentName(type) {
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* moves every Agent that tracks the manifest to the new version; a pinned one stays. Reading needs `agents:read` (or a write scope), saving and deleting
|
|
5
5
|
* `agent-manifests:write`, from any client (Q12). A token caller reaches none: a manifest holds
|
|
6
6
|
* an agent's instructions, tools and servers. A save may send an agent folder by hash instead of
|
|
7
|
-
* the manifest (track T6): the Runtime compiles it and keeps it as the version's source
|
|
7
|
+
* the manifest (track T6): the Runtime compiles it and keeps it as the version's source, and
|
|
8
|
+
* `source/diff` compares two versions' sources (track T7).
|
|
8
9
|
*/
|
|
9
10
|
import type { OpenAPIHono } from "@hono/zod-openapi";
|
|
10
11
|
import type { TenantEnv } from "../app.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AGENT_FOLDER_MEDIA_TYPE, contentTypeFor, isAgentManifestName, PutAgentFolderRequestSchema, PutAgentManifestRequestSchema, } from "@nylorun/core/contracts";
|
|
3
|
-
import { AgentManifestPlan, AgentManifestSource, AgentManifestVersions, AgentManifestView, DeleteAgentManifestResponse, ListAgentManifestsResponse, PutAgentFolderRequest, PutAgentManifestRequest, SaveAgentManifestResponse, } from "../../components.js";
|
|
3
|
+
import { AgentManifestPlan, AgentManifestSource, AgentManifestSourceDiff, AgentManifestVersions, AgentManifestView, DeleteAgentManifestResponse, ListAgentManifestsResponse, PutAgentFolderRequest, PutAgentManifestRequest, SaveAgentManifestResponse, } from "../../components.js";
|
|
4
4
|
import { requirePrincipal } from "../../../tenant/auth.js";
|
|
5
5
|
import { fail } from "../../../tenant/http.js";
|
|
6
|
-
import { agentManifestVersions, deleteAgentManifest, getAgentManifest, getAgentManifestSource, listAgentManifests, readAgentManifestSourceFile, saveAgentFolder, saveAgentManifest, } from "../../../tenant/agent-manifests.js";
|
|
6
|
+
import { agentManifestVersions, deleteAgentManifest, diffAgentManifestSources, getAgentManifest, getAgentManifestSource, listAgentManifests, readAgentManifestSourceFile, saveAgentFolder, saveAgentManifest, } from "../../../tenant/agent-manifests.js";
|
|
7
7
|
import { readJson } from "../body.js";
|
|
8
8
|
import { tenantRoute } from "../define.js";
|
|
9
9
|
import { jsonResponse } from "../respond.js";
|
|
@@ -172,6 +172,33 @@ export function agentManifestRoutes(api) {
|
|
|
172
172
|
headers: { "content-type": contentTypeFor(path), "content-length": String(file.size) },
|
|
173
173
|
});
|
|
174
174
|
});
|
|
175
|
+
tenantRoute(api, READ, {
|
|
176
|
+
method: "get",
|
|
177
|
+
path: "/v1/agent-manifests/{name}/source/diff",
|
|
178
|
+
tags: ["Agent manifests"],
|
|
179
|
+
summary: "Compare two versions' folders",
|
|
180
|
+
description: "The files added, removed and changed from version `from`'s source to version `to`'s, by path, a file changed when its SHA-256 differs (feature `agent-folders`). Each list is sorted by path. A version saved as JSON has no source (`404`).",
|
|
181
|
+
request: {
|
|
182
|
+
params: namePath,
|
|
183
|
+
query: z.object({
|
|
184
|
+
from: z.string().meta({ description: "The version to compare from" }),
|
|
185
|
+
to: z.string().meta({ description: "The version to compare to" }),
|
|
186
|
+
}),
|
|
187
|
+
},
|
|
188
|
+
responses: {
|
|
189
|
+
200: json(AgentManifestSourceDiff, "What changed"),
|
|
190
|
+
400: { description: "`from` or `to` is not a version number" },
|
|
191
|
+
404: { description: "No such version, or one was saved as JSON and has no source" },
|
|
192
|
+
},
|
|
193
|
+
}, async (c) => {
|
|
194
|
+
requirePrincipal(c.get("scope"));
|
|
195
|
+
const name = nameOf(c.req.param("name"));
|
|
196
|
+
const from = Number(c.req.query("from"));
|
|
197
|
+
const to = Number(c.req.query("to"));
|
|
198
|
+
if (!Number.isInteger(from) || from < 1 || !Number.isInteger(to) || to < 1)
|
|
199
|
+
fail(400, "from and to are the versions to compare: positive integers");
|
|
200
|
+
return jsonResponse(200, await diffAgentManifestSources(c.env.tenant, name, from, to));
|
|
201
|
+
});
|
|
175
202
|
tenantRoute(api, WRITE, {
|
|
176
203
|
method: "delete",
|
|
177
204
|
path: "/v1/agent-manifests/{name}",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { RESPONSE_ALREADY_SENT } from "@hono/node-server/utils/response";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { PROTOCOL_HEADER } from "@nylorun/core/compatibility";
|
|
4
|
-
import { PutSessionRequestSchema, SessionCommandSchema, } from "@nylorun/core/contracts";
|
|
4
|
+
import { PutSessionModelRequestSchema, PutSessionRequestSchema, SessionCommandSchema, } from "@nylorun/core/contracts";
|
|
5
5
|
import { handleSessionSandboxTool, SandboxRouteError } from "../../../core/sandbox-routes.js";
|
|
6
6
|
import { traceContextOf } from "../../../traces/ids.js";
|
|
7
|
-
import { AcceptedResponse, QueuedResponse, ListSessionsResponse, SessionPage, HistoryPage, SessionEvent, PutSessionRequest, SandboxToolOutcome, SessionCommand, SessionItemsResponse, SessionView, StreamClosedFrame, } from "../../components.js";
|
|
7
|
+
import { AcceptedResponse, QueuedResponse, ListSessionsResponse, SessionPage, HistoryPage, SessionEvent, PutSessionModelRequest, PutSessionRequest, SandboxToolOutcome, SessionCommand, SessionItemsResponse, SessionModelView, SessionView, StreamClosedFrame, } from "../../components.js";
|
|
8
8
|
import { accessOf, requireApplication } from "../../../tenant/auth.js";
|
|
9
9
|
import { command } from "../../../tenant/commands.js";
|
|
10
10
|
import { loadSession, sessionOf } from "../../../tenant/context.js";
|
|
@@ -12,6 +12,7 @@ import { fail } from "../../../tenant/http.js";
|
|
|
12
12
|
import { agentGrantsOf, sandboxRouteDeps } from "../../../tenant/agents.js";
|
|
13
13
|
import { readHistory, requestCursor, streamHolderOf, streamSessionEvents } from "../../../tenant/session-streams.js";
|
|
14
14
|
import { listSessions, putSession, sessionView } from "../../../tenant/sessions.js";
|
|
15
|
+
import { chooseSessionModel, readSessionModel } from "../../../tenant/session-model.js";
|
|
15
16
|
import { readJson } from "../body.js";
|
|
16
17
|
import { TraceHeaders, tenantRoute } from "../define.js";
|
|
17
18
|
import { pageQuery, pageSize, sessionPage, sessionPageQuery, parseQuery } from "./reads.js";
|
|
@@ -20,6 +21,18 @@ const OWN_SESSIONS = {
|
|
|
20
21
|
credentials: ["application", "subject", "token"],
|
|
21
22
|
scopes: ["sessions:own"],
|
|
22
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* A session's own model costs what its model costs: the application chooses it (for a subject
|
|
26
|
+
* too), never a token a person's browser holds.
|
|
27
|
+
*/
|
|
28
|
+
const APP_SESSIONS = {
|
|
29
|
+
credentials: ["application", "subject"],
|
|
30
|
+
scopes: ["sessions:own"],
|
|
31
|
+
};
|
|
32
|
+
function refuseToken(scope) {
|
|
33
|
+
if (scope.kind === "token")
|
|
34
|
+
fail(403, "A token caller cannot choose a session's model", { code: "scope_required" });
|
|
35
|
+
}
|
|
23
36
|
const json = (schema, description) => ({
|
|
24
37
|
description,
|
|
25
38
|
content: { "application/json": { schema } },
|
|
@@ -122,6 +135,54 @@ export function sessionRoutes(api) {
|
|
|
122
135
|
const id = c.req.param("sessionId");
|
|
123
136
|
return jsonResponse(200, await ctx.store.tx(async (t) => sessionView(t, await sessionOf(t, id, accessOf(scope)))));
|
|
124
137
|
});
|
|
138
|
+
tenantRoute(api, OWN_SESSIONS, {
|
|
139
|
+
method: "get",
|
|
140
|
+
path: "/v1/sessions/{sessionId}/model",
|
|
141
|
+
tags: ["Sessions"],
|
|
142
|
+
summary: "Get a session's model",
|
|
143
|
+
description: "The model the session's next turn uses (feature `session-model`): its own (`source: \"session\"`) while its provider is connected, else the Tenant's (`source: \"tenant\"`). `choice` is the session's own model, kept while its provider is disconnected.",
|
|
144
|
+
request: { params: sessionId },
|
|
145
|
+
responses: { 200: json(SessionModelView, "The session's model") },
|
|
146
|
+
}, async (c) => {
|
|
147
|
+
const scope = c.get("scope");
|
|
148
|
+
return jsonResponse(200, await readSessionModel(c.env.tenant, c.req.param("sessionId"), accessOf(scope)));
|
|
149
|
+
});
|
|
150
|
+
tenantRoute(api, APP_SESSIONS, {
|
|
151
|
+
method: "put",
|
|
152
|
+
path: "/v1/sessions/{sessionId}/model",
|
|
153
|
+
tags: ["Sessions"],
|
|
154
|
+
summary: "Choose a session's model",
|
|
155
|
+
description: "Chooses one of a connected provider's models for the session's turns (feature `session-model`), in place of the Tenant's model. The Tenant's model and every other session's stay as they are. Only the application sets it, for itself or for a subject: a trusted issuer's token is refused. A turn calls one model, so the choice changes only while no turn runs or waits (`409 session_busy`). A provider that is not connected, or a model its catalog does not list, is `422 request_rejected`.",
|
|
156
|
+
request: { params: sessionId, body: body(PutSessionModelRequest) },
|
|
157
|
+
responses: {
|
|
158
|
+
200: json(SessionModelView, "The session's model"),
|
|
159
|
+
403: { description: "A trusted issuer's token (`scope_required`)" },
|
|
160
|
+
409: { description: "A turn is running or waits (`session_busy`)" },
|
|
161
|
+
422: { description: "The provider is not connected, or the model is not one of its models" },
|
|
162
|
+
},
|
|
163
|
+
}, async (c) => {
|
|
164
|
+
const scope = c.get("scope");
|
|
165
|
+
refuseToken(scope);
|
|
166
|
+
const choice = PutSessionModelRequestSchema.parse(await readJson(c));
|
|
167
|
+
return jsonResponse(200, await chooseSessionModel(c.env.tenant, c.req.param("sessionId"), choice, accessOf(scope)));
|
|
168
|
+
});
|
|
169
|
+
tenantRoute(api, APP_SESSIONS, {
|
|
170
|
+
method: "delete",
|
|
171
|
+
path: "/v1/sessions/{sessionId}/model",
|
|
172
|
+
tags: ["Sessions"],
|
|
173
|
+
summary: "Clear a session's model",
|
|
174
|
+
description: "Clears the session's own model (feature `session-model`): its next turns use the Tenant's model. Refused while a turn runs or waits (`409 session_busy`).",
|
|
175
|
+
request: { params: sessionId },
|
|
176
|
+
responses: {
|
|
177
|
+
200: json(SessionModelView, "The session's model"),
|
|
178
|
+
403: { description: "A trusted issuer's token (`scope_required`)" },
|
|
179
|
+
409: { description: "A turn is running or waits (`session_busy`)" },
|
|
180
|
+
},
|
|
181
|
+
}, async (c) => {
|
|
182
|
+
const scope = c.get("scope");
|
|
183
|
+
refuseToken(scope);
|
|
184
|
+
return jsonResponse(200, await chooseSessionModel(c.env.tenant, c.req.param("sessionId"), undefined, accessOf(scope)));
|
|
185
|
+
});
|
|
125
186
|
tenantRoute(api, OWN_SESSIONS, {
|
|
126
187
|
method: "get",
|
|
127
188
|
path: "/v1/sessions/{sessionId}/items",
|
package/dist/api/openapi.js
CHANGED
|
@@ -121,6 +121,7 @@ const RUNTIME_TAGS = [
|
|
|
121
121
|
"GET /v1/agent-manifests/{name}/versions/{version}",
|
|
122
122
|
"GET /v1/agent-manifests/{name}/versions/{version}/source",
|
|
123
123
|
"GET /v1/agent-manifests/{name}/versions/{version}/source/files/{path}",
|
|
124
|
+
"GET /v1/agent-manifests/{name}/source/diff",
|
|
124
125
|
"DELETE /v1/agent-manifests/{name}",
|
|
125
126
|
],
|
|
126
127
|
},
|
|
@@ -193,6 +194,9 @@ const RUNTIME_TAGS = [
|
|
|
193
194
|
"GET /v1/sessions/{sessionId}/events",
|
|
194
195
|
"GET /v1/sessions/{sessionId}/items",
|
|
195
196
|
"GET /v1/sessions/{sessionId}/manifest",
|
|
197
|
+
"GET /v1/sessions/{sessionId}/model",
|
|
198
|
+
"PUT /v1/sessions/{sessionId}/model",
|
|
199
|
+
"DELETE /v1/sessions/{sessionId}/model",
|
|
196
200
|
"GET /v1/sessions/{sessionId}/usage",
|
|
197
201
|
"GET /v1/sessions/{sessionId}/calls/model",
|
|
198
202
|
"GET /v1/sessions/{sessionId}/calls/tool",
|
package/dist/gates/handler.js
CHANGED
|
@@ -23,8 +23,8 @@ export function createModelCallHandler(options) {
|
|
|
23
23
|
request = call;
|
|
24
24
|
const gate = inProcessModelGate({
|
|
25
25
|
root: vault.root,
|
|
26
|
-
readHostModel: () => vault.readHostModel(),
|
|
27
|
-
writeHostCredential: (credential) => vault.writeHostCredential(credential),
|
|
26
|
+
readHostModel: (request) => vault.readHostModel(request.sessionId),
|
|
27
|
+
writeHostCredential: (credential, provider) => vault.writeHostCredential(credential, provider),
|
|
28
28
|
// The Tenant's Runtime limits `model*`, read for this call.
|
|
29
29
|
settings: await modelCallSettings(vault.store),
|
|
30
30
|
...(blobs ? { files: callFiles(vault.store, blobs) } : {}),
|
|
@@ -15,9 +15,10 @@ import type { ModelCaller } from "../model/call-headers.js";
|
|
|
15
15
|
export interface InProcessModelGateOptions {
|
|
16
16
|
/** The Tenant's home: `piModel` redacts secrets it finds there from failure messages. */
|
|
17
17
|
readonly root?: string;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
/** The host model a call uses: its session's own model (`session-model`), else the Tenant's. */
|
|
19
|
+
readonly readHostModel: (request: ModelGateRequest) => Promise<HostModelSecret | undefined>;
|
|
20
|
+
/** Writes back a credential pi-ai refreshed (OAuth) to `provider`'s, the one the call read. */
|
|
21
|
+
readonly writeHostCredential: (credential: Credential, provider: string) => Promise<void>;
|
|
21
22
|
readonly settings?: ModelCallSettings;
|
|
22
23
|
/** Reads the files a call's prompt names (protocol 6): artifacts, for model-gate. */
|
|
23
24
|
readonly files?: (request: ModelGateRequest) => FileResolver;
|
package/dist/gates/in-process.js
CHANGED
|
@@ -45,8 +45,8 @@ export function tenantModelGate(options) {
|
|
|
45
45
|
// The Tenant's Runtime limits `model*`, read for this call.
|
|
46
46
|
const gate = inProcessModelGate({
|
|
47
47
|
root: options.root,
|
|
48
|
-
readHostModel: () => vault.readHostModel(),
|
|
49
|
-
writeHostCredential: (credential) => vault.updateHostCredential(credential),
|
|
48
|
+
readHostModel: (request) => vault.readHostModel(request.sessionId),
|
|
49
|
+
writeHostCredential: (credential, provider) => vault.updateHostCredential(credential, provider),
|
|
50
50
|
settings: await modelCallSettings(options.store),
|
|
51
51
|
...(options.blobs ? { files: callFiles(options.store, options.blobs) } : {}),
|
|
52
52
|
caller: callCaller(options.store),
|
|
@@ -71,11 +71,17 @@ export async function serve(store, gate, request, signal) {
|
|
|
71
71
|
export function inProcessModelGate(options) {
|
|
72
72
|
return {
|
|
73
73
|
async call(request, signal) {
|
|
74
|
-
// One adapter per call, as before the gate: it reads the host model when invoked
|
|
74
|
+
// One adapter per call, as before the gate: it reads the host model when invoked, and a
|
|
75
|
+
// refreshed credential goes back to the provider it read.
|
|
76
|
+
let provider;
|
|
75
77
|
const adapter = piModel({
|
|
76
78
|
...(options.root !== undefined ? { root: options.root } : {}),
|
|
77
|
-
readHostModel:
|
|
78
|
-
|
|
79
|
+
readHostModel: async () => {
|
|
80
|
+
const stored = await options.readHostModel(request);
|
|
81
|
+
provider = stored?.provider;
|
|
82
|
+
return stored;
|
|
83
|
+
},
|
|
84
|
+
writeHostCredential: (credential) => options.writeHostCredential(credential, provider),
|
|
79
85
|
...(options.settings ? { settings: options.settings } : {}),
|
|
80
86
|
...(options.files ? { files: options.files(request) } : {}),
|
|
81
87
|
...(options.caller ? { caller: () => options.caller(request) } : {}),
|
|
@@ -22,9 +22,10 @@ export interface TenantVault {
|
|
|
22
22
|
readonly store: SessionStore;
|
|
23
23
|
/** The Tenant's home: secrets found there are redacted from failure messages. */
|
|
24
24
|
readonly root: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
/** The host model a call uses: its session's own model (`session-model`), else the Tenant's. */
|
|
26
|
+
readHostModel(sessionId?: string): Promise<HostModelSecret | undefined>;
|
|
27
|
+
/** Writes back a credential pi-ai refreshed (OAuth) to `provider`'s, else the active one's. */
|
|
28
|
+
writeHostCredential(credential: Credential, provider?: string): Promise<void>;
|
|
28
29
|
/** A session, for the remote MCP servers and HTTP tools its pinned manifest declares. */
|
|
29
30
|
session(sessionId: string): Promise<Session | undefined>;
|
|
30
31
|
/**
|
|
@@ -47,8 +47,8 @@ export function createTenantVaults(options) {
|
|
|
47
47
|
tenantId,
|
|
48
48
|
store,
|
|
49
49
|
root: paths.home,
|
|
50
|
-
readHostModel: () => vault.readHostModel(),
|
|
51
|
-
writeHostCredential: (credential) => vault.updateHostCredential(credential),
|
|
50
|
+
readHostModel: (sessionId) => vault.readHostModel(sessionId),
|
|
51
|
+
writeHostCredential: (credential, provider) => vault.updateHostCredential(credential, provider),
|
|
52
52
|
session,
|
|
53
53
|
authorizeMcp: (sessionId, request) => authorizeSessionMcp(credentials, session, sessionId, request),
|
|
54
54
|
keys: () => keys,
|
|
@@ -82,7 +82,7 @@ options = {}) {
|
|
|
82
82
|
});
|
|
83
83
|
// The model an agent's harness decides files by, read outside the session's transaction.
|
|
84
84
|
const model = options.harness && !isWorkflowManifest(opened.current.manifest)
|
|
85
|
-
? await currentModelDescriptor(ctx)
|
|
85
|
+
? await currentModelDescriptor(ctx, opened.current.model)
|
|
86
86
|
: undefined;
|
|
87
87
|
const started = model ? { ...opened, model } : opened;
|
|
88
88
|
// One history (P0.3): the engine resumes from the transcript folded from the record.
|
package/dist/host/main.js
CHANGED
|
@@ -65,6 +65,7 @@ import { startHarnessListener } from "../harness-api/ws-server.js";
|
|
|
65
65
|
import { httpSandboxesClient } from "../sandbox/pods/client.js";
|
|
66
66
|
import { retry } from "../retry.js";
|
|
67
67
|
import { hostTuning, useHostTuning } from "../tuning.js";
|
|
68
|
+
import { useHostIdentity } from "../vault/host-identity.js";
|
|
68
69
|
import { useWorkloadToken } from "../vault/workload-token.js";
|
|
69
70
|
const nodeRequire = createRequire(import.meta.url);
|
|
70
71
|
function coreVersion() {
|
|
@@ -220,6 +221,7 @@ export async function main() {
|
|
|
220
221
|
if (stack.tuning)
|
|
221
222
|
useHostTuning(stack.tuning.values, stack.tuning.overrides);
|
|
222
223
|
useWorkloadToken(stack.workloadToken ?? {});
|
|
224
|
+
useHostIdentity(stack.modelHostIdentity ?? []);
|
|
223
225
|
if (stack.services.has("gates") || stack.services.has("keys") || stack.services.has("egress"))
|
|
224
226
|
return runGates(stack);
|
|
225
227
|
if (stack.services.has("harness"))
|
|
@@ -188,6 +188,11 @@ export interface StackConfig {
|
|
|
188
188
|
file?: string;
|
|
189
189
|
origins?: string[];
|
|
190
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* `NYLORUN_MODEL_HOST_IDENTITY`: the comma-separated providers whose models may use the Host's
|
|
193
|
+
* own identity (ADR-71, `vault/host-identity.ts`). Absent: none.
|
|
194
|
+
*/
|
|
195
|
+
modelHostIdentity?: string[];
|
|
191
196
|
/** Present when the process runs gates. */
|
|
192
197
|
gates?: GatesConfig;
|
|
193
198
|
/** Present when the process runs egress. */
|
|
@@ -50,6 +50,7 @@ import { isTenantId } from "@nylorun/core/compatibility";
|
|
|
50
50
|
import { LOOPBACK_HOSTS } from "@nylorun/core/contracts";
|
|
51
51
|
import { blockedAddresses } from "../sandbox/pods/network-gate.js";
|
|
52
52
|
import { HostTuningError, parseHostTuning } from "../tuning.js";
|
|
53
|
+
import { HOST_IDENTITY_PROVIDERS } from "../vault/host-identity.js";
|
|
53
54
|
export const RUNTIME_SERVICES = ["core", "loop", "gates", "keys", "egress", "harness"];
|
|
54
55
|
/**
|
|
55
56
|
* Services that may share a process (D12): they hold the same secrets and parse the same
|
|
@@ -327,6 +328,7 @@ export function parseStackConfig(env, argv) {
|
|
|
327
328
|
const delivery = parseDelivery(env);
|
|
328
329
|
const tenant = servesApi ? parseTenant(env) : undefined;
|
|
329
330
|
const workloadToken = parseWorkloadToken(env);
|
|
331
|
+
const modelHostIdentity = parseModelHostIdentity(env);
|
|
330
332
|
const objectStore = parseObjectStore(env);
|
|
331
333
|
const traces = services.has("core") ? parseTraces(env) : undefined;
|
|
332
334
|
const removedResolverVariables = Object.keys(env)
|
|
@@ -350,6 +352,7 @@ export function parseStackConfig(env, argv) {
|
|
|
350
352
|
...(delivery ? { delivery } : {}),
|
|
351
353
|
...(tenant ? { tenant } : {}),
|
|
352
354
|
...(workloadToken ? { workloadToken } : {}),
|
|
355
|
+
...(modelHostIdentity ? { modelHostIdentity } : {}),
|
|
353
356
|
...(objectStore ? { objectStore } : {}),
|
|
354
357
|
...(traces ? { traces } : {}),
|
|
355
358
|
...(tuning ? { tuning } : {}),
|
|
@@ -468,6 +471,18 @@ function parseWorkloadToken(env) {
|
|
|
468
471
|
return undefined;
|
|
469
472
|
return { ...(file ? { file } : {}), ...(origins ? { origins } : {}) };
|
|
470
473
|
}
|
|
474
|
+
/** `StackConfig.modelHostIdentity` (ADR-71): each a provider that can use the Host's identity. */
|
|
475
|
+
function parseModelHostIdentity(env) {
|
|
476
|
+
const raw = read(env, "NYLORUN_MODEL_HOST_IDENTITY");
|
|
477
|
+
if (raw === undefined)
|
|
478
|
+
return undefined;
|
|
479
|
+
const providers = [...new Set(raw.split(",").map((item) => item.trim()).filter((item) => item !== ""))];
|
|
480
|
+
for (const provider of providers) {
|
|
481
|
+
if (!HOST_IDENTITY_PROVIDERS.includes(provider))
|
|
482
|
+
throw new StackConfigError(`NYLORUN_MODEL_HOST_IDENTITY: ${provider} can't use the Host's identity (only ${HOST_IDENTITY_PROVIDERS.join(", ")})`);
|
|
483
|
+
}
|
|
484
|
+
return providers.length ? providers : undefined;
|
|
485
|
+
}
|
|
471
486
|
/** `NYLORUN_WORKLOAD_TOKEN_ORIGINS`: each an `https` origin (`http` only to a loopback host). */
|
|
472
487
|
function parseOrigins(raw) {
|
|
473
488
|
if (raw === undefined)
|