@nylorun/runtime 0.29.0-beta → 0.30.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 +20 -0
- package/dist/api/components.d.ts +76 -2
- package/dist/gates/egress-credentials.js +2 -13
- package/dist/gates/handler.js +2 -1
- package/dist/gates/in-process.d.ts +9 -0
- package/dist/gates/in-process.js +21 -0
- package/dist/host/main.js +2 -0
- package/dist/host/stack-config.d.ts +10 -0
- package/dist/host/stack-config.js +36 -0
- package/dist/management-openapi.json +359 -5
- package/dist/mcp/connect.d.ts +34 -5
- package/dist/mcp/connect.js +75 -14
- package/dist/mcp/gateway-outcomes.d.ts +14 -0
- package/dist/mcp/gateway-outcomes.js +46 -0
- package/dist/mcp/pool.js +5 -0
- package/dist/model/call-headers.d.ts +15 -0
- package/dist/model/call-headers.js +9 -0
- package/dist/model/models.d.ts +7 -0
- package/dist/model/models.js +3 -0
- package/dist/model/pi-model.d.ts +6 -0
- package/dist/model/pi-model.js +29 -3
- package/dist/openapi.json +79 -2
- package/dist/store/postgres/schema.d.ts +2 -2
- package/dist/store/postgres/schema.js +1 -1
- package/dist/tenant/agents.js +7 -3
- package/dist/tenant/transcript.d.ts +8 -0
- package/dist/tenant/transcript.js +2 -0
- package/dist/vault/headers.d.ts +8 -0
- package/dist/vault/headers.js +25 -0
- package/dist/vault/host-model.js +8 -5
- package/dist/vault/service.d.ts +12 -5
- package/dist/vault/service.js +43 -6
- package/dist/vault/sources.js +22 -1
- package/dist/vault/workload-token.d.ts +16 -0
- package/dist/vault/workload-token.js +58 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.30.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- fce0c9b: Headers for a custom model endpoint (#493). A custom endpoint's `settings` (`PUT /v1/tenant/model`) take `headers`, sent on every call, and `callHeaders`, whose values the Runtime resolves per call from the calling Agent: one of its labels (`{ from: "agent.label", key: "org" }`), its id (`agent.id`) or the session's owner when it is a person (`session.owner`). A source with no value sends no header. A Runtime that serves several orgs' Agents can then send each call's org (`x-nylorun-org` from the `org` label), so a model gateway attributes and budgets it while the call is made, in process and through the gates service alike. They are settings, read back by `GET /v1/tenant/model`: neither map may set `authorization`, a hop-by-hop or transport header, or `Nylorun-*`, and a name appears once across both. Studio keeps them when it saves the model.
|
|
8
|
+
- ab7c08a: A gateway's tool prefix (#494, Host feature `gateway-credentials`). A `bearer` or `headers` credential with `via`, written to an Agent's vault, may add `toolPrefix`: what the gateway at `via` puts before each tool name it lists, such as LiteLLM's `github-`. The Runtime lists the server's tools without it, so tool names (`github__create_issue`), a manifest's `tools` settings and tool policy rules name the server's own tools whether or not a gateway is in between, and calls each tool by the name the gateway listed. A listed tool that lacks the prefix keeps its name, and the server's `mcp.discovered` message names it. `toolPrefix` needs `via`, and secret views carry it. It is the installation's routing, never a manifest's: a manifest's secret slot cannot name it, and a slot's value write (`{ headers, toolPrefix }`) adds it. A fork keeps it while the new slot keeps `via`. No protocol change.
|
|
9
|
+
- 4a563e7: The workload token (#496). A Runtime given `NYLORUN_WORKLOAD_TOKEN_FILE`, a token a platform rotates through a file, reads it at each use and keeps nothing, so a rotation applies to the next request with no restart; a missing, unreadable or empty file fails the request, naming the variable, and nothing is sent without it. A custom model with `auth: { type: "workload" }` sends it as the endpoint's bearer. A new credential type, `workload` (`{ url, via, identity?, toolPrefix? }`, no value), sends `Authorization: Bearer <token>` to its `via` only, and only when `via`'s origin is in `NYLORUN_WORKLOAD_TOKEN_ORIGINS`, since an Agent's writer chooses `via`. A gateway's `401` is `credential_rejected` with `gateway`, its origin. The token stays in the process that makes the call: never in a sandbox, the model, an event or a log. Studio shows the credential and the model's auth.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 8c82ed9: An MCP gateway's report of an upstream `401` is `credential_rejected` (#495). Through a credential's `via`, a gateway that answers HTTP 200 but reports that the server behind it answered `401` is read like a `401`. LiteLLM does this for a token the provider revoked: a `tools/list` with no tools and `"auth_required"` for the server in `_meta["litellm.ai/server_outcomes"]` makes the server's `mcp.discovered` outcome `failed` ("MCP server returned 401"), and a tool error carrying that outcome, or LiteLLM's `HTTPStatusError: Client error '401 Unauthorized'` text, completes as `credential_rejected` with `retryable: false`, naming the server. A server reached without `via` is read as before.
|
|
14
|
+
- Pin core to the tested release.
|
|
15
|
+
- Pin harness to the tested release.
|
|
16
|
+
- Updated dependencies [fce0c9b]
|
|
17
|
+
- Updated dependencies [ab7c08a]
|
|
18
|
+
- Updated dependencies [4a563e7]
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @nylorun/core@0.26.0-beta
|
|
21
|
+
- @nylorun/harness@0.29.2-beta
|
|
22
|
+
|
|
3
23
|
## 0.29.0-beta
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
package/dist/api/components.d.ts
CHANGED
|
@@ -897,6 +897,7 @@ export declare const PutAgentSecretValueRequest: z.ZodObject<{
|
|
|
897
897
|
requestId: z.ZodOptional<z.ZodString>;
|
|
898
898
|
value: z.ZodOptional<z.ZodString>;
|
|
899
899
|
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
900
|
+
toolPrefix: z.ZodOptional<z.ZodString>;
|
|
900
901
|
}, z.core.$strict>;
|
|
901
902
|
export declare const AgentSnapshot: z.ZodObject<{
|
|
902
903
|
agentId: z.ZodString;
|
|
@@ -4447,6 +4448,7 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
4447
4448
|
code: z.ZodString;
|
|
4448
4449
|
message: z.ZodString;
|
|
4449
4450
|
server: z.ZodOptional<z.ZodString>;
|
|
4451
|
+
gateway: z.ZodOptional<z.ZodString>;
|
|
4450
4452
|
retryable: z.ZodOptional<z.ZodBoolean>;
|
|
4451
4453
|
}, z.core.$loose>>;
|
|
4452
4454
|
redacted: z.ZodOptional<z.ZodNumber>;
|
|
@@ -7179,6 +7181,7 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
7179
7181
|
code: z.ZodString;
|
|
7180
7182
|
message: z.ZodString;
|
|
7181
7183
|
server: z.ZodOptional<z.ZodString>;
|
|
7184
|
+
gateway: z.ZodOptional<z.ZodString>;
|
|
7182
7185
|
retryable: z.ZodOptional<z.ZodBoolean>;
|
|
7183
7186
|
}, z.core.$loose>>;
|
|
7184
7187
|
redacted: z.ZodOptional<z.ZodNumber>;
|
|
@@ -9914,6 +9917,7 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
9914
9917
|
code: z.ZodString;
|
|
9915
9918
|
message: z.ZodString;
|
|
9916
9919
|
server: z.ZodOptional<z.ZodString>;
|
|
9920
|
+
gateway: z.ZodOptional<z.ZodString>;
|
|
9917
9921
|
retryable: z.ZodOptional<z.ZodBoolean>;
|
|
9918
9922
|
}, z.core.$loose>>;
|
|
9919
9923
|
redacted: z.ZodOptional<z.ZodNumber>;
|
|
@@ -12646,6 +12650,7 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
12646
12650
|
code: z.ZodString;
|
|
12647
12651
|
message: z.ZodString;
|
|
12648
12652
|
server: z.ZodOptional<z.ZodString>;
|
|
12653
|
+
gateway: z.ZodOptional<z.ZodString>;
|
|
12649
12654
|
retryable: z.ZodOptional<z.ZodBoolean>;
|
|
12650
12655
|
}, z.core.$loose>>;
|
|
12651
12656
|
redacted: z.ZodOptional<z.ZodNumber>;
|
|
@@ -13224,6 +13229,7 @@ export declare const TenantStatus: z.ZodObject<{
|
|
|
13224
13229
|
authType: z.ZodEnum<{
|
|
13225
13230
|
api_key: "api_key";
|
|
13226
13231
|
oauth: "oauth";
|
|
13232
|
+
workload: "workload";
|
|
13227
13233
|
}>;
|
|
13228
13234
|
baseUrl: z.ZodOptional<z.ZodString>;
|
|
13229
13235
|
settings: z.ZodOptional<z.ZodObject<{
|
|
@@ -13239,6 +13245,15 @@ export declare const TenantStatus: z.ZodObject<{
|
|
|
13239
13245
|
video: "video";
|
|
13240
13246
|
}>>>;
|
|
13241
13247
|
compat: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
13248
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
13249
|
+
callHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13250
|
+
from: z.ZodLiteral<"agent.label">;
|
|
13251
|
+
key: z.ZodString;
|
|
13252
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13253
|
+
from: z.ZodLiteral<"agent.id">;
|
|
13254
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13255
|
+
from: z.ZodLiteral<"session.owner">;
|
|
13256
|
+
}, z.core.$strict>], "from">>>;
|
|
13242
13257
|
}, z.core.$strict>>;
|
|
13243
13258
|
}, z.core.$strict>]>;
|
|
13244
13259
|
agents: z.ZodArray<z.ZodObject<{
|
|
@@ -13357,6 +13372,15 @@ export declare const SeedTenantConfigRequest: z.ZodObject<{
|
|
|
13357
13372
|
video: "video";
|
|
13358
13373
|
}>>>;
|
|
13359
13374
|
compat: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
13375
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
13376
|
+
callHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13377
|
+
from: z.ZodLiteral<"agent.label">;
|
|
13378
|
+
key: z.ZodString;
|
|
13379
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13380
|
+
from: z.ZodLiteral<"agent.id">;
|
|
13381
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13382
|
+
from: z.ZodLiteral<"session.owner">;
|
|
13383
|
+
}, z.core.$strict>], "from">>>;
|
|
13360
13384
|
}, z.core.$strict>>;
|
|
13361
13385
|
auth: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13362
13386
|
type: z.ZodLiteral<"api_key">;
|
|
@@ -13367,7 +13391,9 @@ export declare const SeedTenantConfigRequest: z.ZodObject<{
|
|
|
13367
13391
|
refresh: z.ZodString;
|
|
13368
13392
|
access: z.ZodString;
|
|
13369
13393
|
expires: z.ZodNumber;
|
|
13370
|
-
}, z.core.$loose
|
|
13394
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
13395
|
+
type: z.ZodLiteral<"workload">;
|
|
13396
|
+
}, z.core.$strict>], "type">;
|
|
13371
13397
|
}, z.core.$strict>>;
|
|
13372
13398
|
fixtureModel: z.ZodOptional<z.ZodLiteral<true>>;
|
|
13373
13399
|
}, z.core.$strict>;
|
|
@@ -13626,6 +13652,7 @@ export declare const ListProvidersResponse: z.ZodObject<{
|
|
|
13626
13652
|
authType: z.ZodEnum<{
|
|
13627
13653
|
api_key: "api_key";
|
|
13628
13654
|
oauth: "oauth";
|
|
13655
|
+
workload: "workload";
|
|
13629
13656
|
}>;
|
|
13630
13657
|
baseUrl: z.ZodOptional<z.ZodString>;
|
|
13631
13658
|
settings: z.ZodOptional<z.ZodObject<{
|
|
@@ -13641,6 +13668,15 @@ export declare const ListProvidersResponse: z.ZodObject<{
|
|
|
13641
13668
|
video: "video";
|
|
13642
13669
|
}>>>;
|
|
13643
13670
|
compat: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
13671
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
13672
|
+
callHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13673
|
+
from: z.ZodLiteral<"agent.label">;
|
|
13674
|
+
key: z.ZodString;
|
|
13675
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13676
|
+
from: z.ZodLiteral<"agent.id">;
|
|
13677
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13678
|
+
from: z.ZodLiteral<"session.owner">;
|
|
13679
|
+
}, z.core.$strict>], "from">>>;
|
|
13644
13680
|
}, z.core.$strict>>;
|
|
13645
13681
|
inputs: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
13646
13682
|
audio: "audio";
|
|
@@ -13663,6 +13699,7 @@ export declare const HostModelView: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
13663
13699
|
authType: z.ZodEnum<{
|
|
13664
13700
|
api_key: "api_key";
|
|
13665
13701
|
oauth: "oauth";
|
|
13702
|
+
workload: "workload";
|
|
13666
13703
|
}>;
|
|
13667
13704
|
baseUrl: z.ZodOptional<z.ZodString>;
|
|
13668
13705
|
settings: z.ZodOptional<z.ZodObject<{
|
|
@@ -13678,6 +13715,15 @@ export declare const HostModelView: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
13678
13715
|
video: "video";
|
|
13679
13716
|
}>>>;
|
|
13680
13717
|
compat: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
13718
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
13719
|
+
callHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13720
|
+
from: z.ZodLiteral<"agent.label">;
|
|
13721
|
+
key: z.ZodString;
|
|
13722
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13723
|
+
from: z.ZodLiteral<"agent.id">;
|
|
13724
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13725
|
+
from: z.ZodLiteral<"session.owner">;
|
|
13726
|
+
}, z.core.$strict>], "from">>>;
|
|
13681
13727
|
}, z.core.$strict>>;
|
|
13682
13728
|
}, z.core.$strict>]>;
|
|
13683
13729
|
export declare const PutHostModelRequest: z.ZodObject<{
|
|
@@ -13699,6 +13745,15 @@ export declare const PutHostModelRequest: z.ZodObject<{
|
|
|
13699
13745
|
video: "video";
|
|
13700
13746
|
}>>>;
|
|
13701
13747
|
compat: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
13748
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
13749
|
+
callHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13750
|
+
from: z.ZodLiteral<"agent.label">;
|
|
13751
|
+
key: z.ZodString;
|
|
13752
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13753
|
+
from: z.ZodLiteral<"agent.id">;
|
|
13754
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13755
|
+
from: z.ZodLiteral<"session.owner">;
|
|
13756
|
+
}, z.core.$strict>], "from">>>;
|
|
13702
13757
|
}, z.core.$strict>>;
|
|
13703
13758
|
auth: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13704
13759
|
type: z.ZodLiteral<"api_key">;
|
|
@@ -13709,7 +13764,9 @@ export declare const PutHostModelRequest: z.ZodObject<{
|
|
|
13709
13764
|
refresh: z.ZodString;
|
|
13710
13765
|
access: z.ZodString;
|
|
13711
13766
|
expires: z.ZodNumber;
|
|
13712
|
-
}, z.core.$loose
|
|
13767
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
13768
|
+
type: z.ZodLiteral<"workload">;
|
|
13769
|
+
}, z.core.$strict>], "type">;
|
|
13713
13770
|
}, z.core.$strict>;
|
|
13714
13771
|
export declare const SelectHostModelRequest: z.ZodObject<{
|
|
13715
13772
|
requestId: z.ZodString;
|
|
@@ -13740,6 +13797,7 @@ export declare const PutAgentSecretRequest: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
13740
13797
|
type: z.ZodLiteral<"bearer">;
|
|
13741
13798
|
url: z.ZodString;
|
|
13742
13799
|
value: z.ZodString;
|
|
13800
|
+
toolPrefix: z.ZodOptional<z.ZodString>;
|
|
13743
13801
|
}, z.core.$strict>, z.ZodObject<{
|
|
13744
13802
|
via: z.ZodOptional<z.ZodString>;
|
|
13745
13803
|
identity: z.ZodOptional<z.ZodObject<{
|
|
@@ -13749,6 +13807,16 @@ export declare const PutAgentSecretRequest: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
13749
13807
|
type: z.ZodLiteral<"headers">;
|
|
13750
13808
|
url: z.ZodString;
|
|
13751
13809
|
headers: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
13810
|
+
toolPrefix: z.ZodOptional<z.ZodString>;
|
|
13811
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
13812
|
+
requestId: z.ZodOptional<z.ZodString>;
|
|
13813
|
+
type: z.ZodLiteral<"workload">;
|
|
13814
|
+
url: z.ZodString;
|
|
13815
|
+
via: z.ZodString;
|
|
13816
|
+
identity: z.ZodOptional<z.ZodObject<{
|
|
13817
|
+
header: z.ZodString;
|
|
13818
|
+
}, z.core.$strict>>;
|
|
13819
|
+
toolPrefix: z.ZodOptional<z.ZodString>;
|
|
13752
13820
|
}, z.core.$strict>], "type">;
|
|
13753
13821
|
export declare const AgentSecretView: z.ZodObject<{
|
|
13754
13822
|
name: z.ZodString;
|
|
@@ -13757,6 +13825,7 @@ export declare const AgentSecretView: z.ZodObject<{
|
|
|
13757
13825
|
environment_secret: "environment_secret";
|
|
13758
13826
|
environment_variable: "environment_variable";
|
|
13759
13827
|
headers: "headers";
|
|
13828
|
+
workload: "workload";
|
|
13760
13829
|
}>;
|
|
13761
13830
|
binding: z.ZodObject<{
|
|
13762
13831
|
url: z.ZodOptional<z.ZodString>;
|
|
@@ -13768,6 +13837,7 @@ export declare const AgentSecretView: z.ZodObject<{
|
|
|
13768
13837
|
}, z.core.$strict>;
|
|
13769
13838
|
headerNames: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
13770
13839
|
via: z.ZodOptional<z.ZodString>;
|
|
13840
|
+
toolPrefix: z.ZodOptional<z.ZodString>;
|
|
13771
13841
|
identity: z.ZodOptional<z.ZodObject<{
|
|
13772
13842
|
header: z.ZodString;
|
|
13773
13843
|
}, z.core.$strict>>;
|
|
@@ -13782,6 +13852,7 @@ export declare const ListAgentSecretsResponse: z.ZodObject<{
|
|
|
13782
13852
|
environment_secret: "environment_secret";
|
|
13783
13853
|
environment_variable: "environment_variable";
|
|
13784
13854
|
headers: "headers";
|
|
13855
|
+
workload: "workload";
|
|
13785
13856
|
}>;
|
|
13786
13857
|
binding: z.ZodObject<{
|
|
13787
13858
|
url: z.ZodOptional<z.ZodString>;
|
|
@@ -13793,6 +13864,7 @@ export declare const ListAgentSecretsResponse: z.ZodObject<{
|
|
|
13793
13864
|
}, z.core.$strict>;
|
|
13794
13865
|
headerNames: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
13795
13866
|
via: z.ZodOptional<z.ZodString>;
|
|
13867
|
+
toolPrefix: z.ZodOptional<z.ZodString>;
|
|
13796
13868
|
identity: z.ZodOptional<z.ZodObject<{
|
|
13797
13869
|
header: z.ZodString;
|
|
13798
13870
|
}, z.core.$strict>>;
|
|
@@ -16210,6 +16282,7 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
16210
16282
|
code: z.ZodString;
|
|
16211
16283
|
message: z.ZodString;
|
|
16212
16284
|
server: z.ZodOptional<z.ZodString>;
|
|
16285
|
+
gateway: z.ZodOptional<z.ZodString>;
|
|
16213
16286
|
retryable: z.ZodOptional<z.ZodBoolean>;
|
|
16214
16287
|
}, z.core.$loose>>;
|
|
16215
16288
|
redacted: z.ZodOptional<z.ZodNumber>;
|
|
@@ -18942,6 +19015,7 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
18942
19015
|
code: z.ZodString;
|
|
18943
19016
|
message: z.ZodString;
|
|
18944
19017
|
server: z.ZodOptional<z.ZodString>;
|
|
19018
|
+
gateway: z.ZodOptional<z.ZodString>;
|
|
18945
19019
|
retryable: z.ZodOptional<z.ZodBoolean>;
|
|
18946
19020
|
}, z.core.$loose>>;
|
|
18947
19021
|
redacted: z.ZodOptional<z.ZodNumber>;
|
|
@@ -19,26 +19,15 @@ import { createServer } from "node:http";
|
|
|
19
19
|
import { Agent, request } from "node:https";
|
|
20
20
|
import { createSecureContext, TLSSocket } from "node:tls";
|
|
21
21
|
import { hostTuning } from "../tuning.js";
|
|
22
|
+
import { HOP_BY_HOP_HEADERS } from "../vault/headers.js";
|
|
22
23
|
/** The answer to a CONNECT the gate serves; a tunnel's byte counts leave it out. */
|
|
23
24
|
export const CONNECT_ESTABLISHED = "HTTP/1.1 200 Connection Established\r\n\r\n";
|
|
24
|
-
/** Headers that describe one hop and are never forwarded. */
|
|
25
|
-
const HOP_BY_HOP = new Set([
|
|
26
|
-
"connection",
|
|
27
|
-
"keep-alive",
|
|
28
|
-
"proxy-authenticate",
|
|
29
|
-
"proxy-authorization",
|
|
30
|
-
"proxy-connection",
|
|
31
|
-
"te",
|
|
32
|
-
"trailer",
|
|
33
|
-
"transfer-encoding",
|
|
34
|
-
"upgrade",
|
|
35
|
-
]);
|
|
36
25
|
/** `rawHeaders` without hop-by-hop headers and `drop`, as lowercase names to values. */
|
|
37
26
|
function forwardable(raw, drop) {
|
|
38
27
|
const headers = {};
|
|
39
28
|
for (let i = 0; i + 1 < raw.length; i += 2) {
|
|
40
29
|
const name = raw[i].toLowerCase();
|
|
41
|
-
if (
|
|
30
|
+
if (HOP_BY_HOP_HEADERS.has(name) || name === drop)
|
|
42
31
|
continue;
|
|
43
32
|
(headers[name] ??= []).push(raw[i + 1]);
|
|
44
33
|
}
|
package/dist/gates/handler.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* the Tenant's ledger. Logs one line per call, never the prompt, the output or a credential.
|
|
7
7
|
*/
|
|
8
8
|
import { classifyThrown } from "../model/classify.js";
|
|
9
|
-
import { callFiles, inProcessModelGate, modelCallSettings, serve } from "./in-process.js";
|
|
9
|
+
import { callCaller, callFiles, inProcessModelGate, modelCallSettings, serve } from "./in-process.js";
|
|
10
10
|
import { createMeter } from "./meter.js";
|
|
11
11
|
import { GateRefusal } from "./tenant-vaults.js";
|
|
12
12
|
export function createModelCallHandler(options) {
|
|
@@ -28,6 +28,7 @@ export function createModelCallHandler(options) {
|
|
|
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) } : {}),
|
|
31
|
+
caller: callCaller(vault.store),
|
|
31
32
|
});
|
|
32
33
|
outcome = await meter.call(vault.store, call, () => serve(vault.store, gate, call, signal));
|
|
33
34
|
}
|
|
@@ -11,6 +11,7 @@ import type { HostModelSecret } from "../vault/service.js";
|
|
|
11
11
|
import type { ModelGate, ModelGateRequest } from "./model-gate.js";
|
|
12
12
|
import { type FileResolver } from "../artifacts/files.js";
|
|
13
13
|
import type { BlobStore } from "../blob/index.js";
|
|
14
|
+
import type { ModelCaller } from "../model/call-headers.js";
|
|
14
15
|
export interface InProcessModelGateOptions {
|
|
15
16
|
/** The Tenant's home: `piModel` redacts secrets it finds there from failure messages. */
|
|
16
17
|
readonly root?: string;
|
|
@@ -20,6 +21,8 @@ export interface InProcessModelGateOptions {
|
|
|
20
21
|
readonly settings?: ModelCallSettings;
|
|
21
22
|
/** Reads the files a call's prompt names (protocol 6): artifacts, for model-gate. */
|
|
22
23
|
readonly files?: (request: ModelGateRequest) => FileResolver;
|
|
24
|
+
/** Reads who makes a call, for a custom endpoint's per-call headers (#493). */
|
|
25
|
+
readonly caller?: (request: ModelGateRequest) => Promise<ModelCaller | undefined>;
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
25
28
|
* The files a call names, from the Tenant's artifacts, limited to the call's session: in
|
|
@@ -27,6 +30,12 @@ export interface InProcessModelGateOptions {
|
|
|
27
30
|
* gate's route puts on the request (F5). A request without a session reads no file at all.
|
|
28
31
|
*/
|
|
29
32
|
export declare function callFiles(store: SessionStore, blobs: BlobStore): (request: Pick<ModelGateRequest, "sessionId">) => FileResolver;
|
|
33
|
+
/**
|
|
34
|
+
* Who makes a call, from the Tenant's store: the Agent its session runs on, with its labels, and
|
|
35
|
+
* the session's owner when it is a person. The session is the loop's own in process, and the run
|
|
36
|
+
* token's over HTTP; the request's `agentId` names the manifest's agent, not the Agent.
|
|
37
|
+
*/
|
|
38
|
+
export declare function callCaller(store: SessionStore): (request: Pick<ModelGateRequest, "sessionId">) => Promise<ModelCaller | undefined>;
|
|
30
39
|
/**
|
|
31
40
|
* The in-process gate of an open Tenant: reads its host model from its own vault and records
|
|
32
41
|
* each call in its usage ledger. Only a Runtime without the gates service (embedding, the
|
package/dist/gates/in-process.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createMeter } from "./meter.js";
|
|
|
5
5
|
import { artifactFiles } from "../artifacts/files.js";
|
|
6
6
|
import { usesFixtureModel } from "../tenant/model-setting.js";
|
|
7
7
|
import { fixtureAnswer } from "./fixture-model.js";
|
|
8
|
+
import { isSubject } from "@nylorun/core/contracts";
|
|
8
9
|
/**
|
|
9
10
|
* The files a call names, from the Tenant's artifacts, limited to the call's session: in
|
|
10
11
|
* process, the loop's own request; over HTTP, the session of the run token's claims, which the
|
|
@@ -13,6 +14,24 @@ import { fixtureAnswer } from "./fixture-model.js";
|
|
|
13
14
|
export function callFiles(store, blobs) {
|
|
14
15
|
return (request) => artifactFiles({ store, blobs, sessionId: request.sessionId });
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Who makes a call, from the Tenant's store: the Agent its session runs on, with its labels, and
|
|
19
|
+
* the session's owner when it is a person. The session is the loop's own in process, and the run
|
|
20
|
+
* token's over HTTP; the request's `agentId` names the manifest's agent, not the Agent.
|
|
21
|
+
*/
|
|
22
|
+
export function callCaller(store) {
|
|
23
|
+
return (request) => store.tx(async (t) => {
|
|
24
|
+
const session = await t.get("sessions", request.sessionId);
|
|
25
|
+
const agent = session && (await t.environment(session.agentId));
|
|
26
|
+
if (!session || !agent)
|
|
27
|
+
return undefined;
|
|
28
|
+
return {
|
|
29
|
+
agentId: agent.id,
|
|
30
|
+
labels: agent.labels,
|
|
31
|
+
...(isSubject(session.ownerUserId) ? { owner: session.ownerUserId } : {}),
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
16
35
|
/**
|
|
17
36
|
* The in-process gate of an open Tenant: reads its host model from its own vault and records
|
|
18
37
|
* each call in its usage ledger. Only a Runtime without the gates service (embedding, the
|
|
@@ -30,6 +49,7 @@ export function tenantModelGate(options) {
|
|
|
30
49
|
writeHostCredential: (credential) => vault.updateHostCredential(credential),
|
|
31
50
|
settings: await modelCallSettings(options.store),
|
|
32
51
|
...(options.blobs ? { files: callFiles(options.store, options.blobs) } : {}),
|
|
52
|
+
caller: callCaller(options.store),
|
|
33
53
|
});
|
|
34
54
|
return serve(options.store, gate, request, signal);
|
|
35
55
|
}),
|
|
@@ -58,6 +78,7 @@ export function inProcessModelGate(options) {
|
|
|
58
78
|
writeHostCredential: options.writeHostCredential,
|
|
59
79
|
...(options.settings ? { settings: options.settings } : {}),
|
|
60
80
|
...(options.files ? { files: options.files(request) } : {}),
|
|
81
|
+
...(options.caller ? { caller: () => options.caller(request) } : {}),
|
|
61
82
|
});
|
|
62
83
|
return adapter(request.call, {
|
|
63
84
|
// The Runtime never journals the provider request (harness `durable.ts`), and
|
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 { useWorkloadToken } from "../vault/workload-token.js";
|
|
68
69
|
const nodeRequire = createRequire(import.meta.url);
|
|
69
70
|
function coreVersion() {
|
|
70
71
|
try {
|
|
@@ -218,6 +219,7 @@ export async function main() {
|
|
|
218
219
|
// Read once, before any service starts: each reads the parts it uses where it uses them.
|
|
219
220
|
if (stack.tuning)
|
|
220
221
|
useHostTuning(stack.tuning.values, stack.tuning.overrides);
|
|
222
|
+
useWorkloadToken(stack.workloadToken ?? {});
|
|
221
223
|
if (stack.services.has("gates") || stack.services.has("keys") || stack.services.has("egress"))
|
|
222
224
|
return runGates(stack);
|
|
223
225
|
if (stack.services.has("harness"))
|
|
@@ -178,6 +178,16 @@ export interface HarnessServiceConfig {
|
|
|
178
178
|
export interface StackConfig {
|
|
179
179
|
/** The Runtime services this process runs. */
|
|
180
180
|
services: RuntimeServices;
|
|
181
|
+
/**
|
|
182
|
+
* `NYLORUN_WORKLOAD_TOKEN_FILE`, the file of the Runtime's workload token, which a platform
|
|
183
|
+
* rotates and the Runtime reads at each use, and `NYLORUN_WORKLOAD_TOKEN_ORIGINS`, the
|
|
184
|
+
* comma-separated origins a `workload` credential's `via` may send it to (#496,
|
|
185
|
+
* `vault/workload-token.ts`). Absent: no workload token.
|
|
186
|
+
*/
|
|
187
|
+
workloadToken?: {
|
|
188
|
+
file?: string;
|
|
189
|
+
origins?: string[];
|
|
190
|
+
};
|
|
181
191
|
/** Present when the process runs gates. */
|
|
182
192
|
gates?: GatesConfig;
|
|
183
193
|
/** Present when the process runs egress. */
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
import { DEFAULT_SERVICE_NAME } from "../traces/otlp.js";
|
|
48
48
|
import { TRACE_CONTENT_KINDS } from "../traces/map.js";
|
|
49
49
|
import { isTenantId } from "@nylorun/core/compatibility";
|
|
50
|
+
import { LOOPBACK_HOSTS } from "@nylorun/core/contracts";
|
|
50
51
|
import { blockedAddresses } from "../sandbox/pods/network-gate.js";
|
|
51
52
|
import { HostTuningError, parseHostTuning } from "../tuning.js";
|
|
52
53
|
export const RUNTIME_SERVICES = ["core", "loop", "gates", "keys", "egress", "harness"];
|
|
@@ -325,6 +326,7 @@ export function parseStackConfig(env, argv) {
|
|
|
325
326
|
throw new StackConfigError("NYLORUN_HARNESS_LISTEN_PORT must differ from NYLORUN_LISTEN_PORT");
|
|
326
327
|
const delivery = parseDelivery(env);
|
|
327
328
|
const tenant = servesApi ? parseTenant(env) : undefined;
|
|
329
|
+
const workloadToken = parseWorkloadToken(env);
|
|
328
330
|
const objectStore = parseObjectStore(env);
|
|
329
331
|
const traces = services.has("core") ? parseTraces(env) : undefined;
|
|
330
332
|
const removedResolverVariables = Object.keys(env)
|
|
@@ -347,6 +349,7 @@ export function parseStackConfig(env, argv) {
|
|
|
347
349
|
...(sandboxes ? { sandboxes } : {}),
|
|
348
350
|
...(delivery ? { delivery } : {}),
|
|
349
351
|
...(tenant ? { tenant } : {}),
|
|
352
|
+
...(workloadToken ? { workloadToken } : {}),
|
|
350
353
|
...(objectStore ? { objectStore } : {}),
|
|
351
354
|
...(traces ? { traces } : {}),
|
|
352
355
|
...(tuning ? { tuning } : {}),
|
|
@@ -454,6 +457,39 @@ function parseTenant(env) {
|
|
|
454
457
|
...(managementKeyFile ? { managementKeyFile } : {}),
|
|
455
458
|
};
|
|
456
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* `StackConfig.workloadToken` (#496): the Runtime's workload token, which the gates read for a
|
|
462
|
+
* custom model and for `workload` credentials, and the in-process Tenant does without them.
|
|
463
|
+
*/
|
|
464
|
+
function parseWorkloadToken(env) {
|
|
465
|
+
const file = read(env, "NYLORUN_WORKLOAD_TOKEN_FILE");
|
|
466
|
+
const origins = parseOrigins(read(env, "NYLORUN_WORKLOAD_TOKEN_ORIGINS"));
|
|
467
|
+
if (file === undefined && origins === undefined)
|
|
468
|
+
return undefined;
|
|
469
|
+
return { ...(file ? { file } : {}), ...(origins ? { origins } : {}) };
|
|
470
|
+
}
|
|
471
|
+
/** `NYLORUN_WORKLOAD_TOKEN_ORIGINS`: each an `https` origin (`http` only to a loopback host). */
|
|
472
|
+
function parseOrigins(raw) {
|
|
473
|
+
if (raw === undefined)
|
|
474
|
+
return undefined;
|
|
475
|
+
return raw
|
|
476
|
+
.split(",")
|
|
477
|
+
.map((item) => item.trim())
|
|
478
|
+
.filter((item) => item !== "")
|
|
479
|
+
.map((item) => {
|
|
480
|
+
let url;
|
|
481
|
+
try {
|
|
482
|
+
url = new URL(item);
|
|
483
|
+
}
|
|
484
|
+
catch {
|
|
485
|
+
throw new StackConfigError(`NYLORUN_WORKLOAD_TOKEN_ORIGINS: ${item} is not a URL`);
|
|
486
|
+
}
|
|
487
|
+
const loopback = url.protocol === "http:" && LOOPBACK_HOSTS.test(url.hostname);
|
|
488
|
+
if ((url.protocol !== "https:" && !loopback) || url.origin !== item.replace(/\/$/, ""))
|
|
489
|
+
throw new StackConfigError(`NYLORUN_WORKLOAD_TOKEN_ORIGINS: ${item} must be an https origin, such as https://gateway.example.com`);
|
|
490
|
+
return url.origin;
|
|
491
|
+
});
|
|
492
|
+
}
|
|
457
493
|
const GATES_TOKEN = /^[0-9a-f]{64,}$/i;
|
|
458
494
|
/** `NYLORUN_HARNESS`: `in-process` (the default when unset) or `remote`. */
|
|
459
495
|
function parseHarnessMode(env) {
|