@nylorun/runtime 0.23.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 +252 -0
- package/README.md +87 -28
- package/dist/adapters/execution/restate.js +1 -1
- package/dist/adapters/replication/pgoutput.d.ts +2 -0
- package/dist/adapters/replication/pgoutput.js +6 -3
- package/dist/adapters/sandbox/local.d.ts +9 -1
- package/dist/adapters/sandbox/local.js +16 -4
- package/dist/adapters/sandbox/virtual.js +4 -1
- package/dist/api/a2a/card.d.ts +11 -1
- package/dist/api/a2a/card.js +26 -2
- package/dist/api/a2a/endpoint.js +9 -3
- package/dist/api/a2a/protocol.d.ts +25 -2
- package/dist/api/a2a/protocol.js +20 -3
- package/dist/api/a2a/routes.d.ts +6 -1
- package/dist/api/a2a/routes.js +67 -9
- package/dist/api/a2a/tasks.js +2 -1
- package/dist/api/ag-ui/endpoint.js +8 -3
- package/dist/api/ag-ui/history.d.ts +6 -1
- package/dist/api/ag-ui/history.js +39 -3
- package/dist/api/ag-ui/routes.d.ts +4 -1
- package/dist/api/ag-ui/routes.js +63 -20
- package/dist/api/ag-ui/translate.js +3 -2
- package/dist/api/components.d.ts +5327 -1091
- package/dist/api/components.js +40 -16
- package/dist/api/gate/keys.d.ts +2 -1
- package/dist/api/gate/keys.js +14 -1
- package/dist/api/gate/routes.d.ts +6 -0
- package/dist/api/gate/routes.js +52 -3
- package/dist/api/http/app.js +17 -6
- package/dist/api/http/body.d.ts +3 -3
- package/dist/api/http/body.js +7 -7
- package/dist/api/http/define.d.ts +6 -0
- package/dist/api/http/define.js +13 -1
- package/dist/api/http/respond.js +1 -1
- package/dist/api/http/routes/artifacts.js +35 -8
- package/dist/api/http/routes/coverage.d.ts +9 -0
- package/dist/api/http/routes/coverage.js +34 -0
- 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.d.ts +11 -0
- package/dist/api/http/routes/environments.js +332 -0
- package/dist/api/http/routes/mcp.d.ts +1 -1
- package/dist/api/http/routes/mcp.js +2 -2
- package/dist/api/http/routes/me.js +1 -1
- package/dist/api/http/routes/reads.d.ts +94 -9
- package/dist/api/http/routes/reads.js +54 -5
- package/dist/api/http/routes/sessions.js +24 -9
- package/dist/api/http/routes/tenant.js +65 -15
- package/dist/api/inbound-files.d.ts +65 -0
- package/dist/api/inbound-files.js +115 -0
- package/dist/api/openapi.js +48 -28
- package/dist/artifacts/disk.d.ts +59 -0
- package/dist/artifacts/disk.js +569 -0
- package/dist/artifacts/export.d.ts +1 -1
- package/dist/artifacts/export.js +2 -3
- package/dist/artifacts/folders.d.ts +6 -3
- package/dist/artifacts/folders.js +17 -12
- 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/service.d.ts +2 -1
- package/dist/artifacts/service.js +6 -1
- package/dist/artifacts/workspace.d.ts +5 -5
- package/dist/artifacts/workspace.js +7 -19
- package/dist/core/flow-host.d.ts +3 -4
- package/dist/core/flow-host.js +5 -2
- package/dist/core/provider.d.ts +3 -2
- package/dist/core/provider.js +5 -37
- package/dist/core/sandbox-routes.d.ts +2 -21
- package/dist/core/sandbox-routes.js +11 -44
- package/dist/core/turn-manifest.d.ts +3 -2
- package/dist/core/turn-manifest.js +29 -5
- package/dist/execution/types.d.ts +1 -1
- package/dist/gates/contract.d.ts +3 -24
- package/dist/gates/contract.js +1 -36
- package/dist/gates/egress-credentials.d.ts +9 -0
- package/dist/gates/egress-credentials.js +11 -4
- package/dist/gates/egress.d.ts +22 -1
- package/dist/gates/egress.js +116 -10
- package/dist/gates/fixture-model.d.ts +28 -0
- package/dist/gates/fixture-model.js +92 -0
- package/dist/gates/handler.js +4 -4
- package/dist/gates/http-tool.d.ts +9 -6
- package/dist/gates/http-tool.js +11 -17
- package/dist/gates/in-process.d.ts +5 -0
- package/dist/gates/in-process.js +12 -1
- package/dist/gates/journal.d.ts +30 -0
- package/dist/gates/journal.js +51 -0
- package/dist/gates/mcp-handler.d.ts +4 -0
- package/dist/gates/mcp-handler.js +7 -4
- package/dist/gates/meter.d.ts +10 -2
- package/dist/gates/meter.js +20 -5
- package/dist/gates/policy.d.ts +49 -0
- package/dist/gates/policy.js +132 -0
- package/dist/gates/tenant-vaults.d.ts +7 -7
- package/dist/gates/tenant-vaults.js +5 -5
- package/dist/gates/tool-calls.d.ts +10 -5
- package/dist/gates/tool-calls.js +28 -10
- package/dist/gates/tool-client.d.ts +8 -0
- package/dist/gates/tool-client.js +27 -11
- package/dist/gates/tool-contract.d.ts +11 -69
- package/dist/gates/tool-contract.js +1 -85
- package/dist/gates/tool-gate.d.ts +1 -1
- package/dist/harness/calls.d.ts +14 -7
- package/dist/harness/calls.js +30 -24
- package/dist/harness/executors.js +12 -9
- package/dist/harness/main.js +24 -5
- package/dist/harness/pod.d.ts +39 -0
- package/dist/harness/pod.js +46 -0
- package/dist/harness/service.d.ts +0 -1
- package/dist/harness/service.js +17 -9
- package/dist/harness/setup.d.ts +29 -0
- package/dist/harness/setup.js +174 -0
- package/dist/harness/ws-client.js +3 -2
- package/dist/harness/ws-port.d.ts +1 -5
- package/dist/harness/ws-port.js +1 -5
- package/dist/harness-api/in-process.js +3 -3
- package/dist/harness-api/record.d.ts +15 -1
- package/dist/harness-api/record.js +180 -50
- package/dist/harness-api/redact.d.ts +3 -0
- package/dist/harness-api/redact.js +45 -0
- package/dist/harness-api/server.d.ts +35 -4
- package/dist/harness-api/server.js +130 -17
- package/dist/harness-api/start.d.ts +10 -3
- package/dist/harness-api/start.js +40 -10
- package/dist/harness-api/tool-journal.d.ts +105 -0
- package/dist/harness-api/tool-journal.js +132 -0
- package/dist/harness-api/tool-status.d.ts +13 -0
- package/dist/harness-api/tool-status.js +26 -0
- package/dist/harness-api/workspace.d.ts +12 -7
- package/dist/harness-api/workspace.js +47 -25
- package/dist/harness-api/ws-server.d.ts +11 -3
- package/dist/harness-api/ws-server.js +94 -15
- package/dist/host/gates.d.ts +2 -1
- package/dist/host/gates.js +10 -2
- package/dist/host/main.js +54 -5
- package/dist/host/operate.js +67 -5
- package/dist/host/stack-config.d.ts +64 -0
- package/dist/host/stack-config.js +62 -2
- package/dist/keys/client.js +4 -1
- package/dist/keys/keys.d.ts +13 -6
- package/dist/keys/keys.js +9 -8
- package/dist/management-openapi.json +1264 -2171
- package/dist/mcp/connect.d.ts +26 -22
- package/dist/mcp/connect.js +30 -34
- package/dist/mcp/pool.d.ts +3 -6
- package/dist/mcp/pool.js +14 -28
- package/dist/mcp/preview.d.ts +3 -3
- package/dist/mcp/preview.js +10 -21
- package/dist/mcp/snapshot.d.ts +16 -24
- package/dist/mcp/snapshot.js +33 -45
- 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 +114 -94
- package/dist/openapi.json +12822 -3943
- package/dist/reads/types.d.ts +16 -3
- package/dist/record/append.d.ts +3 -1
- package/dist/record/append.js +1 -0
- package/dist/record/envelope.d.ts +5 -1
- package/dist/record/envelope.js +7 -3
- package/dist/record/environment.d.ts +25 -0
- package/dist/record/environment.js +44 -0
- package/dist/record/index.d.ts +1 -1
- package/dist/record/index.js +1 -1
- package/dist/sandbox/disk-fs.d.ts +95 -0
- package/dist/sandbox/disk-fs.js +206 -0
- package/dist/sandbox/join.d.ts +17 -18
- package/dist/sandbox/join.js +46 -15
- package/dist/sandbox/manager.d.ts +47 -21
- package/dist/sandbox/manager.js +162 -107
- package/dist/sandbox/placement.d.ts +14 -13
- package/dist/sandbox/placement.js +31 -14
- package/dist/sandbox/pods/client.d.ts +9 -2
- package/dist/sandbox/pods/lifecycle.d.ts +36 -27
- package/dist/sandbox/pods/lifecycle.js +29 -26
- package/dist/sandbox/pods/reconcile.js +18 -12
- package/dist/sandbox/pods/spec.d.ts +15 -13
- package/dist/sandbox/pods/spec.js +17 -20
- package/dist/sandbox/records.d.ts +2 -2
- package/dist/sandbox/records.js +3 -3
- package/dist/sandbox/resolve.d.ts +37 -27
- package/dist/sandbox/resolve.js +73 -41
- 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 +64 -0
- package/dist/sandbox/setup.js +160 -0
- package/dist/sandbox/share.d.ts +21 -26
- package/dist/sandbox/share.js +36 -63
- package/dist/sandbox/skills.d.ts +8 -6
- package/dist/sandbox/skills.js +24 -23
- package/dist/sandbox/tenant-config.d.ts +12 -14
- package/dist/sandbox/tenant-config.js +12 -17
- package/dist/sandbox/types.d.ts +6 -0
- package/dist/store/postgres/drizzle/0020_environments.sql +63 -0
- package/dist/store/postgres/drizzle/0021_disk_versions.sql +7 -0
- package/dist/store/postgres/drizzle/0022_model_usage_timing.sql +5 -0
- package/dist/store/postgres/drizzle/0023_artifact_pages.sql +1 -0
- 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 +56 -0
- package/dist/store/postgres/reads.js +123 -17
- package/dist/store/postgres/record-writer.d.ts +4 -4
- package/dist/store/postgres/record-writer.js +9 -9
- package/dist/store/postgres/record.d.ts +7 -0
- package/dist/store/postgres/record.js +23 -2
- package/dist/store/postgres/schema.d.ts +1126 -736
- package/dist/store/postgres/schema.js +136 -73
- package/dist/store/postgres/store.js +195 -67
- package/dist/store/types.d.ts +165 -50
- package/dist/tenant/advance.d.ts +7 -6
- package/dist/tenant/advance.js +118 -42
- package/dist/tenant/artifact-tool.d.ts +1 -1
- package/dist/tenant/artifact-tool.js +46 -26
- package/dist/tenant/commands.d.ts +15 -2
- package/dist/tenant/commands.js +115 -14
- package/dist/tenant/context.d.ts +56 -24
- package/dist/tenant/context.js +4 -15
- package/dist/tenant/effects.d.ts +1 -1
- package/dist/tenant/effects.js +44 -29
- package/dist/tenant/environment-manifests.d.ts +57 -0
- package/dist/tenant/environment-manifests.js +200 -0
- package/dist/tenant/environments.d.ts +174 -0
- package/dist/tenant/environments.js +1044 -0
- package/dist/tenant/harness-tokens.d.ts +21 -0
- package/dist/tenant/harness-tokens.js +61 -0
- package/dist/tenant/host-token.d.ts +1 -1
- package/dist/tenant/host-token.js +2 -4
- package/dist/tenant/identity-file.d.ts +4 -4
- package/dist/tenant/identity-file.js +17 -8
- package/dist/tenant/issuers.js +3 -3
- package/dist/tenant/model-setting.d.ts +14 -0
- package/dist/tenant/model-setting.js +51 -0
- package/dist/tenant/principals.js +1 -1
- package/dist/tenant/reset.js +3 -3
- package/dist/tenant/runtime.d.ts +6 -1
- package/dist/tenant/runtime.js +7 -1
- package/dist/tenant/session.d.ts +3 -3
- package/dist/tenant/session.js +0 -14
- package/dist/tenant/sessions.d.ts +18 -14
- package/dist/tenant/sessions.js +99 -143
- package/dist/tenant/signing-keys.d.ts +5 -1
- package/dist/tenant/skill-tool.d.ts +3 -3
- package/dist/tenant/skill-tool.js +6 -11
- package/dist/tenant/status.js +3 -3
- package/dist/tenant/sweep.js +13 -7
- 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 +245 -36
- package/dist/tenant/transcript.js +64 -12
- package/dist/tenant/turn-timing.d.ts +43 -0
- package/dist/tenant/turn-timing.js +39 -0
- package/dist/tenant/types.d.ts +2 -0
- package/dist/traces/ids.d.ts +41 -0
- package/dist/traces/ids.js +81 -0
- package/dist/traces/key.d.ts +6 -0
- package/dist/traces/key.js +37 -0
- package/dist/traces/map.d.ts +113 -0
- package/dist/traces/map.js +289 -0
- package/dist/traces/options.d.ts +7 -0
- package/dist/traces/options.js +1 -0
- package/dist/traces/otlp.d.ts +42 -0
- package/dist/traces/otlp.js +84 -0
- package/dist/traces/projector.d.ts +58 -0
- package/dist/traces/projector.js +200 -0
- package/dist/traces/read.d.ts +23 -0
- package/dist/traces/read.js +16 -0
- package/dist/vault/coverage.d.ts +26 -0
- package/dist/vault/coverage.js +62 -0
- package/dist/vault/error.d.ts +11 -1
- package/dist/vault/error.js +5 -1
- package/dist/vault/host-model.d.ts +4 -1
- package/dist/vault/host-model.js +10 -2
- package/dist/vault/service.d.ts +92 -48
- package/dist/vault/service.js +462 -376
- package/dist/vault/sources.d.ts +5 -16
- package/dist/vault/sources.js +6 -8
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/package.json +13 -13
- package/dist/api/http/routes/sandboxes.d.ts +0 -9
- package/dist/api/http/routes/sandboxes.js +0 -153
- package/dist/api/http/routes/vaults.d.ts +0 -10
- package/dist/api/http/routes/vaults.js +0 -139
- package/dist/record/sandbox.d.ts +0 -25
- package/dist/record/sandbox.js +0 -43
- package/dist/sandbox/capability.d.ts +0 -3
- package/dist/sandbox/capability.js +0 -10
- package/dist/tenant/sandboxes.d.ts +0 -123
- package/dist/tenant/sandboxes.js +0 -566
package/dist/tenant/sessions.js
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Session and definition resources: `PUT/GET /v1/agents`, `PUT /v1/sessions/:id` (create or
|
|
3
|
-
*
|
|
4
|
-
* queries; `PUT /v1/sessions/:id` runs in one transaction with the
|
|
2
|
+
* Session and definition resources: `PUT/GET /v1/agents`, `PUT /v1/sessions/:id` (create, or
|
|
3
|
+
* find an identical one), the session list and the session view. Reads use the store's typed
|
|
4
|
+
* queries; `PUT /v1/sessions/:id` runs in one transaction with the Environment's checks.
|
|
5
5
|
*/
|
|
6
6
|
import { DefinitionDocumentSchema, definitionFilesOf, } from "@nylorun/core/contracts";
|
|
7
7
|
import { hashManifest } from "@nylorun/core/compatibility";
|
|
8
|
-
import { codeToolRefusal } from "@nylorun/core/define";
|
|
8
|
+
import { approvalRefusal, codeToolRefusal } from "@nylorun/core/define";
|
|
9
9
|
import { aggregateWaits, isWorkflowManifest } from "../core/flow-host.js";
|
|
10
10
|
import { canonical } from "../store/canonical.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { declaredSandboxes, sandboxSpecOf, sessionSandboxSpec, } from "../sandbox/share.js";
|
|
11
|
+
import { sandboxSpecOf } from "../sandbox/resolve.js";
|
|
12
|
+
import { withRuntimeTools, withSandbox } from "../sandbox/session-sandbox.js";
|
|
13
|
+
import { authoredRuntimeBlocks, declaredSandboxes } from "../sandbox/share.js";
|
|
15
14
|
import { effectiveSandboxConfig, readSandboxConfig } from "../sandbox/tenant-config.js";
|
|
16
|
-
import { checkPlacement, requirePods } from "../sandbox/placement.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
15
|
+
import { HARNESS_ID, checkPlacement, requirePods } from "../sandbox/placement.js";
|
|
16
|
+
import { openEnvironment, recordAttachment } from "./environments.js";
|
|
17
|
+
import { harnessOf, } from "./context.js";
|
|
19
18
|
import { fail } from "./http.js";
|
|
20
19
|
import { missingDefinitionFiles } from "./definition-files.js";
|
|
21
|
-
/** A session's creation identity: everything but the request id
|
|
20
|
+
/** A session's creation identity: everything but the request id. */
|
|
22
21
|
const sessionIdentity = (value) => {
|
|
23
|
-
const { requestId: _requestId,
|
|
22
|
+
const { requestId: _requestId, ...body } = value ?? {};
|
|
24
23
|
return canonical(body);
|
|
25
24
|
};
|
|
26
25
|
export async function listDefinitions(ctx) {
|
|
@@ -52,17 +51,24 @@ export async function listAgentsPublic(ctx, agents) {
|
|
|
52
51
|
})),
|
|
53
52
|
};
|
|
54
53
|
}
|
|
55
|
-
export async function putDefinition(ctx, agentId, body) {
|
|
54
|
+
export async function putDefinition(ctx, agentId, body, options = {}) {
|
|
56
55
|
if (body.manifest.id !== agentId)
|
|
57
56
|
fail(400, "Agent id mismatch");
|
|
58
57
|
DefinitionDocumentSchema.parse(body.manifest);
|
|
59
|
-
// The Runtime runs
|
|
58
|
+
// The Runtime runs agents from their manifests alone (track R2): no tool may need it.
|
|
60
59
|
const code = codeToolRefusal(body.manifest);
|
|
61
60
|
if (code)
|
|
62
61
|
fail(400, code);
|
|
62
|
+
// Tool approvals are the Tenant's tool policy, decided at the Tool Gate (R5 step 2).
|
|
63
|
+
const approval = approvalRefusal(body.manifest);
|
|
64
|
+
if (approval)
|
|
65
|
+
fail(400, approval);
|
|
63
66
|
const declared = declaredSandboxes(body.manifest);
|
|
64
67
|
if (declared.length > 0)
|
|
65
|
-
fail(400, `${declared.join(", ")} declares a sandbox. Agents no longer declare one: remove .sandbox()
|
|
68
|
+
fail(400, `${declared.join(", ")} declares a sandbox. Agents no longer declare one: remove .sandbox(), create an Environment with the sandbox (PUT /v1/environments/{id}) and open the session on it, createSession({ environment }). See MIGRATION.md.`);
|
|
69
|
+
const runtime = authoredRuntimeBlocks(body.manifest);
|
|
70
|
+
if (runtime.length > 0)
|
|
71
|
+
fail(400, `${runtime.join(", ")} sets runtime, which only the Runtime writes when it pins a session's agent. Remove it and register the manifest your builder makes.`);
|
|
66
72
|
const definition = {
|
|
67
73
|
...body,
|
|
68
74
|
manifestHash: hashManifest(body.manifest),
|
|
@@ -72,6 +78,8 @@ export async function putDefinition(ctx, agentId, body) {
|
|
|
72
78
|
const missing = await missingDefinitionFiles(t, body.manifest);
|
|
73
79
|
if (missing.length > 0)
|
|
74
80
|
fail(400, `The definition names ${missing.length} file(s) the Runtime does not hold; upload each with PUT /v1/files/<sha256> first: ${missing.join(", ")}`, { code: "definition_files_missing", details: { missing } });
|
|
81
|
+
if (options.dryRun)
|
|
82
|
+
return;
|
|
75
83
|
await t.put("definitions", agentId, definition);
|
|
76
84
|
await t.insertDefinitionFileUses(agentId, definition.manifestHash, files);
|
|
77
85
|
});
|
|
@@ -79,6 +87,7 @@ export async function putDefinition(ctx, agentId, body) {
|
|
|
79
87
|
agentId,
|
|
80
88
|
manifestHash: definition.manifestHash,
|
|
81
89
|
implementationVersion: body.implementationVersion,
|
|
90
|
+
...(options.dryRun ? { dryRun: true } : {}),
|
|
82
91
|
};
|
|
83
92
|
}
|
|
84
93
|
/**
|
|
@@ -104,18 +113,16 @@ export async function listSessions(ctx, agentId, access) {
|
|
|
104
113
|
};
|
|
105
114
|
}
|
|
106
115
|
/**
|
|
107
|
-
* Create a session from its definition, or
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
116
|
+
* Create a session from its definition, or find an identical one. `access`, when the request
|
|
117
|
+
* acts for a subject, must be the session's owner: another owner's session id is the 404 of a
|
|
118
|
+
* missing one (not the 409 of a mismatch), and so is an Environment whose owner guard names
|
|
119
|
+
* another owner.
|
|
111
120
|
*
|
|
112
|
-
* The session's
|
|
113
|
-
*
|
|
114
|
-
*
|
|
121
|
+
* The session's Environment is fixed for its life: its sandbox (kinds `virtual` and `pod`) is
|
|
122
|
+
* the session's, with the spec of the Environment's applied recipe pinned now, and its vault
|
|
123
|
+
* holds the session's credentials. Without one the session has no sandbox and no credentials.
|
|
115
124
|
*/
|
|
116
125
|
export async function putSession(ctx, id, body, access, options = {}) {
|
|
117
|
-
const vaultIds = body.vaultIds ?? [];
|
|
118
|
-
const credentialSelections = body.credentialSelections ?? [];
|
|
119
126
|
const opaque = access !== undefined;
|
|
120
127
|
if (opaque && body.ownerUserId !== access.owner)
|
|
121
128
|
fail(403, "ownerUserId must be the subject");
|
|
@@ -135,35 +142,36 @@ export async function putSession(ctx, id, body, access, options = {}) {
|
|
|
135
142
|
fail(404, "Session not found");
|
|
136
143
|
return prior;
|
|
137
144
|
}
|
|
138
|
-
await ctx.vault.assertAttachment(t, body.ownerUserId, vaultIds, credentialSelections, { opaque });
|
|
139
|
-
const environment = await ctx.vault.sessionEnvironment(t, vaultIds);
|
|
140
|
-
if (environment.conflict)
|
|
141
|
-
fail(409, environment.conflict, { code: "credential_conflict" });
|
|
142
145
|
if (prior) {
|
|
143
|
-
if (prior.sandboxId !== undefined)
|
|
144
|
-
await assertSandboxSecrets(ctx, t, prior.sandboxId, id, body.ownerUserId, environment.secretHosts);
|
|
145
146
|
if (sessionIdentity(prior.creation) !== sessionIdentity(body))
|
|
146
147
|
fail(409, "Session already exists with different creation parameters");
|
|
147
|
-
prior.vaultIds = vaultIds;
|
|
148
|
-
prior.credentialSelections = credentialSelections;
|
|
149
|
-
prior.creation = body;
|
|
150
|
-
await t.put("sessions", id, prior);
|
|
151
|
-
await ctx.vault.recordAttachment(t, id, vaultIds);
|
|
152
148
|
return prior;
|
|
153
149
|
}
|
|
154
150
|
const definition = (await t.get("definitions", body.agentId)) ??
|
|
155
151
|
fail(404, "Definition not found");
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
152
|
+
const environment = body.environment === undefined
|
|
153
|
+
? undefined
|
|
154
|
+
: await openEnvironment(t, body.environment, {
|
|
155
|
+
...(options.environmentGrants === undefined ? {} : { grants: options.environmentGrants }),
|
|
156
|
+
ownerUserId: body.ownerUserId,
|
|
157
|
+
opaque,
|
|
158
|
+
});
|
|
159
|
+
if (!isWorkflowManifest(definition.manifest))
|
|
160
|
+
await checkRequirements(t, definition.manifest, environment);
|
|
161
|
+
const config = await readSandboxConfig(t);
|
|
162
|
+
// The harness the session runs for its life (R4.1): its Environment's, else ours. A flow
|
|
163
|
+
// runs in core and our engine, whatever its Environment names.
|
|
164
|
+
const harness = isWorkflowManifest(definition.manifest) || environment === undefined
|
|
165
|
+
? HARNESS_ID
|
|
166
|
+
: environment.applied.harness;
|
|
167
|
+
// Placement (D38, D52): where this session's harness may run, decided now and kept.
|
|
168
|
+
checkPlacement(config, environment?.kind, harness);
|
|
169
|
+
if (environment?.kind === "pod")
|
|
170
|
+
await requirePods(ctx.pods, `Environment ${environment.id}`);
|
|
171
|
+
const spec = environment === undefined || environment.kind === "none"
|
|
172
|
+
? undefined
|
|
173
|
+
: sandboxSpecOf(environment.applied, effectiveSandboxConfig(config).limits.idle);
|
|
174
|
+
const pinned = spec === undefined ? runtimeTools(definition) : pin(definition, spec);
|
|
167
175
|
const created = {
|
|
168
176
|
id,
|
|
169
177
|
agentId: body.agentId,
|
|
@@ -176,117 +184,66 @@ export async function putSession(ctx, id, body, access, options = {}) {
|
|
|
176
184
|
status: "idle",
|
|
177
185
|
activeTurnId: null,
|
|
178
186
|
creation: body,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
...(sandbox.sandboxId !== undefined ? { sandboxId: sandbox.sandboxId } : {}),
|
|
185
|
-
...(sandbox.spec !== undefined
|
|
186
|
-
? { sandbox: sandbox.spec, sandboxSource: sandbox.source }
|
|
187
|
-
: {}),
|
|
187
|
+
harness,
|
|
188
|
+
...(environment === undefined
|
|
189
|
+
? {}
|
|
190
|
+
: { environmentId: environment.id, environmentVersion: environment.version }),
|
|
191
|
+
...(spec === undefined ? {} : { sandbox: spec }),
|
|
188
192
|
};
|
|
189
193
|
await t.put("sessions", id, created);
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
await recordAttachment(t, id, sandbox.sandboxId);
|
|
194
|
+
if (environment !== undefined)
|
|
195
|
+
await recordAttachment(t, id, environment.id);
|
|
193
196
|
return created;
|
|
194
197
|
});
|
|
195
198
|
}
|
|
196
199
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
+
* Refuses a session whose agent requires what its Environment lacks (protocol 14, D65): a
|
|
201
|
+
* sandbox (`any`: kind `virtual` or `pod`), a pod, or a secret its vault does not hold. Every
|
|
202
|
+
* gap is named in one `409 environment_unsuitable`.
|
|
200
203
|
*/
|
|
201
|
-
async function
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
204
|
+
async function checkRequirements(t, manifest, environment) {
|
|
205
|
+
const requires = manifest.requires;
|
|
206
|
+
if (requires === undefined)
|
|
207
|
+
return;
|
|
208
|
+
const missing = [];
|
|
209
|
+
const kind = environment?.kind;
|
|
210
|
+
if (requires.sandbox === "any" && kind !== "virtual" && kind !== "pod")
|
|
211
|
+
missing.push("sandbox");
|
|
212
|
+
if (requires.sandbox === "pod" && kind !== "pod")
|
|
213
|
+
missing.push("pod");
|
|
214
|
+
if (requires.secrets?.length) {
|
|
215
|
+
const vault = environment === undefined ? undefined : await t.vaultOfEnvironment(environment.id);
|
|
216
|
+
const held = new Set(vault ? (await t.credentialsForVault(vault.id)).map((row) => row.name) : []);
|
|
217
|
+
for (const name of requires.secrets)
|
|
218
|
+
if (!held.has(name))
|
|
219
|
+
missing.push(`secret:${name}`);
|
|
213
220
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
function isAttach(value) {
|
|
219
|
-
return typeof value === "object" && value !== null && "id" in value;
|
|
220
|
-
}
|
|
221
|
-
/** Decide a new session's sandbox and, for an agent, the manifest that carries its tools. */
|
|
222
|
-
async function sessionSandbox(t, body, definition, options) {
|
|
223
|
-
const request = body.sandbox;
|
|
224
|
-
const declared = sandboxSpecOf(definition.manifest) !== undefined;
|
|
225
|
-
if (isAttach(request)) {
|
|
226
|
-
if (declared)
|
|
227
|
-
fail(400, `'${body.agentId}' declares its own sandbox with .sandbox(). Remove it from the agent to attach a sandbox.`);
|
|
228
|
-
const sandbox = await attachSandbox(t, request.id, options.grants);
|
|
229
|
-
// A pod's storage and lifecycle are the resource's, not the agent's sandbox manifest.
|
|
230
|
-
const { storage: _storage, lifecycle: _lifecycle, ...spec } = sandbox.spec;
|
|
231
|
-
return { ...(await pin(definition, spec, "sandbox")), sandboxId: sandbox.id, kind: sandbox.kind };
|
|
232
|
-
}
|
|
233
|
-
if (isShare(request)) {
|
|
234
|
-
const owner = await t.get("sessions", request.session);
|
|
235
|
-
if (owner?.sandboxId !== undefined && (!options.opaque || owner.ownerUserId === body.ownerUserId))
|
|
236
|
-
fail(400, `Session ${request.session} is attached to sandbox ${owner.sandboxId}: open this session with sandbox: { id: "${owner.sandboxId}" }.`);
|
|
237
|
-
const lookup = await sandboxLookup(t, request.session);
|
|
238
|
-
const sandboxOwnerId = validateSandboxAttach(body, definition.manifest, lookup, {
|
|
239
|
-
opaque: options.opaque,
|
|
240
|
-
inherit: !declared,
|
|
241
|
-
});
|
|
242
|
-
if (declared || sandboxOwnerId === undefined)
|
|
243
|
-
return { sandboxOwnerId };
|
|
244
|
-
const spec = sessionSandboxSpec(lookup(request.session));
|
|
245
|
-
return { ...(await pin(definition, spec, "shared")), sandboxOwnerId };
|
|
246
|
-
}
|
|
247
|
-
if (declared) {
|
|
248
|
-
if (request !== undefined)
|
|
249
|
-
fail(400, `'${body.agentId}' declares its own sandbox with .sandbox(). Remove it from the agent to choose the sandbox when opening the session, or omit sandbox here.`);
|
|
250
|
-
return {};
|
|
251
|
-
}
|
|
252
|
-
const resolved = resolveSandbox({
|
|
253
|
-
request,
|
|
254
|
-
config: effectiveSandboxConfig(await readSandboxConfig(t)),
|
|
255
|
-
actingForSubject: options.opaque,
|
|
256
|
-
});
|
|
257
|
-
if (resolved.kind === "none")
|
|
258
|
-
return {};
|
|
259
|
-
if (resolved.kind === "error")
|
|
260
|
-
return fail(resolved.status, resolved.errors.join(" "));
|
|
261
|
-
return pin(definition, resolved.spec, resolved.source);
|
|
221
|
+
if (missing.length === 0)
|
|
222
|
+
return;
|
|
223
|
+
const where = environment === undefined ? "the session names no Environment" : `Environment ${environment.id} lacks it`;
|
|
224
|
+
fail(409, `Agent ${manifest.id} requires ${missing.map((gap) => (gap.startsWith("secret:") ? `the secret ${gap.slice(7)}` : gap === "pod" ? "a pod Environment" : "a sandbox")).join(", ")}, and ${where}.`, { code: "environment_unsuitable", details: { missing } });
|
|
262
225
|
}
|
|
263
226
|
/**
|
|
264
|
-
* The manifest a session without a sandbox pins:
|
|
265
|
-
*
|
|
227
|
+
* The manifest a session without a sandbox pins: each agent's `runtime` block, with
|
|
228
|
+
* `read_artifact` (R2b C11) and its skill tools; nothing for a workflow.
|
|
266
229
|
*/
|
|
267
|
-
function
|
|
230
|
+
function runtimeTools(definition) {
|
|
268
231
|
if (isWorkflowManifest(definition.manifest))
|
|
269
232
|
return {};
|
|
270
|
-
const pinned =
|
|
271
|
-
if (pinned === undefined)
|
|
272
|
-
return {};
|
|
233
|
+
const pinned = withRuntimeTools(definition.manifest);
|
|
273
234
|
if (!pinned.ok)
|
|
274
235
|
return fail(400, pinned.message);
|
|
275
236
|
return { manifest: pinned.manifest, manifestHash: pinned.manifestHash };
|
|
276
237
|
}
|
|
277
|
-
|
|
238
|
+
/** The manifest a session with a sandbox pins: the definition with the sandbox in its `runtime` block. */
|
|
239
|
+
function pin(definition, spec) {
|
|
278
240
|
// A workflow's manifest stays as registered: its agents inherit the sandbox when they start.
|
|
279
241
|
if (isWorkflowManifest(definition.manifest))
|
|
280
|
-
return {
|
|
281
|
-
const sandboxed =
|
|
242
|
+
return {};
|
|
243
|
+
const sandboxed = withSandbox(definition.manifest, spec);
|
|
282
244
|
if (!sandboxed.ok)
|
|
283
245
|
return fail(400, sandboxed.message);
|
|
284
|
-
return {
|
|
285
|
-
spec,
|
|
286
|
-
source,
|
|
287
|
-
manifest: sandboxed.manifest,
|
|
288
|
-
manifestHash: sandboxed.manifestHash,
|
|
289
|
-
};
|
|
246
|
+
return { manifest: sandboxed.manifest, manifestHash: sandboxed.manifestHash };
|
|
290
247
|
}
|
|
291
248
|
/** The session resource returned by `GET`/`PUT /v1/sessions/:id`. */
|
|
292
249
|
export async function sessionView(t, s) {
|
|
@@ -315,12 +272,11 @@ export async function sessionView(t, s) {
|
|
|
315
272
|
implementationVersion: s.implementationVersion,
|
|
316
273
|
status: s.status,
|
|
317
274
|
activeTurnId: s.activeTurnId,
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
...(s.sandboxSource ? { sandboxSource: s.sandboxSource } : {}),
|
|
275
|
+
environment: s.environmentId === undefined
|
|
276
|
+
? null
|
|
277
|
+
: { id: s.environmentId, version: s.environmentVersion ?? 1 },
|
|
278
|
+
harness: harnessOf(s),
|
|
279
|
+
...(s.closedReason === undefined ? {} : { closedReason: s.closedReason }),
|
|
324
280
|
mcpSnapshot: s.mcpSnapshot ?? null,
|
|
325
281
|
mcpDiagnostics: s.mcpDiagnostics ?? [],
|
|
326
282
|
waits,
|
|
@@ -19,7 +19,11 @@ import type { SigningKeyRow, Tx } from "../store/types.js";
|
|
|
19
19
|
type KeyLike = Awaited<ReturnType<typeof importJWK>>;
|
|
20
20
|
export interface SigningKeysOptions {
|
|
21
21
|
tenantId: string;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* The vault KEK. The gateway's keys service only reads the file `nylorun start` wrote
|
|
24
|
+
* (`gates/tenant-vaults.ts`); an in-process Runtime may create it on first use. Resolve it
|
|
25
|
+
* before opening a transaction.
|
|
26
|
+
*/
|
|
23
27
|
kek(): Buffer;
|
|
24
28
|
}
|
|
25
29
|
export interface CurrentKey {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The skill tools (track R2 M4): `load_skill` and `read_skill_resource`, which the
|
|
3
|
-
* the
|
|
2
|
+
* The skill tools (track R2 M4): `load_skill` and `read_skill_resource`, which the Runtime pins
|
|
3
|
+
* in the `runtime` block of an agent with skills. The Runtime runs them itself, like `save_artifact`, from the
|
|
4
4
|
* definition files uploaded with the agent: no developer process is involved.
|
|
5
5
|
*
|
|
6
6
|
* - `load_skill`: the skill's instructions (its `SKILL.md` after the frontmatter), the paths of
|
|
7
7
|
* its other files, and, when the session has a sandbox, where they are in it
|
|
8
|
-
* (`/skills/<name>/`, read-only).
|
|
8
|
+
* (`/skills/<name>@<hash>/`, read-only, D66).
|
|
9
9
|
* - `read_skill_resource`: one text file of the skill. A binary file is refused: the model reads
|
|
10
10
|
* it in the sandbox, when there is one.
|
|
11
11
|
*
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
import { LOAD_SKILL_TOOL,
|
|
2
|
-
import {
|
|
1
|
+
import { LOAD_SKILL_TOOL, SKILL_ENTRY, skillFolderOf, isSkillTool, skillInstructions, } from "@nylorun/core/define";
|
|
2
|
+
import { sandboxToolSpec } from "../sandbox/runtime-tools.js";
|
|
3
3
|
import { readDefinitionFile } from "./definition-files.js";
|
|
4
4
|
const failed = (code, message) => ({ kind: "failed", code, message });
|
|
5
5
|
/** True when `request` calls a skill tool the Runtime serves for `manifest`'s agent. */
|
|
6
6
|
export function isSkillToolCall(manifest, request) {
|
|
7
|
-
return
|
|
8
|
-
isSkillTool(manifest?.capabilities.find((capability) => capability.id === request.capabilityId), request.toolName));
|
|
7
|
+
return request.kind === "tool" && isSkillTool(manifest, request.toolName);
|
|
9
8
|
}
|
|
10
9
|
/** Every skill of the agent, by name. */
|
|
11
10
|
function skillsOf(manifest) {
|
|
12
|
-
|
|
13
|
-
for (const capability of manifest.capabilities)
|
|
14
|
-
for (const skill of Object.values(capability.skills ?? {}))
|
|
15
|
-
skills.set(skill.name, skill);
|
|
16
|
-
return skills;
|
|
11
|
+
return new Map(Object.values(manifest.skills ?? {}).map((skill) => [skill.name, skill]));
|
|
17
12
|
}
|
|
18
13
|
/** UTF-8 text, or undefined for bytes that are not (a NUL byte, or invalid UTF-8). */
|
|
19
14
|
function textOf(bytes) {
|
|
@@ -35,8 +30,8 @@ export async function callSkillTool(ctx, manifest, request, signal) {
|
|
|
35
30
|
return request.toolName === LOAD_SKILL_TOOL
|
|
36
31
|
? { kind: "completed", output: { unknown: name, available: [...skills.keys()].sort() } }
|
|
37
32
|
: failed("skill.unknown", `There is no skill '${name}'.`);
|
|
38
|
-
const sandboxed =
|
|
39
|
-
const directory = `${
|
|
33
|
+
const sandboxed = sandboxToolSpec(manifest, "bash") !== undefined;
|
|
34
|
+
const directory = `${skillFolderOf(skill)}/`;
|
|
40
35
|
const read = async (path) => {
|
|
41
36
|
const bytes = await readDefinitionFile(ctx.blobs, skill.files[path], signal);
|
|
42
37
|
if (!bytes)
|
package/dist/tenant/status.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FIXTURE_MODEL_SETTING, seedFixtureModel } from "./model-setting.js";
|
|
2
|
-
import {
|
|
2
|
+
import { ENVIRONMENTS_CONFIG_SETTING, writeSandboxConfig } from "../sandbox/tenant-config.js";
|
|
3
3
|
/** The Tenant's harnesses, for its status and the Host's. */
|
|
4
4
|
export function harnessStatusOf(ctx) {
|
|
5
5
|
return { mode: ctx.mcp ? "in-process" : "remote", ...ctx.harness.status() };
|
|
@@ -108,12 +108,12 @@ export async function seedTenantConfig(ctx, body) {
|
|
|
108
108
|
const sandboxConfig = body.sandbox?.config;
|
|
109
109
|
if (sandboxConfig) {
|
|
110
110
|
const inserted = await ctx.store.tx(async (t) => {
|
|
111
|
-
if ((await t.getSetting(
|
|
111
|
+
if ((await t.getSetting(ENVIRONMENTS_CONFIG_SETTING)) !== undefined)
|
|
112
112
|
return false;
|
|
113
113
|
await writeSandboxConfig(t, sandboxConfig);
|
|
114
114
|
return true;
|
|
115
115
|
});
|
|
116
|
-
(inserted ? applied : kept).push(
|
|
116
|
+
(inserted ? applied : kept).push(ENVIRONMENTS_CONFIG_SETTING);
|
|
117
117
|
}
|
|
118
118
|
if (body.fixtureModel) {
|
|
119
119
|
const inserted = await ctx.store.tx((t) => seedFixtureModel(t));
|
package/dist/tenant/sweep.js
CHANGED
|
@@ -28,10 +28,12 @@
|
|
|
28
28
|
* for a Tenant not open on its Worker, an invocation an operator killed, Restate's state
|
|
29
29
|
* wiped (§17.11), or a parked outbox row.
|
|
30
30
|
* 4. **Sandboxes.** Idle sandboxes are stopped, records of compute no longer held are marked
|
|
31
|
-
* stopped, and sandboxes whose session or
|
|
32
|
-
* workspace
|
|
31
|
+
* stopped, and sandboxes whose session or Environment is gone are removed, by the
|
|
32
|
+
* workspace feature (`harness-api/workspace.ts`: here, or in the harness that serves
|
|
33
33
|
* workspaces). Idle MCP connections of the in-process harness are closed. As often as the
|
|
34
|
-
* orphan scan, pod
|
|
34
|
+
* orphan scan, pod Environments whose change stalled get a reconcile (`reconcileStalePods`).
|
|
35
|
+
* Environments unused for their `lifecycle.deleteAfter` are deleted
|
|
36
|
+
* (`sweepUnusedEnvironments`).
|
|
35
37
|
* 5. **Control signals.** Signals on the control bus older than `SIGNAL_RETENTION_MS` are
|
|
36
38
|
* deleted: followers read back only the last two minutes (`store/postgres/control.ts`).
|
|
37
39
|
* 6. **Hooks.** Callbacks registered with `ctx.onSweep`.
|
|
@@ -41,6 +43,8 @@
|
|
|
41
43
|
* step does not stop the others; the first error is rethrown at the end so the execution
|
|
42
44
|
* reports it.
|
|
43
45
|
*/
|
|
46
|
+
import { sweepUnusedEnvironments } from "./environments.js";
|
|
47
|
+
import { sweepPendingSeeds } from "../artifacts/disk.js";
|
|
44
48
|
import { pendingAgentEffects, reconcilePendingAgentEffect, } from "../core/flow-host.js";
|
|
45
49
|
const BATCH = 100;
|
|
46
50
|
/** How long a control signal is kept after it was written. */
|
|
@@ -101,7 +105,7 @@ export async function sweep(ctx) {
|
|
|
101
105
|
() => ctx.sandbox.sweep({
|
|
102
106
|
now: now.getTime(),
|
|
103
107
|
sessionExists: async (id) => !!(await ctx.store.tx((t) => t.get("sessions", id))),
|
|
104
|
-
sandboxExists: async (id) => (await ctx.store.tx((t) => t.
|
|
108
|
+
sandboxExists: async (id) => (await ctx.store.tx((t) => t.environment(id))) !== undefined,
|
|
105
109
|
}),
|
|
106
110
|
],
|
|
107
111
|
...(checkPods
|
|
@@ -115,6 +119,10 @@ export async function sweep(ctx) {
|
|
|
115
119
|
],
|
|
116
120
|
]
|
|
117
121
|
: []),
|
|
122
|
+
// Environments unused for their `lifecycle.deleteAfter`: one query when none is due.
|
|
123
|
+
["environments", () => sweepUnusedEnvironments(ctx, now.getTime())],
|
|
124
|
+
// Seeds of new volumes whose engine is connected and no process copies (R2d step 3).
|
|
125
|
+
["seeds", () => sweepPendingSeeds(ctx)],
|
|
118
126
|
// A harness elsewhere closes its own idle MCP connections.
|
|
119
127
|
["mcp", async () => ctx.mcp?.sweep()],
|
|
120
128
|
[
|
|
@@ -257,16 +265,14 @@ const STALE_POD_MS = 60_000;
|
|
|
257
265
|
async function reconcileStalePods(ctx, now) {
|
|
258
266
|
if (!ctx.pods)
|
|
259
267
|
return;
|
|
260
|
-
const stale = await ctx.store.tx(async (t) => (await t.
|
|
268
|
+
const stale = await ctx.store.tx(async (t) => (await t.listEnvironments()).filter((row) => {
|
|
261
269
|
const pod = row.pod;
|
|
262
270
|
if (!pod || now.getTime() - Date.parse(row.updatedAt) < STALE_POD_MS)
|
|
263
271
|
return false;
|
|
264
|
-
const expiring = pod.expiresAt !== undefined && Date.parse(pod.expiresAt) <= now.getTime() && pod.observed !== "expired";
|
|
265
272
|
return (pod.desired === "deleted" ||
|
|
266
273
|
pod.retiring !== undefined ||
|
|
267
274
|
pod.observed === "creating" ||
|
|
268
275
|
pod.observed === "deleting" ||
|
|
269
|
-
expiring ||
|
|
270
276
|
(pod.desired === "suspended" && pod.observed !== "suspended") ||
|
|
271
277
|
// Running, but its engine is not connected: the pod may be gone, or its volume.
|
|
272
278
|
(pod.desired === "running" && pod.observed === "running" && !ctx.harness.hosting(row.id)));
|
|
@@ -170,7 +170,7 @@ async function shapeBinary(shaping, part, index) {
|
|
|
170
170
|
kept.size <= MODEL_FILE_MAX_BYTES)
|
|
171
171
|
shaping.files.push({
|
|
172
172
|
mediaType: contentType,
|
|
173
|
-
reference: { artifactId: kept.artifactId, version: kept.version, name },
|
|
173
|
+
reference: { artifactId: kept.artifactId, version: kept.version, name, size: kept.size },
|
|
174
174
|
});
|
|
175
175
|
return {
|
|
176
176
|
type: part.type,
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `tool_search` (R2b C10, Q20): core finds an agent's deferred MCP tools in the session's pinned
|
|
3
|
-
* snapshot, ranked with BM25 over their names and descriptions, and returns each match's name,
|
|
4
|
-
* description and `inputSchema`, for the model to run with `tool_call`. It reads only the pinned
|
|
5
|
-
* snapshot, so the same query finds the same tools for the session's life; a tool the turn's
|
|
6
|
-
* manifest disables is never found.
|
|
7
|
-
*/
|
|
8
|
-
import { type AgentManifest } from "@nylorun/core/define";
|
|
9
1
|
import type { HostEffect } from "@nylorun/harness/run";
|
|
10
|
-
import { type McpToolRecord } from "../mcp/snapshot.js";
|
|
2
|
+
import { type McpSnapshot, type McpToolRecord } from "../mcp/snapshot.js";
|
|
11
3
|
import { type TenantContext } from "./context.js";
|
|
12
|
-
/**
|
|
13
|
-
|
|
4
|
+
/**
|
|
5
|
+
* True when `request` calls `tool_search`, the session tool an agent gets when the session's
|
|
6
|
+
* pinned snapshot holds deferred tools of its own. The name is reserved: no tool of the agent's
|
|
7
|
+
* own takes it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isToolSearchCall(snapshot: McpSnapshot | undefined, request: HostEffect): boolean;
|
|
14
10
|
/** Runs `tool_search` for the run's agent. */
|
|
15
11
|
export declare function callToolSearch(ctx: TenantContext, request: HostEffect): Promise<{
|
|
16
12
|
output?: undefined;
|
|
@@ -5,19 +5,22 @@
|
|
|
5
5
|
* snapshot, so the same query finds the same tools for the session's life; a tool the turn's
|
|
6
6
|
* manifest disables is never found.
|
|
7
7
|
*/
|
|
8
|
-
import { TOOL_SEARCH_DEFAULT_LIMIT, TOOL_SEARCH_MAX_LIMIT, TOOL_SEARCH_TOOL,
|
|
8
|
+
import { TOOL_SEARCH_DEFAULT_LIMIT, TOOL_SEARCH_MAX_LIMIT, TOOL_SEARCH_TOOL, } from "@nylorun/core/define";
|
|
9
9
|
import { isEnabledIn } from "../mcp/snapshot.js";
|
|
10
10
|
import { sessionOf } from "./context.js";
|
|
11
11
|
import { turnManifestOf } from "./session.js";
|
|
12
12
|
/** BM25's term saturation and length normalization, the usual values. */
|
|
13
13
|
const K1 = 1.2;
|
|
14
14
|
const B = 0.75;
|
|
15
|
-
/**
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* True when `request` calls `tool_search`, the session tool an agent gets when the session's
|
|
17
|
+
* pinned snapshot holds deferred tools of its own. The name is reserved: no tool of the agent's
|
|
18
|
+
* own takes it.
|
|
19
|
+
*/
|
|
20
|
+
export function isToolSearchCall(snapshot, request) {
|
|
17
21
|
return (request.kind === "tool" &&
|
|
18
|
-
request.capabilityId === TOOLS_CAPABILITY_ID &&
|
|
19
22
|
request.toolName === TOOL_SEARCH_TOOL &&
|
|
20
|
-
|
|
23
|
+
snapshot?.mcpTools.some((tool) => tool.deferred === true && tool.agentId === request.agent?.id) === true);
|
|
21
24
|
}
|
|
22
25
|
/** Runs `tool_search` for the run's agent. */
|
|
23
26
|
export async function callToolSearch(ctx, request) {
|