@nylorun/runtime 0.32.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 +20 -0
- package/dist/api/components.d.ts +35 -0
- package/dist/api/components.js +3 -1
- package/dist/api/http/routes/sessions.js +63 -2
- package/dist/api/openapi.js +3 -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 +60 -5
- 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 +515 -2
- 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,25 @@
|
|
|
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
|
+
|
|
3
23
|
## 0.32.0-beta
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
package/dist/api/components.d.ts
CHANGED
|
@@ -2421,6 +2421,30 @@ export declare const SessionView: z.ZodObject<{
|
|
|
2421
2421
|
error: z.ZodUnknown;
|
|
2422
2422
|
}, z.core.$strict>>;
|
|
2423
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>]>;
|
|
2424
2448
|
export declare const LiveEvent: z.ZodObject<{
|
|
2425
2449
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
2426
2450
|
eventId: z.ZodString;
|
|
@@ -13457,6 +13481,7 @@ export declare const TenantStatus: z.ZodObject<{
|
|
|
13457
13481
|
model: z.ZodString;
|
|
13458
13482
|
authType: z.ZodEnum<{
|
|
13459
13483
|
api_key: "api_key";
|
|
13484
|
+
host_identity: "host_identity";
|
|
13460
13485
|
oauth: "oauth";
|
|
13461
13486
|
workload: "workload";
|
|
13462
13487
|
}>;
|
|
@@ -13622,6 +13647,10 @@ export declare const SeedTenantConfigRequest: z.ZodObject<{
|
|
|
13622
13647
|
expires: z.ZodNumber;
|
|
13623
13648
|
}, z.core.$loose>, z.ZodObject<{
|
|
13624
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;
|
|
13625
13654
|
}, z.core.$strict>], "type">;
|
|
13626
13655
|
}, z.core.$strict>>;
|
|
13627
13656
|
fixtureModel: z.ZodOptional<z.ZodLiteral<true>>;
|
|
@@ -13880,6 +13909,7 @@ export declare const ListProvidersResponse: z.ZodObject<{
|
|
|
13880
13909
|
model: z.ZodString;
|
|
13881
13910
|
authType: z.ZodEnum<{
|
|
13882
13911
|
api_key: "api_key";
|
|
13912
|
+
host_identity: "host_identity";
|
|
13883
13913
|
oauth: "oauth";
|
|
13884
13914
|
workload: "workload";
|
|
13885
13915
|
}>;
|
|
@@ -13927,6 +13957,7 @@ export declare const HostModelView: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
13927
13957
|
model: z.ZodString;
|
|
13928
13958
|
authType: z.ZodEnum<{
|
|
13929
13959
|
api_key: "api_key";
|
|
13960
|
+
host_identity: "host_identity";
|
|
13930
13961
|
oauth: "oauth";
|
|
13931
13962
|
workload: "workload";
|
|
13932
13963
|
}>;
|
|
@@ -13995,6 +14026,10 @@ export declare const PutHostModelRequest: z.ZodObject<{
|
|
|
13995
14026
|
expires: z.ZodNumber;
|
|
13996
14027
|
}, z.core.$loose>, z.ZodObject<{
|
|
13997
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;
|
|
13998
14033
|
}, z.core.$strict>], "type">;
|
|
13999
14034
|
}, z.core.$strict>;
|
|
14000
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, 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";
|
|
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
|
}
|
|
@@ -77,6 +77,8 @@ export const WebhookAcceptedResponse = named("WebhookAcceptedResponse", WebhookA
|
|
|
77
77
|
export const ListSessionsResponse = named("ListSessionsResponse", ListSessionsResponseSchema);
|
|
78
78
|
export const PutSessionRequest = named("PutSessionRequest", PutSessionRequestSchema);
|
|
79
79
|
export const SessionView = named("SessionView", SessionViewSchema);
|
|
80
|
+
export const PutSessionModelRequest = named("PutSessionModelRequest", PutSessionModelRequestSchema);
|
|
81
|
+
export const SessionModelView = named("SessionModelView", SessionModelViewSchema);
|
|
80
82
|
export const LiveEvent = named("LiveEvent", LiveEventSchema);
|
|
81
83
|
/** `environment.state` → `EnvironmentStateEvent`. */
|
|
82
84
|
export function eventComponentName(type) {
|
|
@@ -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
|
@@ -194,6 +194,9 @@ const RUNTIME_TAGS = [
|
|
|
194
194
|
"GET /v1/sessions/{sessionId}/events",
|
|
195
195
|
"GET /v1/sessions/{sessionId}/items",
|
|
196
196
|
"GET /v1/sessions/{sessionId}/manifest",
|
|
197
|
+
"GET /v1/sessions/{sessionId}/model",
|
|
198
|
+
"PUT /v1/sessions/{sessionId}/model",
|
|
199
|
+
"DELETE /v1/sessions/{sessionId}/model",
|
|
197
200
|
"GET /v1/sessions/{sessionId}/usage",
|
|
198
201
|
"GET /v1/sessions/{sessionId}/calls/model",
|
|
199
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)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.2.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Nylorun Management API",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.33.0-beta",
|
|
6
6
|
"x-nylorun-protocol": {
|
|
7
7
|
"min": 16,
|
|
8
8
|
"max": 18,
|
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
"traces",
|
|
35
35
|
"artifact-reads",
|
|
36
36
|
"gateway-credentials",
|
|
37
|
-
"agent-folders"
|
|
37
|
+
"agent-folders",
|
|
38
|
+
"session-model",
|
|
39
|
+
"model-host-identity"
|
|
38
40
|
]
|
|
39
41
|
},
|
|
40
42
|
"description": "For operators: the Tenant's models, vaults, signing keys, settings and application keys, at `/v1/tenant/*` on the Tenant's URL, through `@nylorun/admin`. Every operation takes a management key, acting as itself: never for a subject and never from a browser. Management keys are issued only on the Tenant's machine (`nylorun tenant keys put <id> --management`) or from `NYLORUN_MANAGEMENT_KEY_FILE`."
|
|
@@ -427,7 +429,8 @@
|
|
|
427
429
|
"enum": [
|
|
428
430
|
"api_key",
|
|
429
431
|
"oauth",
|
|
430
|
-
"workload"
|
|
432
|
+
"workload",
|
|
433
|
+
"host_identity"
|
|
431
434
|
]
|
|
432
435
|
},
|
|
433
436
|
"baseUrl": {
|
|
@@ -1137,6 +1140,31 @@
|
|
|
1137
1140
|
"type"
|
|
1138
1141
|
],
|
|
1139
1142
|
"additionalProperties": false
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
"type": "object",
|
|
1146
|
+
"properties": {
|
|
1147
|
+
"type": {
|
|
1148
|
+
"type": "string",
|
|
1149
|
+
"enum": [
|
|
1150
|
+
"host_identity"
|
|
1151
|
+
]
|
|
1152
|
+
},
|
|
1153
|
+
"project": {
|
|
1154
|
+
"type": "string",
|
|
1155
|
+
"pattern": "^[a-z][a-z0-9-]{4,28}[a-z0-9]$"
|
|
1156
|
+
},
|
|
1157
|
+
"location": {
|
|
1158
|
+
"type": "string",
|
|
1159
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1162
|
+
"required": [
|
|
1163
|
+
"type",
|
|
1164
|
+
"project",
|
|
1165
|
+
"location"
|
|
1166
|
+
],
|
|
1167
|
+
"additionalProperties": false
|
|
1140
1168
|
}
|
|
1141
1169
|
]
|
|
1142
1170
|
}
|
|
@@ -2680,7 +2708,8 @@
|
|
|
2680
2708
|
"enum": [
|
|
2681
2709
|
"api_key",
|
|
2682
2710
|
"oauth",
|
|
2683
|
-
"workload"
|
|
2711
|
+
"workload",
|
|
2712
|
+
"host_identity"
|
|
2684
2713
|
]
|
|
2685
2714
|
},
|
|
2686
2715
|
"baseUrl": {
|
|
@@ -2860,7 +2889,8 @@
|
|
|
2860
2889
|
"enum": [
|
|
2861
2890
|
"api_key",
|
|
2862
2891
|
"oauth",
|
|
2863
|
-
"workload"
|
|
2892
|
+
"workload",
|
|
2893
|
+
"host_identity"
|
|
2864
2894
|
]
|
|
2865
2895
|
},
|
|
2866
2896
|
"baseUrl": {
|
|
@@ -3170,6 +3200,31 @@
|
|
|
3170
3200
|
"type"
|
|
3171
3201
|
],
|
|
3172
3202
|
"additionalProperties": false
|
|
3203
|
+
},
|
|
3204
|
+
{
|
|
3205
|
+
"type": "object",
|
|
3206
|
+
"properties": {
|
|
3207
|
+
"type": {
|
|
3208
|
+
"type": "string",
|
|
3209
|
+
"enum": [
|
|
3210
|
+
"host_identity"
|
|
3211
|
+
]
|
|
3212
|
+
},
|
|
3213
|
+
"project": {
|
|
3214
|
+
"type": "string",
|
|
3215
|
+
"pattern": "^[a-z][a-z0-9-]{4,28}[a-z0-9]$"
|
|
3216
|
+
},
|
|
3217
|
+
"location": {
|
|
3218
|
+
"type": "string",
|
|
3219
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
3220
|
+
}
|
|
3221
|
+
},
|
|
3222
|
+
"required": [
|
|
3223
|
+
"type",
|
|
3224
|
+
"project",
|
|
3225
|
+
"location"
|
|
3226
|
+
],
|
|
3227
|
+
"additionalProperties": false
|
|
3173
3228
|
}
|
|
3174
3229
|
]
|
|
3175
3230
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* gate takes cannot disagree.
|
|
8
8
|
*/
|
|
9
9
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
10
|
-
import { type CustomModelSettings, type HostModelView, type ModelInput } from "@nylorun/core/contracts";
|
|
10
|
+
import { type CustomModelSettings, type HostModelView, type ModelInput, type SessionModelChoice } from "@nylorun/core/contracts";
|
|
11
11
|
import type { ModelDescriptor } from "@nylorun/core/harness-api";
|
|
12
12
|
import type { SessionStore } from "../store/types.js";
|
|
13
13
|
import { type Selection } from "./models.js";
|
|
@@ -36,14 +36,15 @@ export declare const FIXTURE_DESCRIPTOR: ModelDescriptor;
|
|
|
36
36
|
export declare function hostModelDescriptor(binding: ModelBindingView, added?: Readonly<Record<string, readonly ModelInput[]>>): ModelDescriptor | undefined;
|
|
37
37
|
/**
|
|
38
38
|
* The model the Tenant's turns use now: the fixture model's descriptor when the Tenant uses it,
|
|
39
|
-
* else
|
|
39
|
+
* else a session's own model's (`choice`, while its provider is connected), else its active
|
|
40
|
+
* model's; undefined when none is configured (a test's scripted provider, say).
|
|
40
41
|
*/
|
|
41
42
|
export declare function currentModelDescriptor(ctx: {
|
|
42
43
|
readonly store: SessionStore;
|
|
43
44
|
readonly vault: {
|
|
44
|
-
getHostModel(): Promise<HostModelView>;
|
|
45
|
+
getHostModel(choice?: SessionModelChoice): Promise<HostModelView>;
|
|
45
46
|
};
|
|
46
|
-
}): Promise<ModelDescriptor | undefined>;
|
|
47
|
+
}, choice?: SessionModelChoice): Promise<ModelDescriptor | undefined>;
|
|
47
48
|
/**
|
|
48
49
|
* The context window, in tokens, of the Tenant's model now; without one, or one the catalog does
|
|
49
50
|
* not know, it is assumed small (`CUSTOM_MODEL_SETTING_DEFAULTS`), as for a custom endpoint.
|
package/dist/model/descriptor.js
CHANGED
|
@@ -62,16 +62,17 @@ export function hostModelDescriptor(binding, added = {}) {
|
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* The model the Tenant's turns use now: the fixture model's descriptor when the Tenant uses it,
|
|
65
|
-
* else
|
|
65
|
+
* else a session's own model's (`choice`, while its provider is connected), else its active
|
|
66
|
+
* model's; undefined when none is configured (a test's scripted provider, say).
|
|
66
67
|
*/
|
|
67
|
-
export async function currentModelDescriptor(ctx) {
|
|
68
|
+
export async function currentModelDescriptor(ctx, choice) {
|
|
68
69
|
const { fixture, added } = await ctx.store.tx(async (t) => ({
|
|
69
70
|
fixture: await usesFixtureModel(t),
|
|
70
71
|
added: await readAddedInputs(t),
|
|
71
72
|
}));
|
|
72
73
|
if (fixture)
|
|
73
74
|
return FIXTURE_DESCRIPTOR;
|
|
74
|
-
const view = await ctx.vault.getHostModel();
|
|
75
|
+
const view = await ctx.vault.getHostModel(choice);
|
|
75
76
|
return view.configured ? hostModelDescriptor(view, added) : undefined;
|
|
76
77
|
}
|
|
77
78
|
/**
|
package/dist/model/pi-model.js
CHANGED
|
@@ -8,6 +8,7 @@ import { classifyAssistantError, failure } from "./classify.js";
|
|
|
8
8
|
import { addedInputsOf, describeModel, selectionOf } from "./descriptor.js";
|
|
9
9
|
import { modelsFor } from "./models.js";
|
|
10
10
|
import { callHeaders } from "./call-headers.js";
|
|
11
|
+
import { hostIdentityRefused, VERTEX_ADC_MARKER } from "../vault/host-identity.js";
|
|
11
12
|
import { workloadToken, WorkloadTokenUnavailable } from "../vault/workload-token.js";
|
|
12
13
|
import { NativeBlocks, nativeKindsOf } from "./native-blocks.js";
|
|
13
14
|
import { projectSecrets } from "./settings.js";
|
|
@@ -67,6 +68,12 @@ export function piModel(options = {}) {
|
|
|
67
68
|
throw error;
|
|
68
69
|
}
|
|
69
70
|
}
|
|
71
|
+
// The Host's identity (ADR-71): only while its operator still lends it.
|
|
72
|
+
if (stored.authType === "host_identity") {
|
|
73
|
+
const refused = hostIdentityRefused(stored.provider);
|
|
74
|
+
if (refused)
|
|
75
|
+
return failure("auth", refused, false);
|
|
76
|
+
}
|
|
70
77
|
const secrets = [
|
|
71
78
|
...projectSecrets(root),
|
|
72
79
|
...credentialSecrets(stored.credential),
|
|
@@ -119,6 +126,8 @@ export function piModel(options = {}) {
|
|
|
119
126
|
sessionId: call.executionId,
|
|
120
127
|
cacheRetention: "short",
|
|
121
128
|
...(Object.keys(perCall).length > 0 ? { headers: perCall } : {}),
|
|
129
|
+
// With the Host's identity: where Agent Platform runs the call (ADR-71).
|
|
130
|
+
...(stored.authType === "host_identity" && stored.credential.env ? { env: stored.credential.env } : {}),
|
|
122
131
|
timeoutMs: settings.requestTimeoutMs,
|
|
123
132
|
maxRetries: settings.providerRetries,
|
|
124
133
|
maxRetryDelayMs: settings.maxRetryDelayMs,
|
|
@@ -504,7 +513,11 @@ function idleTimeout(selected, idleTimeoutMs) {
|
|
|
504
513
|
};
|
|
505
514
|
}
|
|
506
515
|
function hostCredentialStore(stored, write) {
|
|
507
|
-
|
|
516
|
+
// The Host's identity (ADR-71): pi-ai's Vertex AI client uses Application Default Credentials
|
|
517
|
+
// for this marker in place of a key.
|
|
518
|
+
let current = stored.authType === "host_identity"
|
|
519
|
+
? { type: "api_key", key: VERTEX_ADC_MARKER }
|
|
520
|
+
: stored.credential;
|
|
508
521
|
// A workload model stores no credential: pi-ai then asks the provider's `resolve` (`modelsFor`).
|
|
509
522
|
const stores = stored.authType !== "workload";
|
|
510
523
|
return {
|
|
@@ -532,6 +545,9 @@ function hostCredentialStore(stored, write) {
|
|
|
532
545
|
};
|
|
533
546
|
}
|
|
534
547
|
function credentialSecrets(credential) {
|
|
548
|
+
// The Host's identity keeps no secret: its project and location stay readable in messages.
|
|
549
|
+
if (credential.type === "host_identity")
|
|
550
|
+
return [];
|
|
535
551
|
const values = [credential.key, credential.access, credential.refresh];
|
|
536
552
|
if (credential.env)
|
|
537
553
|
values.push(...Object.values(credential.env));
|