@nylorun/runtime 0.24.0-beta → 0.25.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 +104 -0
- package/README.md +10 -2
- package/dist/api/a2a/card.d.ts +11 -1
- package/dist/api/a2a/card.js +26 -2
- package/dist/api/a2a/endpoint.js +4 -2
- package/dist/api/a2a/protocol.d.ts +25 -2
- package/dist/api/a2a/protocol.js +20 -3
- package/dist/api/a2a/routes.d.ts +4 -1
- package/dist/api/a2a/routes.js +65 -7
- package/dist/api/ag-ui/endpoint.js +5 -2
- package/dist/api/ag-ui/history.d.ts +6 -1
- package/dist/api/ag-ui/history.js +35 -2
- package/dist/api/ag-ui/routes.js +53 -11
- package/dist/api/components.d.ts +1165 -678
- package/dist/api/components.js +16 -1
- package/dist/api/gate/keys.d.ts +2 -1
- package/dist/api/gate/keys.js +7 -0
- package/dist/api/gate/routes.js +13 -0
- package/dist/api/http/app.js +13 -2
- package/dist/api/http/body.d.ts +3 -3
- package/dist/api/http/body.js +7 -7
- package/dist/api/http/routes/environment-manifests.d.ts +9 -0
- package/dist/api/http/routes/environment-manifests.js +118 -0
- package/dist/api/http/routes/environments.js +61 -12
- package/dist/api/http/routes/reads.d.ts +52 -3
- package/dist/api/http/routes/sessions.js +13 -3
- package/dist/api/http/routes/tenant.js +35 -7
- package/dist/api/inbound-files.d.ts +65 -0
- package/dist/api/inbound-files.js +115 -0
- package/dist/api/openapi.js +18 -3
- package/dist/artifacts/disk.js +20 -14
- package/dist/artifacts/media-types.d.ts +15 -0
- package/dist/artifacts/media-types.js +56 -4
- package/dist/artifacts/parts.d.ts +12 -3
- package/dist/artifacts/parts.js +15 -4
- package/dist/artifacts/workspace.d.ts +4 -4
- package/dist/artifacts/workspace.js +6 -18
- package/dist/core/flow-host.d.ts +1 -1
- package/dist/core/flow-host.js +2 -2
- package/dist/core/sandbox-routes.js +2 -2
- package/dist/core/turn-manifest.d.ts +3 -2
- package/dist/core/turn-manifest.js +29 -5
- package/dist/gates/egress-credentials.js +1 -1
- package/dist/gates/egress.d.ts +13 -19
- package/dist/gates/egress.js +30 -29
- package/dist/gates/http-tool.d.ts +3 -4
- package/dist/gates/http-tool.js +8 -12
- package/dist/gates/journal.js +0 -1
- package/dist/gates/mcp-handler.js +2 -3
- package/dist/gates/policy.js +1 -3
- package/dist/gates/tool-contract.d.ts +1 -1
- package/dist/harness/calls.d.ts +2 -2
- package/dist/harness/calls.js +9 -12
- package/dist/harness/main.js +7 -1
- package/dist/harness/pod.d.ts +6 -1
- package/dist/harness/pod.js +5 -0
- package/dist/harness/service.js +5 -5
- package/dist/harness/setup.d.ts +2 -0
- package/dist/harness/setup.js +25 -1
- package/dist/harness-api/record.d.ts +1 -1
- package/dist/harness-api/record.js +13 -13
- package/dist/harness-api/server.d.ts +27 -4
- package/dist/harness-api/server.js +41 -8
- package/dist/harness-api/tool-journal.d.ts +17 -8
- package/dist/harness-api/tool-journal.js +41 -11
- package/dist/harness-api/workspace.d.ts +7 -5
- package/dist/harness-api/workspace.js +25 -19
- package/dist/host/gates.js +2 -2
- package/dist/host/stack-config.js +1 -1
- package/dist/keys/keys.d.ts +9 -2
- package/dist/keys/keys.js +4 -1
- package/dist/management-openapi.json +366 -61
- package/dist/mcp/connect.d.ts +1 -2
- package/dist/mcp/connect.js +1 -4
- package/dist/mcp/pool.d.ts +1 -4
- package/dist/mcp/pool.js +13 -27
- package/dist/mcp/preview.js +0 -1
- package/dist/mcp/snapshot.d.ts +11 -13
- package/dist/mcp/snapshot.js +27 -38
- package/dist/model/capabilities.d.ts +26 -0
- package/dist/model/capabilities.js +44 -0
- package/dist/model/catalog.d.ts +34 -3
- package/dist/model/catalog.js +38 -2
- package/dist/model/models.d.ts +2 -0
- package/dist/model/models.js +1 -1
- package/dist/model/native-blocks.d.ts +35 -0
- package/dist/model/native-blocks.js +170 -0
- package/dist/model/pi-model.js +106 -94
- package/dist/openapi.json +9554 -5104
- package/dist/record/environment.js +1 -1
- package/dist/sandbox/join.js +4 -0
- package/dist/sandbox/manager.d.ts +32 -14
- package/dist/sandbox/manager.js +132 -93
- package/dist/sandbox/placement.d.ts +1 -1
- package/dist/sandbox/placement.js +2 -2
- package/dist/sandbox/pods/client.d.ts +3 -1
- package/dist/sandbox/pods/lifecycle.d.ts +8 -0
- package/dist/sandbox/pods/lifecycle.js +15 -0
- package/dist/sandbox/pods/spec.js +2 -1
- package/dist/sandbox/resolve.d.ts +5 -3
- package/dist/sandbox/resolve.js +9 -2
- package/dist/sandbox/runtime-tools.d.ts +9 -0
- package/dist/sandbox/runtime-tools.js +16 -0
- package/dist/sandbox/session-sandbox.d.ts +4 -6
- package/dist/sandbox/session-sandbox.js +47 -94
- package/dist/sandbox/setup.d.ts +4 -1
- package/dist/sandbox/setup.js +46 -9
- package/dist/sandbox/share.d.ts +12 -7
- package/dist/sandbox/share.js +27 -25
- package/dist/sandbox/skills.d.ts +8 -6
- package/dist/sandbox/skills.js +24 -23
- package/dist/store/postgres/drizzle/0024_flat_manifest.sql +7 -0
- package/dist/store/postgres/drizzle/0025_environment_manifests.sql +14 -0
- package/dist/store/postgres/drizzle/0026_environment_forks.sql +1 -0
- package/dist/store/postgres/drizzle/0027_environment_image_digest.sql +1 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
- package/dist/store/postgres/reads.js +8 -2
- package/dist/store/postgres/schema.d.ts +217 -0
- package/dist/store/postgres/schema.js +36 -2
- package/dist/store/postgres/store.js +79 -4
- package/dist/store/types.d.ts +68 -14
- package/dist/tenant/advance.js +3 -0
- package/dist/tenant/artifact-tool.d.ts +1 -1
- package/dist/tenant/artifact-tool.js +43 -22
- package/dist/tenant/commands.js +24 -4
- package/dist/tenant/context.d.ts +10 -4
- package/dist/tenant/effects.js +7 -9
- package/dist/tenant/environment-manifests.d.ts +57 -0
- package/dist/tenant/environment-manifests.js +200 -0
- package/dist/tenant/environments.d.ts +54 -47
- package/dist/tenant/environments.js +304 -83
- package/dist/tenant/model-setting.d.ts +14 -0
- package/dist/tenant/model-setting.js +51 -0
- package/dist/tenant/sessions.d.ts +5 -1
- package/dist/tenant/sessions.js +45 -12
- package/dist/tenant/skill-tool.d.ts +3 -3
- package/dist/tenant/skill-tool.js +6 -11
- package/dist/tenant/sweep.js +1 -1
- package/dist/tenant/tool-results.js +1 -1
- package/dist/tenant/tool-search.d.ts +7 -11
- package/dist/tenant/tool-search.js +8 -5
- package/dist/tenant/transcript.d.ts +51 -32
- package/dist/tenant/transcript.js +2 -1
- package/dist/traces/ids.d.ts +0 -1
- package/dist/traces/ids.js +0 -4
- package/dist/traces/map.d.ts +2 -2
- package/dist/traces/map.js +1 -29
- package/dist/vault/coverage.js +11 -13
- package/dist/vault/host-model.d.ts +4 -1
- package/dist/vault/host-model.js +10 -2
- package/dist/vault/service.d.ts +49 -4
- package/dist/vault/service.js +153 -6
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/sandbox/capability.d.ts +0 -3
- package/dist/sandbox/capability.js +0 -10
|
@@ -17,7 +17,10 @@ export declare class HostModelVault {
|
|
|
17
17
|
private readonly store;
|
|
18
18
|
private readonly kek;
|
|
19
19
|
constructor(options: HostModelVaultOptions);
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Reads the active host model secret, with the inputs the operator added to catalog models
|
|
22
|
+
* (protocol 12). Decrypts after the read commits.
|
|
23
|
+
*/
|
|
21
24
|
readHostModel(): Promise<HostModelSecret | undefined>;
|
|
22
25
|
/** Replaces the active host model's secret, keeping its binding. */
|
|
23
26
|
updateHostCredential(credential: {
|
package/dist/vault/host-model.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readAddedInputs } from "../tenant/model-setting.js";
|
|
1
2
|
import { encryptSecret } from "./crypto.js";
|
|
2
3
|
import { VaultError } from "./error.js";
|
|
3
4
|
import { activeHostCredentialRow, HOST_VAULT_ID, hostModelAad, modelBinding, readHostPayload, } from "./service.js";
|
|
@@ -8,9 +9,15 @@ export class HostModelVault {
|
|
|
8
9
|
this.store = options.store;
|
|
9
10
|
this.kek = options.kek;
|
|
10
11
|
}
|
|
11
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Reads the active host model secret, with the inputs the operator added to catalog models
|
|
14
|
+
* (protocol 12). Decrypts after the read commits.
|
|
15
|
+
*/
|
|
12
16
|
async readHostModel() {
|
|
13
|
-
const row = await this.store.tx((t) =>
|
|
17
|
+
const { row, addedInputs } = await this.store.tx(async (t) => ({
|
|
18
|
+
row: await activeHostCredentialRow(t),
|
|
19
|
+
addedInputs: await readAddedInputs(t),
|
|
20
|
+
}));
|
|
14
21
|
if (!row)
|
|
15
22
|
return undefined;
|
|
16
23
|
const binding = modelBinding(row);
|
|
@@ -27,6 +34,7 @@ export class HostModelVault {
|
|
|
27
34
|
model: binding.model,
|
|
28
35
|
...(binding.baseUrl ? { baseUrl: binding.baseUrl } : {}),
|
|
29
36
|
...(binding.settings ? { settings: binding.settings } : {}),
|
|
37
|
+
addedInputs,
|
|
30
38
|
authType: binding.authType,
|
|
31
39
|
credential,
|
|
32
40
|
};
|
package/dist/vault/service.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CredentialCoverage, CredentialCoverageRequest, CredentialIdentity, EnvironmentSecretView, HostModelProviderInfo, HostModelView, PutEnvironmentSecretRequest, PutHostModelRequest, CustomModelSettings, SelectHostModelRequest } from "@nylorun/core/contracts";
|
|
1
|
+
import type { CredentialCoverage, CredentialCoverageRequest, CredentialIdentity, EnvironmentSecretView, HostModelProviderInfo, HostModelView, PutEnvironmentSecretRequest, PutHostModelRequest, CustomModelSettings, ModelInput, SelectHostModelRequest } from "@nylorun/core/contracts";
|
|
2
2
|
import type { AgentManifest, WorkflowManifest } from "@nylorun/core/define";
|
|
3
3
|
import type { SessionStore, Tx, VaultCredentialRow } from "../store/types.js";
|
|
4
4
|
export declare const HOST_VAULT_ID = "host";
|
|
@@ -6,8 +6,10 @@ export type HostModelSecret = {
|
|
|
6
6
|
provider: string;
|
|
7
7
|
model: string;
|
|
8
8
|
baseUrl?: string;
|
|
9
|
-
/** A custom endpoint's window, output limit, reasoning and pi-ai compat (Model Calls §7). */
|
|
9
|
+
/** A custom endpoint's window, output limit, reasoning, inputs and pi-ai compat (Model Calls §7). */
|
|
10
10
|
settings?: CustomModelSettings;
|
|
11
|
+
/** The inputs the operator added to catalog models, by `<provider>/<model>` (protocol 12). */
|
|
12
|
+
addedInputs?: Readonly<Record<string, readonly ModelInput[]>>;
|
|
11
13
|
authType: "api_key" | "oauth";
|
|
12
14
|
credential: {
|
|
13
15
|
type: "api_key" | "oauth";
|
|
@@ -19,6 +21,28 @@ export type HostModelSecret = {
|
|
|
19
21
|
[key: string]: unknown;
|
|
20
22
|
};
|
|
21
23
|
};
|
|
24
|
+
type UserCredentialRow = VaultCredentialRow & {
|
|
25
|
+
type: "bearer" | "headers" | "environment_secret" | "environment_variable";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A fork's secrets sealed for its new vault (`sealEnvironmentSecretCopies`): each copy's
|
|
29
|
+
* ciphertext, base64 so it crosses the keys service's JSON, and what about it is not secret.
|
|
30
|
+
*/
|
|
31
|
+
export interface SealedSecretCopies {
|
|
32
|
+
readonly copies: readonly {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly type: UserCredentialRow["type"];
|
|
36
|
+
readonly bindingJson: string;
|
|
37
|
+
readonly expiresAt: string | null;
|
|
38
|
+
readonly kekId: string;
|
|
39
|
+
readonly nonce: string;
|
|
40
|
+
readonly ciphertext: string;
|
|
41
|
+
readonly wrappedDek: string;
|
|
42
|
+
}[];
|
|
43
|
+
/** Names left behind: no slot of the fork declares them, or their slot cannot take the value. */
|
|
44
|
+
readonly dropped: readonly string[];
|
|
45
|
+
}
|
|
22
46
|
export type AuthorizeResult = {
|
|
23
47
|
status: "unauthenticated";
|
|
24
48
|
url: string;
|
|
@@ -47,14 +71,35 @@ export declare class VaultService {
|
|
|
47
71
|
private readonly store;
|
|
48
72
|
private readonly kek;
|
|
49
73
|
constructor(options: VaultServiceOptions);
|
|
50
|
-
/**
|
|
51
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Creates Environment `environmentId`'s vault (D56), in the transaction that creates it; answers
|
|
76
|
+
* its id, `id` when given (a fork's, whose secrets were sealed for it first).
|
|
77
|
+
*/
|
|
78
|
+
createEnvironmentVault(t: Tx, environmentId: string, actor: string, id?: string): Promise<string>;
|
|
52
79
|
/**
|
|
53
80
|
* Deletes Environment `environmentId`'s vault and its credentials, with their audit rows, in
|
|
54
81
|
* the transaction that deletes the Environment: no release or tool call finds them after it
|
|
55
82
|
* commits.
|
|
56
83
|
*/
|
|
57
84
|
deleteEnvironmentVault(t: Tx, environmentId: string, actor: string): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Seals Environment `from`'s secrets again for vault `vaultId`, a fork's new vault (Q15): each
|
|
87
|
+
* value is unsealed and sealed under the new vault's and credential's ids, which its AAD binds.
|
|
88
|
+
* Needs the vault key, so callers reach it through `Keys`; it reads `from` in its own
|
|
89
|
+
* transaction and writes nothing. With `slots` (what the fork runs declares secret slots, D64),
|
|
90
|
+
* only the names it declares are sealed, each with its slot's binding; a value the slot's type
|
|
91
|
+
* cannot take is left behind. The fork's transaction inserts the copies
|
|
92
|
+
* (`insertEnvironmentSecretCopies`).
|
|
93
|
+
*/
|
|
94
|
+
sealEnvironmentSecretCopies(from: string, vaultId: string, slots?: Readonly<Record<string, Record<string, unknown>>> | null): Promise<SealedSecretCopies>;
|
|
95
|
+
/**
|
|
96
|
+
* Inserts a fork's sealed copies (`sealEnvironmentSecretCopies`) into vault `vaultId`, in the
|
|
97
|
+
* transaction that creates the fork, with an audit row each naming `from`. Reads no secret.
|
|
98
|
+
*/
|
|
99
|
+
insertEnvironmentSecretCopies(t: Tx, vaultId: string, from: string, actor: string, sealed: SealedSecretCopies): Promise<{
|
|
100
|
+
copied: string[];
|
|
101
|
+
dropped: string[];
|
|
102
|
+
}>;
|
|
58
103
|
/**
|
|
59
104
|
* `PUT /v1/environments/{id}/secrets/{name}`: creates or replaces one credential. The same
|
|
60
105
|
* name and type keeps the credential's id and re-seals its value and binding; another type
|
package/dist/vault/service.js
CHANGED
|
@@ -9,9 +9,15 @@
|
|
|
9
9
|
* new VaultService({ store: SessionStore, kek: () => Buffer })
|
|
10
10
|
*
|
|
11
11
|
* // An Environment's vault, in the caller's transaction (`tenant/environments.ts`).
|
|
12
|
-
* createEnvironmentVault(t: Tx, environmentId: string, actor: string): Promise<
|
|
12
|
+
* createEnvironmentVault(t: Tx, environmentId: string, actor: string, id?: string): Promise<string>
|
|
13
13
|
* deleteEnvironmentVault(t: Tx, environmentId: string, actor: string): Promise<void>
|
|
14
14
|
*
|
|
15
|
+
* // A fork's secrets (Q15): `Keys` seals the copies with the vault key in its own transaction,
|
|
16
|
+
* // before the fork's; the fork's transaction inserts them, so the process that forks never
|
|
17
|
+
* // holds the key.
|
|
18
|
+
* sealEnvironmentSecretCopies(from, vaultId, slots | null): Promise<SealedSecretCopies>
|
|
19
|
+
* insertEnvironmentSecretCopies(t: Tx, vaultId, from, actor, sealed): Promise<{ copied; dropped }>
|
|
20
|
+
*
|
|
15
21
|
* // Its secrets (`/v1/environments/{id}/secrets`): each opens its own transaction and writes its
|
|
16
22
|
* // audit rows in it. A put needs the vault key, so callers reach it through `Keys`.
|
|
17
23
|
* putEnvironmentSecret(environmentId, name, body: PutEnvironmentSecretRequest, actor): Promise<EnvironmentSecretView>
|
|
@@ -78,7 +84,9 @@ import { decryptSecret, encryptSecret, VaultCryptoError } from "./crypto.js";
|
|
|
78
84
|
import { VaultError } from "./error.js";
|
|
79
85
|
import { credentialNeeds } from "./coverage.js";
|
|
80
86
|
import { checkCredentialHeaders } from "./headers.js";
|
|
81
|
-
import { hostModelCatalog } from "../model/catalog.js";
|
|
87
|
+
import { hostModelCatalog, inputsOfHostModel } from "../model/catalog.js";
|
|
88
|
+
import { inputsError } from "../model/capabilities.js";
|
|
89
|
+
import { readAddedInputs } from "../tenant/model-setting.js";
|
|
82
90
|
import { normalizeVaultUrl } from "./url.js";
|
|
83
91
|
export const HOST_VAULT_ID = "host";
|
|
84
92
|
const HOST_MODEL_ID = "host-model";
|
|
@@ -90,10 +98,13 @@ export class VaultService {
|
|
|
90
98
|
this.kek = options.kek;
|
|
91
99
|
}
|
|
92
100
|
// --- an Environment's vault (caller's transaction) ------------------------------
|
|
93
|
-
/**
|
|
94
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Creates Environment `environmentId`'s vault (D56), in the transaction that creates it; answers
|
|
103
|
+
* its id, `id` when given (a fork's, whose secrets were sealed for it first).
|
|
104
|
+
*/
|
|
105
|
+
async createEnvironmentVault(t, environmentId, actor, id = randomUUID()) {
|
|
95
106
|
const row = {
|
|
96
|
-
id
|
|
107
|
+
id,
|
|
97
108
|
name: environmentId,
|
|
98
109
|
metadataJson: null,
|
|
99
110
|
createdAt: new Date().toISOString(),
|
|
@@ -101,6 +112,7 @@ export class VaultService {
|
|
|
101
112
|
};
|
|
102
113
|
await t.insertVault(row);
|
|
103
114
|
await this.audit(t, { actor, action: "create", vaultId: row.id, target: environmentId, outcome: "created" });
|
|
115
|
+
return row.id;
|
|
104
116
|
}
|
|
105
117
|
/**
|
|
106
118
|
* Deletes Environment `environmentId`'s vault and its credentials, with their audit rows, in
|
|
@@ -123,6 +135,100 @@ export class VaultService {
|
|
|
123
135
|
await t.deleteVault(vault.id);
|
|
124
136
|
await this.audit(t, { actor, action: "delete", vaultId: vault.id, target: environmentId, outcome: "deleted" });
|
|
125
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Seals Environment `from`'s secrets again for vault `vaultId`, a fork's new vault (Q15): each
|
|
140
|
+
* value is unsealed and sealed under the new vault's and credential's ids, which its AAD binds.
|
|
141
|
+
* Needs the vault key, so callers reach it through `Keys`; it reads `from` in its own
|
|
142
|
+
* transaction and writes nothing. With `slots` (what the fork runs declares secret slots, D64),
|
|
143
|
+
* only the names it declares are sealed, each with its slot's binding; a value the slot's type
|
|
144
|
+
* cannot take is left behind. The fork's transaction inserts the copies
|
|
145
|
+
* (`insertEnvironmentSecretCopies`).
|
|
146
|
+
*/
|
|
147
|
+
async sealEnvironmentSecretCopies(from, vaultId, slots) {
|
|
148
|
+
const kek = this.kek();
|
|
149
|
+
const rows = await this.store.tx(async (t) => {
|
|
150
|
+
const source = await t.vaultOfEnvironment(from);
|
|
151
|
+
return source ? (await t.credentialsForVault(source.id)).filter(isUserCredential) : [];
|
|
152
|
+
});
|
|
153
|
+
const sealed = [];
|
|
154
|
+
const dropped = [];
|
|
155
|
+
const now = new Date().toISOString();
|
|
156
|
+
for (const row of rows) {
|
|
157
|
+
const payload = readPayload(kek, row);
|
|
158
|
+
let type = row.type;
|
|
159
|
+
let binding = credentialBinding(row);
|
|
160
|
+
let value = payload;
|
|
161
|
+
if (slots) {
|
|
162
|
+
const slot = slots[row.name];
|
|
163
|
+
const rebound = slot === undefined ? undefined : rebind(row.name, slot, row, payload, binding);
|
|
164
|
+
if (rebound === undefined) {
|
|
165
|
+
dropped.push(row.name);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
({ type, binding, payload: value } = rebound);
|
|
169
|
+
try {
|
|
170
|
+
conflictOf(type, binding, sealed);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
if (!(error instanceof VaultError))
|
|
174
|
+
throw error;
|
|
175
|
+
dropped.push(row.name);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const id = randomUUID();
|
|
180
|
+
sealed.push({
|
|
181
|
+
id,
|
|
182
|
+
vaultId,
|
|
183
|
+
name: row.name,
|
|
184
|
+
type,
|
|
185
|
+
bindingJson: JSON.stringify(binding),
|
|
186
|
+
expiresAt: row.expiresAt,
|
|
187
|
+
createdAt: now,
|
|
188
|
+
rotatedAt: null,
|
|
189
|
+
...encryptSecret(kek, credentialAad(vaultId, id, type, binding), Buffer.from(JSON.stringify(value), "utf8")),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
copies: sealed.map((row) => ({
|
|
194
|
+
id: row.id,
|
|
195
|
+
name: row.name,
|
|
196
|
+
type: row.type,
|
|
197
|
+
bindingJson: row.bindingJson,
|
|
198
|
+
expiresAt: row.expiresAt,
|
|
199
|
+
kekId: row.kekId,
|
|
200
|
+
nonce: Buffer.from(row.nonce).toString("base64"),
|
|
201
|
+
ciphertext: Buffer.from(row.ciphertext).toString("base64"),
|
|
202
|
+
wrappedDek: Buffer.from(row.wrappedDek).toString("base64"),
|
|
203
|
+
})),
|
|
204
|
+
dropped: dropped.sort(),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Inserts a fork's sealed copies (`sealEnvironmentSecretCopies`) into vault `vaultId`, in the
|
|
209
|
+
* transaction that creates the fork, with an audit row each naming `from`. Reads no secret.
|
|
210
|
+
*/
|
|
211
|
+
async insertEnvironmentSecretCopies(t, vaultId, from, actor, sealed) {
|
|
212
|
+
const now = new Date().toISOString();
|
|
213
|
+
for (const copy of sealed.copies) {
|
|
214
|
+
await t.insertCredential({
|
|
215
|
+
id: copy.id,
|
|
216
|
+
vaultId,
|
|
217
|
+
name: copy.name,
|
|
218
|
+
type: copy.type,
|
|
219
|
+
bindingJson: copy.bindingJson,
|
|
220
|
+
expiresAt: copy.expiresAt,
|
|
221
|
+
createdAt: now,
|
|
222
|
+
rotatedAt: null,
|
|
223
|
+
kekId: copy.kekId,
|
|
224
|
+
nonce: Buffer.from(copy.nonce, "base64"),
|
|
225
|
+
ciphertext: Buffer.from(copy.ciphertext, "base64"),
|
|
226
|
+
wrappedDek: Buffer.from(copy.wrappedDek, "base64"),
|
|
227
|
+
});
|
|
228
|
+
await this.audit(t, { actor, action: "create", vaultId, credentialId: copy.id, target: from, outcome: "copied" });
|
|
229
|
+
}
|
|
230
|
+
return { copied: sealed.copies.map((copy) => copy.name).sort(), dropped: [...sealed.dropped] };
|
|
231
|
+
}
|
|
126
232
|
// --- an Environment's secrets ----------------------------------------------------
|
|
127
233
|
/**
|
|
128
234
|
* `PUT /v1/environments/{id}/secrets/{name}`: creates or replaces one credential. The same
|
|
@@ -402,9 +508,11 @@ export class VaultService {
|
|
|
402
508
|
async listHostProviders() {
|
|
403
509
|
return this.store.tx(async (t) => {
|
|
404
510
|
const active = await activeProviderId(t);
|
|
511
|
+
const added = await readAddedInputs(t);
|
|
405
512
|
const catalog = new Map(hostModelCatalog().providers.map((provider) => [provider.id, provider.name]));
|
|
406
513
|
const providers = (await hostModelRows(t)).map((row) => {
|
|
407
514
|
const binding = modelBinding(row);
|
|
515
|
+
const inputs = inputsOfHostModel({ configured: true, ...binding }, added);
|
|
408
516
|
return {
|
|
409
517
|
id: binding.provider,
|
|
410
518
|
name: catalog.get(binding.provider) ??
|
|
@@ -415,6 +523,7 @@ export class VaultService {
|
|
|
415
523
|
authType: binding.authType,
|
|
416
524
|
...(binding.baseUrl ? { baseUrl: binding.baseUrl } : {}),
|
|
417
525
|
...(binding.settings ? { settings: binding.settings } : {}),
|
|
526
|
+
...(inputs ? { inputs } : {}),
|
|
418
527
|
lastUpdated: row.rotatedAt ?? row.createdAt,
|
|
419
528
|
active: binding.provider === active,
|
|
420
529
|
};
|
|
@@ -541,8 +650,13 @@ export class VaultService {
|
|
|
541
650
|
}
|
|
542
651
|
validateHostModel(body) {
|
|
543
652
|
if (body.settings && body.provider !== "custom")
|
|
544
|
-
throw new VaultError(400, "Model settings (context window, output limit, reasoning, compat) apply only to a custom provider.");
|
|
653
|
+
throw new VaultError(400, "Model settings (context window, output limit, reasoning, inputs, compat) apply only to a custom provider.");
|
|
545
654
|
if (body.provider === "custom") {
|
|
655
|
+
// A custom endpoint is OpenAI-compatible: it reads only what that API carries (protocol 12).
|
|
656
|
+
const inputsRefused = body.settings?.inputs &&
|
|
657
|
+
inputsError({ api: "openai-completions", input: ["text", "image"] }, body.settings.inputs);
|
|
658
|
+
if (inputsRefused)
|
|
659
|
+
throw new VaultError(400, inputsRefused);
|
|
546
660
|
if (!body.baseUrl)
|
|
547
661
|
throw new VaultError(400, "A base URL is required for a custom provider.");
|
|
548
662
|
let url;
|
|
@@ -855,6 +969,39 @@ function credentialAad(vaultId, credentialId, type, binding) {
|
|
|
855
969
|
}
|
|
856
970
|
: { vaultId, credentialId, type, url: binding.url }), "utf8");
|
|
857
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* A copied credential's type, binding and payload under a slot of the fork (D64): its value with
|
|
974
|
+
* the slot's binding, or undefined when the slot's type cannot take it.
|
|
975
|
+
*/
|
|
976
|
+
function rebind(name, slot, row, payload, binding) {
|
|
977
|
+
const type = slot.type;
|
|
978
|
+
const value = row.type === "environment_variable" ? binding.variableValue : row.type === "bearer" ? payload.token : payload.value;
|
|
979
|
+
try {
|
|
980
|
+
if (type === "environment_secret" || type === "environment_variable") {
|
|
981
|
+
if (value === undefined)
|
|
982
|
+
return undefined;
|
|
983
|
+
const made = environmentCredential(name, { ...slot, type, value });
|
|
984
|
+
return { type, ...made };
|
|
985
|
+
}
|
|
986
|
+
const auth = type === "headers"
|
|
987
|
+
? payload.headers === undefined
|
|
988
|
+
? undefined
|
|
989
|
+
: { type, headers: payload.headers }
|
|
990
|
+
: value === undefined
|
|
991
|
+
? undefined
|
|
992
|
+
: { type: "bearer", value };
|
|
993
|
+
if (auth === undefined)
|
|
994
|
+
return undefined;
|
|
995
|
+
const sealed = payloadOf(auth);
|
|
996
|
+
const routing = slot;
|
|
997
|
+
return { type, payload: sealed, binding: bindingOf(normalizeVaultUrl(routing.url), sealed, routing) };
|
|
998
|
+
}
|
|
999
|
+
catch (error) {
|
|
1000
|
+
if (error instanceof VaultError)
|
|
1001
|
+
return undefined;
|
|
1002
|
+
throw error;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
858
1005
|
/** The sealed payload and unsealed binding of a shell credential named `name` (R2c). */
|
|
859
1006
|
function environmentCredential(name, body) {
|
|
860
1007
|
if (body.type === "environment_variable")
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const RUNTIME_VERSION = "0.
|
|
1
|
+
export declare const RUNTIME_VERSION = "0.25.0-beta";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Kept in step with package.json by runtime/server/scripts/check-package.mjs, which runs in npm run check.
|
|
2
2
|
// release:prepare also rewrites this when it bumps @nylorun/runtime.
|
|
3
|
-
export const RUNTIME_VERSION = "0.
|
|
3
|
+
export const RUNTIME_VERSION = "0.25.0-beta";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0-beta",
|
|
4
4
|
"description": "Nylorun Runtime: the agent execution Host on Postgres, Restate and S2, and model providers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"@hono/node-server": "^2.1.3",
|
|
66
66
|
"@hono/zod-openapi": "^1.6.3",
|
|
67
67
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
68
|
-
"@nylorun/core": "0.
|
|
69
|
-
"@nylorun/harness": "0.
|
|
68
|
+
"@nylorun/core": "0.21.0-beta",
|
|
69
|
+
"@nylorun/harness": "0.27.0-beta",
|
|
70
70
|
"@restatedev/restate-sdk": "1.17.2",
|
|
71
71
|
"@restatedev/restate-sdk-clients": "1.17.2",
|
|
72
72
|
"@s2-dev/streamstore": "0.28.0",
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { type AgentManifest, type CapabilityManifest } from "@nylorun/core/define";
|
|
2
|
-
/** The sandbox capability that owns this tool call, when the call is a built-in sandbox tool. */
|
|
3
|
-
export declare function sandboxCapabilityOf(manifest: AgentManifest | undefined, capabilityId: string | undefined, toolName: string | undefined): CapabilityManifest | undefined;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { isSandboxToolName, } from "@nylorun/core/define";
|
|
2
|
-
/** The sandbox capability that owns this tool call, when the call is a built-in sandbox tool. */
|
|
3
|
-
export function sandboxCapabilityOf(manifest, capabilityId, toolName) {
|
|
4
|
-
if (!manifest || !capabilityId || !toolName || !isSandboxToolName(toolName))
|
|
5
|
-
return undefined;
|
|
6
|
-
const capability = manifest.capabilities.find((item) => item.id === capabilityId);
|
|
7
|
-
return capability?.sandbox && capability.tools?.some((tool) => tool.name === toolName)
|
|
8
|
-
? capability
|
|
9
|
-
: undefined;
|
|
10
|
-
}
|