@nylorun/runtime 0.25.0-beta → 0.27.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 +169 -0
- package/README.md +26 -16
- package/dist/adapters/execution/restate.d.ts +15 -18
- package/dist/adapters/execution/restate.js +31 -27
- package/dist/adapters/replication/pgoutput.d.ts +1 -1
- package/dist/adapters/replication/pgoutput.js +3 -2
- package/dist/adapters/sandbox/local.js +8 -5
- package/dist/adapters/sandbox/virtual.js +2 -2
- package/dist/adapters/streams/s2.d.ts +1 -1
- package/dist/adapters/streams/s2.js +18 -14
- package/dist/api/a2a/card.js +1 -1
- package/dist/api/a2a/endpoint.js +3 -4
- package/dist/api/a2a/protocol.js +4 -0
- package/dist/api/a2a/routes.d.ts +2 -6
- package/dist/api/a2a/routes.js +12 -18
- package/dist/api/ag-ui/endpoint.js +2 -3
- package/dist/api/ag-ui/routes.js +4 -4
- package/dist/api/components.d.ts +326 -45
- package/dist/api/components.js +5 -1
- package/dist/api/gate/keys.js +7 -4
- package/dist/api/gate/routes.d.ts +6 -2
- package/dist/api/gate/routes.js +15 -11
- package/dist/api/http/app.d.ts +2 -2
- package/dist/api/http/app.js +2 -2
- package/dist/api/http/body.d.ts +15 -3
- package/dist/api/http/body.js +15 -7
- package/dist/api/http/define.d.ts +1 -1
- package/dist/api/http/respond.js +7 -3
- package/dist/api/http/routes/access.js +5 -4
- package/dist/api/http/routes/artifacts.js +19 -7
- package/dist/api/http/routes/coverage.js +1 -1
- package/dist/api/http/routes/environment-manifests.js +1 -1
- package/dist/api/http/routes/environments.js +6 -6
- package/dist/api/http/routes/files.d.ts +2 -1
- package/dist/api/http/routes/files.js +31 -5
- package/dist/api/http/routes/mcp.js +1 -1
- package/dist/api/http/routes/reads.d.ts +35 -0
- package/dist/api/http/routes/reads.js +50 -22
- package/dist/api/http/routes/sessions.js +12 -11
- package/dist/api/http/routes/tenant.d.ts +2 -2
- package/dist/api/http/routes/tenant.js +69 -16
- package/dist/api/inbound-files.d.ts +3 -9
- package/dist/api/inbound-files.js +18 -24
- package/dist/api/openapi.js +6 -2
- package/dist/artifacts/disk.d.ts +0 -4
- package/dist/artifacts/disk.js +77 -73
- package/dist/artifacts/files.d.ts +13 -4
- package/dist/artifacts/files.js +27 -9
- package/dist/artifacts/folder-upload.d.ts +75 -0
- package/dist/artifacts/folder-upload.js +263 -0
- package/dist/artifacts/folders.d.ts +14 -8
- package/dist/artifacts/folders.js +19 -11
- package/dist/artifacts/links.js +7 -6
- package/dist/artifacts/parts.d.ts +9 -14
- package/dist/artifacts/parts.js +11 -9
- package/dist/artifacts/pipe.d.ts +15 -0
- package/dist/artifacts/pipe.js +71 -0
- package/dist/artifacts/quota.d.ts +36 -0
- package/dist/artifacts/quota.js +44 -0
- package/dist/artifacts/service.d.ts +25 -1
- package/dist/artifacts/service.js +70 -25
- package/dist/blob/fs.js +2 -1
- package/dist/blob/s3.d.ts +6 -2
- package/dist/blob/s3.js +9 -7
- package/dist/blob/types.d.ts +1 -1
- package/dist/blob/types.js +1 -1
- package/dist/core/limits.d.ts +11 -35
- package/dist/core/limits.js +5 -73
- package/dist/core/sandbox-routes.js +0 -1
- package/dist/core/turn-manifest.d.ts +1 -2
- package/dist/core/turn-manifest.js +4 -28
- package/dist/execution/memory.d.ts +8 -5
- package/dist/execution/memory.js +8 -6
- package/dist/execution/types.d.ts +1 -6
- package/dist/execution/types.js +0 -5
- package/dist/gates/contract.d.ts +3 -2
- package/dist/gates/contract.js +1 -1
- package/dist/gates/egress-credentials.js +4 -3
- package/dist/gates/egress.d.ts +9 -9
- package/dist/gates/egress.js +19 -19
- package/dist/gates/fixture-model.js +13 -2
- package/dist/gates/handler.d.ts +1 -3
- package/dist/gates/handler.js +4 -3
- package/dist/gates/http-client.d.ts +4 -3
- package/dist/gates/http-client.js +5 -7
- package/dist/gates/http-tool.d.ts +24 -4
- package/dist/gates/http-tool.js +53 -17
- package/dist/gates/in-process.d.ts +2 -1
- package/dist/gates/in-process.js +17 -9
- package/dist/gates/inflight.d.ts +2 -2
- package/dist/gates/inflight.js +3 -2
- package/dist/gates/journal.js +5 -7
- package/dist/gates/mcp-handler.d.ts +4 -3
- package/dist/gates/mcp-handler.js +15 -5
- package/dist/gates/model-gate.d.ts +11 -2
- package/dist/gates/policy.d.ts +28 -5
- package/dist/gates/policy.js +60 -17
- package/dist/gates/provider-gate.d.ts +22 -0
- package/dist/gates/provider-gate.js +30 -0
- package/dist/gates/tool-calls.d.ts +1 -3
- package/dist/gates/tool-calls.js +2 -3
- package/dist/gates/tool-client.d.ts +1 -1
- package/dist/gates/tool-client.js +5 -6
- package/dist/gates/tool-contract.d.ts +8 -5
- package/dist/gates/tool-contract.js +1 -1
- package/dist/gates/tool-gate.d.ts +18 -7
- package/dist/gates/tool-gate.js +49 -7
- package/dist/harness/calls.d.ts +27 -25
- package/dist/harness/calls.js +40 -46
- package/dist/harness/executors.d.ts +10 -3
- package/dist/harness/executors.js +53 -23
- package/dist/harness/main.js +2 -2
- package/dist/harness/pod.d.ts +0 -2
- package/dist/harness/pod.js +7 -6
- package/dist/harness/run-tokens.d.ts +4 -1
- package/dist/harness/run-tokens.js +6 -2
- package/dist/harness/service.d.ts +17 -14
- package/dist/harness/service.js +21 -35
- package/dist/harness/setup.d.ts +0 -2
- package/dist/harness/setup.js +4 -9
- package/dist/harness/ws-client.d.ts +2 -2
- package/dist/harness/ws-client.js +7 -5
- package/dist/harness/ws-port.d.ts +3 -4
- package/dist/harness/ws-port.js +3 -4
- package/dist/harness-api/artifacts.d.ts +20 -0
- package/dist/harness-api/artifacts.js +478 -0
- package/dist/harness-api/in-process.d.ts +2 -2
- package/dist/harness-api/in-process.js +18 -16
- package/dist/harness-api/record.d.ts +10 -9
- package/dist/harness-api/record.js +102 -157
- package/dist/harness-api/renew.d.ts +1 -1
- package/dist/harness-api/renew.js +2 -2
- package/dist/harness-api/server.d.ts +1 -16
- package/dist/harness-api/server.js +82 -73
- package/dist/harness-api/start.d.ts +20 -2
- package/dist/harness-api/start.js +57 -18
- package/dist/harness-api/tool-journal.d.ts +15 -10
- package/dist/harness-api/tool-journal.js +26 -24
- package/dist/harness-api/workspace.d.ts +0 -4
- package/dist/harness-api/workspace.js +2 -45
- package/dist/harness-api/ws-server.js +10 -10
- package/dist/host/create-host.js +2 -3
- package/dist/host/execution.js +2 -3
- package/dist/host/gates.d.ts +2 -9
- package/dist/host/gates.js +15 -12
- package/dist/host/http.d.ts +0 -2
- package/dist/host/http.js +0 -27
- package/dist/host/main.js +10 -3
- package/dist/host/operate.js +12 -3
- package/dist/host/stack-config.d.ts +11 -0
- package/dist/host/stack-config.js +21 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/infra/index.js +2 -1
- package/dist/infra/readiness.d.ts +0 -2
- package/dist/infra/readiness.js +4 -3
- package/dist/keys/client.d.ts +1 -0
- package/dist/keys/client.js +2 -3
- package/dist/keys/contract.d.ts +1 -3
- package/dist/keys/contract.js +1 -3
- package/dist/keys/egress-ca.d.ts +0 -2
- package/dist/keys/egress-ca.js +2 -3
- package/dist/keys/keys.js +6 -1
- package/dist/keys/x509.d.ts +8 -4
- package/dist/keys/x509.js +14 -5
- package/dist/management-openapi.json +1961 -994
- package/dist/mcp/connect.d.ts +35 -26
- package/dist/mcp/connect.js +112 -141
- package/dist/mcp/pool.d.ts +27 -22
- package/dist/mcp/pool.js +34 -48
- package/dist/mcp/preview.d.ts +13 -6
- package/dist/mcp/preview.js +37 -20
- package/dist/mcp/snapshot.d.ts +35 -86
- package/dist/mcp/snapshot.js +93 -135
- package/dist/model/auth-store.js +5 -3
- package/dist/model/capabilities.d.ts +1 -1
- package/dist/model/catalog.d.ts +9 -36
- package/dist/model/catalog.js +6 -33
- package/dist/model/descriptor.d.ts +51 -0
- package/dist/model/descriptor.js +83 -0
- package/dist/model/models.d.ts +0 -3
- package/dist/model/models.js +3 -5
- package/dist/model/native-blocks.js +1 -1
- package/dist/model/pi-model.d.ts +16 -5
- package/dist/model/pi-model.js +86 -105
- package/dist/openapi.json +866 -1218
- package/dist/reads/cursor.js +3 -1
- package/dist/record/append.d.ts +34 -2
- package/dist/record/append.js +50 -1
- package/dist/record/environment.d.ts +2 -0
- package/dist/record/environment.js +2 -0
- package/dist/record/index.d.ts +1 -1
- package/dist/record/index.js +1 -1
- package/dist/redact.d.ts +1 -1
- package/dist/redact.js +3 -2
- package/dist/sandbox/egress-token.d.ts +3 -3
- package/dist/sandbox/egress-token.js +3 -3
- package/dist/sandbox/join.js +3 -2
- package/dist/sandbox/manager.d.ts +41 -41
- package/dist/sandbox/manager.js +112 -44
- package/dist/sandbox/placement.d.ts +1 -1
- package/dist/sandbox/placement.js +5 -8
- package/dist/sandbox/pods/client.d.ts +1 -10
- package/dist/sandbox/pods/client.js +8 -4
- package/dist/sandbox/pods/lifecycle.d.ts +19 -11
- package/dist/sandbox/pods/lifecycle.js +45 -23
- package/dist/sandbox/pods/network-gate.d.ts +4 -5
- package/dist/sandbox/pods/network-gate.js +7 -7
- package/dist/sandbox/pods/reconcile.js +4 -1
- package/dist/sandbox/pods/spec.js +8 -5
- package/dist/sandbox/policy.d.ts +7 -1
- package/dist/sandbox/policy.js +10 -3
- package/dist/sandbox/resolve.d.ts +8 -3
- package/dist/sandbox/resolve.js +12 -2
- package/dist/sandbox/setup.d.ts +3 -1
- package/dist/sandbox/setup.js +34 -11
- package/dist/sandbox/share.d.ts +5 -14
- package/dist/sandbox/share.js +5 -34
- package/dist/sandbox/skills.d.ts +7 -13
- package/dist/sandbox/skills.js +16 -31
- package/dist/sandbox/tenant-config.d.ts +2 -2
- package/dist/sandbox/tenant-config.js +4 -3
- package/dist/sandbox/tools.d.ts +7 -1
- package/dist/sandbox/tools.js +26 -26
- package/dist/sandbox/types.d.ts +10 -3
- package/dist/sandbox/types.js +9 -0
- package/dist/store/postgres/connect.d.ts +6 -5
- package/dist/store/postgres/connect.js +14 -11
- package/dist/store/postgres/control.js +13 -13
- package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
- package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
- package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
- package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
- package/dist/store/postgres/migrate.js +1 -1
- package/dist/store/postgres/reads.js +10 -2
- package/dist/store/postgres/schema.d.ts +19 -0
- package/dist/store/postgres/schema.js +7 -0
- package/dist/store/postgres/store.js +55 -26
- package/dist/store/types.d.ts +17 -7
- package/dist/streams/relay/core.d.ts +3 -3
- package/dist/streams/relay/core.js +9 -10
- package/dist/tenant/advance.js +21 -31
- package/dist/tenant/commands.js +9 -16
- package/dist/tenant/context.d.ts +14 -17
- package/dist/tenant/definition-files.d.ts +25 -4
- package/dist/tenant/definition-files.js +85 -47
- package/dist/tenant/effects.js +9 -36
- package/dist/tenant/environment-manifests.js +9 -1
- package/dist/tenant/environments.d.ts +0 -2
- package/dist/tenant/environments.js +54 -30
- package/dist/tenant/ephemeral.d.ts +1 -1
- package/dist/tenant/ephemeral.js +2 -1
- package/dist/tenant/history.d.ts +1 -1
- package/dist/tenant/history.js +1 -1
- package/dist/tenant/host-token.d.ts +3 -3
- package/dist/tenant/host-token.js +12 -11
- package/dist/tenant/http.d.ts +5 -8
- package/dist/tenant/http.js +9 -0
- package/dist/tenant/identity-file.d.ts +24 -1
- package/dist/tenant/identity-file.js +35 -7
- package/dist/tenant/issuers.d.ts +5 -5
- package/dist/tenant/issuers.js +31 -23
- package/dist/tenant/jwt.d.ts +8 -2
- package/dist/tenant/jwt.js +10 -2
- package/dist/tenant/limits.d.ts +90 -0
- package/dist/tenant/limits.js +175 -0
- package/dist/tenant/module.d.ts +4 -1
- package/dist/tenant/module.js +9 -8
- package/dist/tenant/outbound.d.ts +17 -19
- package/dist/tenant/outbound.js +18 -21
- package/dist/tenant/run-grants.js +3 -2
- package/dist/tenant/run-token.d.ts +0 -4
- package/dist/tenant/run-token.js +6 -11
- package/dist/tenant/runtime-limits.d.ts +24 -0
- package/dist/tenant/runtime-limits.js +27 -0
- package/dist/tenant/runtime.js +30 -43
- package/dist/tenant/session-streams.js +7 -6
- package/dist/tenant/session.d.ts +1 -1
- package/dist/tenant/session.js +1 -1
- package/dist/tenant/sessions.js +32 -29
- package/dist/tenant/signing-keys.d.ts +1 -1
- package/dist/tenant/signing-keys.js +5 -6
- package/dist/tenant/status.js +4 -3
- package/dist/tenant/streams.js +18 -20
- package/dist/tenant/sweep.d.ts +1 -21
- package/dist/tenant/sweep.js +39 -48
- package/dist/tenant/transcript.d.ts +70 -23
- package/dist/tenant/transcript.js +28 -22
- package/dist/tenant/types.d.ts +11 -16
- package/dist/tenant/worker.d.ts +2 -10
- package/dist/tenant/worker.js +5 -14
- package/dist/traces/ids.js +5 -1
- package/dist/traces/map.d.ts +9 -6
- package/dist/traces/map.js +9 -11
- package/dist/traces/otlp.d.ts +3 -3
- package/dist/traces/otlp.js +5 -3
- package/dist/traces/projector.d.ts +9 -4
- package/dist/traces/projector.js +13 -7
- package/dist/traces/read.js +6 -1
- package/dist/tuning.d.ts +383 -0
- package/dist/tuning.js +658 -0
- package/dist/vault/headers.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/artifacts/export.d.ts +0 -8
- package/dist/artifacts/export.js +0 -204
- package/dist/artifacts/media-types.d.ts +0 -30
- package/dist/artifacts/media-types.js +0 -137
- package/dist/artifacts/workspace.d.ts +0 -60
- package/dist/artifacts/workspace.js +0 -45
- package/dist/media.d.ts +0 -10
- package/dist/media.js +0 -58
- package/dist/sandbox/runtime-tools.d.ts +0 -9
- package/dist/sandbox/runtime-tools.js +0 -16
- package/dist/sandbox/session-sandbox.d.ts +0 -16
- package/dist/sandbox/session-sandbox.js +0 -77
- package/dist/tenant/artifact-tool.d.ts +0 -13
- package/dist/tenant/artifact-tool.js +0 -243
- package/dist/tenant/skill-tool.d.ts +0 -20
- package/dist/tenant/skill-tool.js +0 -67
- package/dist/tenant/tool-results.d.ts +0 -57
- package/dist/tenant/tool-results.js +0 -298
- package/dist/tenant/tool-search.d.ts +0 -39
- package/dist/tenant/tool-search.js +0 -103
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The Record seam of the Harness API: core's journal for the effects of a run. `recordIntent`
|
|
3
3
|
* journals an effect before anything runs it, and either answers it from the journal, hands it
|
|
4
|
-
* to core's own executors (flow work, delegation, `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* to core's own executors (flow work, delegation), tells the harness to `execute` it (model calls;
|
|
5
|
+
* a flow's HTTP stages and HTTP verifiers; an agent's tool call whose target the session has,
|
|
6
|
+
* protocol 15: an `mcp` tool it discovered and the turn leaves enabled, by `{server, tool}`; an
|
|
7
|
+
* `http` tool it declares; a `sandbox` operation when it has a sandbox; a `harness` tool), or
|
|
8
|
+
* fails a tool call it cannot run (no target, as an author's code tool has, R2 M6, or one the
|
|
9
|
+
* session lacks). A tool call is routed by its target, never by its name. `recordOutcome`
|
|
10
|
+
* records what the harness's call returned, as the harness reported it: one record entry, refused
|
|
11
|
+
* past the Runtime limit `recordEntryBytes` (`limit_exceeded`), since the harness shapes tool
|
|
12
|
+
* results, not core. Both run under the advance's lease: every write is epoch-checked
|
|
13
|
+
* (`ownedSession`), and a lost epoch writes nothing.
|
|
11
14
|
*
|
|
12
15
|
* Rows store the request's hash (`requestHash`) and, for a model call, the request without its
|
|
13
16
|
* prompt: drift is a hash compare. Rows written before carry their full request, hashed on read.
|
|
@@ -19,26 +22,24 @@
|
|
|
19
22
|
* harness and the Tool Gate reads with the row.
|
|
20
23
|
*/
|
|
21
24
|
import { HarnessApiError, effectRequestHash, isEffectIdOf, } from "@nylorun/core/harness-api";
|
|
25
|
+
import { isSandboxToolName } from "@nylorun/core/define";
|
|
22
26
|
import { isFlowEffect, isFlowToolEffect, recordVerdict, settleAgentEffect, } from "../core/flow-host.js";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import { mayNeedShaping, resultBytes, resultLimit, shapeToolOutcome, } from "../tenant/tool-results.js";
|
|
27
|
-
import { callSkillTool, isSkillToolCall } from "../tenant/skill-tool.js";
|
|
28
|
-
import { callToolSearch, isToolSearchCall } from "../tenant/tool-search.js";
|
|
27
|
+
import { sessionSandboxSpec } from "../sandbox/share.js";
|
|
28
|
+
import { readRuntimeLimits } from "../tenant/runtime-limits.js";
|
|
29
|
+
import { checkEntry } from "../record/index.js";
|
|
29
30
|
import { turnManifestOf } from "../tenant/session.js";
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
31
|
+
import { isEnabledIn, manifestFor, mcpToolIn } from "../mcp/snapshot.js";
|
|
32
|
+
import { findServer } from "../mcp/pool.js";
|
|
32
33
|
import { isHttpToolCall } from "../gates/http-tool.js";
|
|
33
34
|
import { ownedSession } from "../tenant/context.js";
|
|
34
35
|
import { isGateToolEffect, linkedOutcome, recoversModelCalls, recoversToolCalls, resolveNewFlowEffect, } from "../tenant/effects.js";
|
|
35
|
-
import { assistantMessage,
|
|
36
|
+
import { assistantMessage, modelFailed, modelOutcomeFacts, } from "../tenant/transcript.js";
|
|
36
37
|
import { abortKind } from "../tenant/worker.js";
|
|
37
38
|
import { redactTokens } from "./redact.js";
|
|
38
39
|
import { toolCallDecision } from "../gates/policy.js";
|
|
39
40
|
import { traceKey } from "../traces/key.js";
|
|
40
41
|
import { effectSpanOf, traceparentOf, turnTraceIdOf } from "../traces/ids.js";
|
|
41
|
-
import {
|
|
42
|
+
import { firstSend, interrupted, settleToolRow, toolKindOf, } from "./tool-journal.js";
|
|
42
43
|
const TURN_CANCELLED = () => new HarnessApiError("turn_cancelled", "Turn cancelled");
|
|
43
44
|
/** The hash a journal row's request was recorded with. */
|
|
44
45
|
export function hashOf(row) {
|
|
@@ -137,36 +138,20 @@ export async function recordIntent(scope, effect, requestHash) {
|
|
|
137
138
|
const agentManifest = manifestFor(s.manifest, request.agent);
|
|
138
139
|
if (!agentManifest)
|
|
139
140
|
throw new Error(`Agent '${request.agent?.id ?? ""}' is not used as a tool`);
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
sandboxToolSpec(agentManifest, request.toolName) !== undefined ||
|
|
147
|
-
// `save_artifact` (F8.1) runs beside the sandbox tools, as do `read_artifact` (R2b
|
|
148
|
-
// C11) and the skill tools (R2 M4).
|
|
149
|
-
isSaveArtifactCall(agentManifest, request) ||
|
|
150
|
-
isReadArtifactCall(agentManifest, request) ||
|
|
151
|
-
isSkillToolCall(agentManifest, request) ||
|
|
152
|
-
// `tool_search` (R2b C10) reads the session's pinned MCP snapshot: core serves it.
|
|
153
|
-
isToolSearchCall(s.mcpSnapshot, request) ||
|
|
154
|
-
// A tool the run's harness declared and runs itself (R4.2, Q3), by its name: the turn
|
|
155
|
-
// refuses a native tool whose name another tool of the agent's has (`harness-api/server.ts`).
|
|
156
|
-
(request.toolName !== undefined && scope.nativeTools?.has(request.toolName) === true)));
|
|
157
|
-
if (!executed) {
|
|
158
|
-
// A tool that would run the developer's code: refused at save (a turn's manifest only
|
|
159
|
-
// removes tools), so this is a backstop, as is an MCP tool the turn disabled, which the
|
|
160
|
-
// model was never offered. The model sees the failure; nothing runs.
|
|
161
|
-
const disabled = request.kind === "tool" && mcpToolOf(s.mcpSnapshot, request) !== undefined;
|
|
141
|
+
const refused = request.kind === "tool" ? refusal(s, request) : undefined;
|
|
142
|
+
if (refused) {
|
|
143
|
+
// A call with no target (an author's code tool, refused at save, so a backstop), or one
|
|
144
|
+
// whose target the session lacks: an MCP tool it never discovered or the turn disables, an
|
|
145
|
+
// HTTP tool its agent does not declare, a sandbox call without a sandbox. The model sees
|
|
146
|
+
// the failure; nothing runs.
|
|
162
147
|
const row = {
|
|
163
148
|
request,
|
|
164
149
|
requestHash,
|
|
165
150
|
status: "invoking",
|
|
166
|
-
...toolKindOf(s, agentManifest, request
|
|
151
|
+
...toolKindOf(s, agentManifest, request),
|
|
167
152
|
attempts: 0,
|
|
168
153
|
};
|
|
169
|
-
const outcome = await settleToolRow(t, s, row,
|
|
154
|
+
const outcome = await settleToolRow(t, s, row, refused, { writer: coreIn(scope) });
|
|
170
155
|
return { status: "completed", outcome };
|
|
171
156
|
}
|
|
172
157
|
const row = {
|
|
@@ -175,7 +160,7 @@ export async function recordIntent(scope, effect, requestHash) {
|
|
|
175
160
|
requestHash,
|
|
176
161
|
status: "invoking",
|
|
177
162
|
...(request.kind === "tool"
|
|
178
|
-
? { ...firstSend(toolKindOf(s, agentManifest, request
|
|
163
|
+
? { ...firstSend(toolKindOf(s, agentManifest, request)), ...traced() }
|
|
179
164
|
: { startedAt: new Date().toISOString() }),
|
|
180
165
|
};
|
|
181
166
|
// The Tenant's tool policy decides an MCP or HTTP tool call as it is journaled (R5 step 2).
|
|
@@ -185,28 +170,8 @@ export async function recordIntent(scope, effect, requestHash) {
|
|
|
185
170
|
return decided;
|
|
186
171
|
}
|
|
187
172
|
await t.put("effects", request.effectId, row);
|
|
188
|
-
// `save_artifact` writes the Tenant's artifacts: core runs it, reading the file through the
|
|
189
|
-
// workspace feature, wherever the sandbox is.
|
|
190
|
-
if (request.kind === "tool" && isSaveArtifactCall(agentManifest, request))
|
|
191
|
-
return "save";
|
|
192
|
-
// `read_artifact` reads the session's artifacts: core serves it, with or without a sandbox.
|
|
193
|
-
if (isReadArtifactCall(agentManifest, request))
|
|
194
|
-
return "read";
|
|
195
|
-
// The skill tools read the agent's definition files: core serves them.
|
|
196
|
-
if (isSkillToolCall(agentManifest, request))
|
|
197
|
-
return { skill: agentManifest };
|
|
198
|
-
if (isToolSearchCall(s.mcpSnapshot, request))
|
|
199
|
-
return "search";
|
|
200
173
|
return { status: "execute", ...(row.traceparent ? { traceparent: row.traceparent } : {}) };
|
|
201
174
|
});
|
|
202
|
-
if (answer === "save")
|
|
203
|
-
return runInCore(scope, request, () => callSaveArtifact(scope.ctx, request, scope.signal));
|
|
204
|
-
if (answer === "read")
|
|
205
|
-
return runInCore(scope, request, () => callReadArtifact(scope.ctx, request, scope.signal));
|
|
206
|
-
if (answer === "search")
|
|
207
|
-
return runInCore(scope, request, () => callToolSearch(scope.ctx, request));
|
|
208
|
-
if (typeof answer === "object" && "skill" in answer)
|
|
209
|
-
return runInCore(scope, request, () => callSkillTool(scope.ctx, answer.skill, request, scope.signal));
|
|
210
175
|
if (answer !== "flow")
|
|
211
176
|
return answer;
|
|
212
177
|
if (!isFlowEffect(request))
|
|
@@ -214,27 +179,50 @@ export async function recordIntent(scope, effect, requestHash) {
|
|
|
214
179
|
return resolveNewFlowEffect(ctx, request, signal, lease);
|
|
215
180
|
}
|
|
216
181
|
/**
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* the
|
|
182
|
+
* Why an agent's tool call cannot run, by what it names as its target (protocol 15), or
|
|
183
|
+
* undefined when it can:
|
|
184
|
+
*
|
|
185
|
+
* - `mcp`: the tool `{server, tool}` of an MCP server its agent declares, as the session
|
|
186
|
+
* discovered it (`tool.unknown` otherwise), left enabled by the turn's manifest (R2b C9,
|
|
187
|
+
* `tool.disabled`);
|
|
188
|
+
* - `http`: an HTTP tool its agent declares under that name (R2 M3), which crosses the Tool Gate;
|
|
189
|
+
* - `sandbox`: one of the sandbox operations, in a session with a sandbox;
|
|
190
|
+
* - `harness`: a tool the harness runs in its own process; its egress gate is its only control.
|
|
191
|
+
*
|
|
192
|
+
* No target, and anything else, runs nothing (`tool.unavailable`).
|
|
221
193
|
*/
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
194
|
+
function refusal(s, request) {
|
|
195
|
+
const target = request.target;
|
|
196
|
+
switch (target?.kind) {
|
|
197
|
+
case "mcp": {
|
|
198
|
+
const agentId = request.agent?.id;
|
|
199
|
+
if (!findServer(s.manifest, agentId, target.server) || !mcpToolIn(s.mcpSnapshot, agentId, target.server, target.tool))
|
|
200
|
+
return {
|
|
201
|
+
kind: "failed",
|
|
202
|
+
code: "tool.unknown",
|
|
203
|
+
message: `Tool '${target.tool}' of MCP server '${target.server}' was not discovered for this session.`,
|
|
204
|
+
};
|
|
205
|
+
if (!isEnabledIn(turnManifestOf(s), agentId, target.server, target.tool))
|
|
206
|
+
return {
|
|
207
|
+
kind: "failed",
|
|
208
|
+
code: "tool.disabled",
|
|
209
|
+
message: `Tool '${target.tool}' is disabled by its MCP server's tools settings.`,
|
|
210
|
+
};
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
case "http":
|
|
214
|
+
return isHttpToolCall(s.manifest, request) ? undefined : unrunnableTool(request);
|
|
215
|
+
case "sandbox":
|
|
216
|
+
return sessionSandboxSpec(s) !== undefined &&
|
|
217
|
+
request.toolName !== undefined &&
|
|
218
|
+
isSandboxToolName(request.toolName)
|
|
219
|
+
? undefined
|
|
220
|
+
: unrunnableTool(request);
|
|
221
|
+
case "harness":
|
|
222
|
+
return undefined;
|
|
223
|
+
default:
|
|
224
|
+
return unrunnableTool(request);
|
|
236
225
|
}
|
|
237
|
-
return recordOutcome(core, request.effectId, { value });
|
|
238
226
|
}
|
|
239
227
|
/** Core's own write during the scope's run (R4.9): core saw it, in that run. */
|
|
240
228
|
function coreIn(scope) {
|
|
@@ -244,9 +232,9 @@ function coreIn(scope) {
|
|
|
244
232
|
/**
|
|
245
233
|
* The answer to a tool row still `invoking` (R5.3, R5.4): a crash, a shutdown or a lost gate
|
|
246
234
|
* hop interrupted its send. An MCP or HTTP call (it crosses the Tool Gate, which hands the tool
|
|
247
|
-
* its key) is sent again, one more attempt, until `
|
|
248
|
-
* model. Any other call (sandbox, core-served) has no key to dedupe on: it fails to the
|
|
249
|
-
* now, and is not run again (Q2).
|
|
235
|
+
* its key) is sent again, one more attempt, until the Tenant's `toolAttempts`; then it fails to the
|
|
236
|
+
* model. Any other call (sandbox, harness, core-served) has no key to dedupe on: it fails to the
|
|
237
|
+
* model now, and is not run again (Q2).
|
|
250
238
|
*/
|
|
251
239
|
async function resend(t, s, row, rejoin) {
|
|
252
240
|
if (!isGateToolEffect(s, row.request)) {
|
|
@@ -254,8 +242,9 @@ async function resend(t, s, row, rejoin) {
|
|
|
254
242
|
return { status: "completed", outcome };
|
|
255
243
|
}
|
|
256
244
|
const attempts = (row.attempts ?? 1) + 1;
|
|
257
|
-
|
|
258
|
-
|
|
245
|
+
const { toolAttempts } = await readRuntimeLimits(t);
|
|
246
|
+
if (attempts > toolAttempts) {
|
|
247
|
+
const outcome = await settleToolRow(t, s, row, interrupted(`The call was interrupted ${toolAttempts} times and may have run (the Runtime limit toolAttempts).`));
|
|
259
248
|
return { status: "completed", outcome };
|
|
260
249
|
}
|
|
261
250
|
row.attempts = attempts;
|
|
@@ -295,16 +284,24 @@ async function bypolicy(t, s, row, kind) {
|
|
|
295
284
|
await t.put("effects", row.request.effectId, row);
|
|
296
285
|
return { status: "pending" };
|
|
297
286
|
}
|
|
298
|
-
/**
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
message: `Tool '${request.toolName ?? ""}' is disabled by its MCP server's tools settings.`,
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
/** The failed outcome of a tool the Runtime cannot run: it would run the developer's code. */
|
|
287
|
+
/**
|
|
288
|
+
* The failed outcome of a tool call the Runtime cannot run: one that names no target (an author's
|
|
289
|
+
* code tool: the Runtime runs agents from their manifests alone), or one whose target the session
|
|
290
|
+
* lacks (a sandbox call without a sandbox).
|
|
291
|
+
*/
|
|
307
292
|
function unrunnableTool(request) {
|
|
293
|
+
if (request.target?.kind === "sandbox")
|
|
294
|
+
return {
|
|
295
|
+
kind: "failed",
|
|
296
|
+
code: "tool.unavailable",
|
|
297
|
+
message: `Tool '${request.toolName ?? ""}' runs in a sandbox, and this session has none.`,
|
|
298
|
+
};
|
|
299
|
+
if (request.target !== undefined)
|
|
300
|
+
return {
|
|
301
|
+
kind: "failed",
|
|
302
|
+
code: "tool.unavailable",
|
|
303
|
+
message: `Tool '${request.toolName ?? ""}' is not one this session can run (${request.target.kind}).`,
|
|
304
|
+
};
|
|
308
305
|
return {
|
|
309
306
|
kind: "failed",
|
|
310
307
|
code: "tool.unavailable",
|
|
@@ -347,12 +344,16 @@ export async function recordOutcome(scope, effectId, reported) {
|
|
|
347
344
|
});
|
|
348
345
|
}
|
|
349
346
|
// What a harness reports never carries the Runtime's own tokens into the record (R4).
|
|
350
|
-
const value =
|
|
347
|
+
const value = redactTokens(result.value);
|
|
351
348
|
return ctx.store.tx(async (t) => {
|
|
352
349
|
const s = await t.assertEpoch(lease.sessionId, lease.epoch);
|
|
353
350
|
const effect = await t.get("effects", effectId);
|
|
354
351
|
if (!effect)
|
|
355
352
|
throw new HarnessApiError("invalid", `Effect ${effectId} was never journaled`);
|
|
353
|
+
// An entry of the record (S0): past the Tenant's `recordEntryBytes`, `limit_exceeded`. The
|
|
354
|
+
// harness shapes what it reports to fit, storing the rest with `artifact.write`; the row
|
|
355
|
+
// stays as it was.
|
|
356
|
+
checkEntry(`The outcome of effect ${effectId} (store the rest with artifact.write)`, value, (await readRuntimeLimits(t)).recordEntryBytes);
|
|
356
357
|
const { request } = effect;
|
|
357
358
|
if (s.status === "cancelled" || s.activeTurnId !== request.turnId || abortKind(signal) === "cancel")
|
|
358
359
|
throw TURN_CANCELLED();
|
|
@@ -360,7 +361,7 @@ export async function recordOutcome(scope, effectId, reported) {
|
|
|
360
361
|
// Settled already: a re-send after a lost hop collected what the first send recorded.
|
|
361
362
|
if (effect.status === "completed")
|
|
362
363
|
return { status: "completed", outcome: effect.outcome };
|
|
363
|
-
// What the call returned is the harness's claim
|
|
364
|
+
// What the call returned is the harness's claim (R4.9).
|
|
364
365
|
const outcome = await settleToolRow(t, s, effect, value, { writer: scope.writer });
|
|
365
366
|
if (request.context?.role === "verify-http")
|
|
366
367
|
await recordVerdict(t, request, value);
|
|
@@ -372,80 +373,24 @@ export async function recordOutcome(scope, effectId, reported) {
|
|
|
372
373
|
await t.put("effects", effectId, effect);
|
|
373
374
|
const model = request.kind === "model";
|
|
374
375
|
const failed = model ? modelFailed(request, value) : undefined;
|
|
375
|
-
// A summary call is never an assistant message
|
|
376
|
-
//
|
|
377
|
-
const summarizing = model &&
|
|
378
|
-
const compacted = summarizing && !failed ? contextCompacted(request, value) : undefined;
|
|
376
|
+
// A summary call is never an assistant message: the compaction's transcript edit names it,
|
|
377
|
+
// and `context.compacted` is written with that edit (Q4).
|
|
378
|
+
const summarizing = model && request.purpose === "summary";
|
|
379
379
|
const transcript = failed || summarizing || !model ? undefined : assistantMessage(request, value);
|
|
380
380
|
if (request.context?.role === "verify-http")
|
|
381
381
|
await recordVerdict(t, request, value);
|
|
382
382
|
const writer = scope.writer;
|
|
383
383
|
// The call's span (R7.1): the journal's window, and the meter's row for it when a gate ran it.
|
|
384
|
-
const facts = failed ||
|
|
384
|
+
const facts = failed || transcript
|
|
385
385
|
? modelOutcomeFacts(effectId, effect, await t.modelUsageOf(effectId))
|
|
386
386
|
: undefined;
|
|
387
387
|
if (failed)
|
|
388
388
|
await t.event(s.id, request.turnId, "model.failed", { ...failed, ...facts }, writer);
|
|
389
|
-
if (compacted)
|
|
390
|
-
await t.event(s.id, request.turnId, "context.compacted", { ...compacted, ...facts }, writer);
|
|
391
389
|
if (transcript)
|
|
392
390
|
await t.event(s.id, request.turnId, "message.assistant", { ...transcript, ...facts }, writer);
|
|
393
391
|
return { status: "completed", outcome: effect.outcome };
|
|
394
392
|
});
|
|
395
393
|
}
|
|
396
|
-
/**
|
|
397
|
-
* The outcome of an agent's remote MCP or HTTP tool call, shaped to fit before anything records
|
|
398
|
-
* it (R2b C11, `tenant/tool-results.ts`): what does not fit becomes the session's artifacts. Any
|
|
399
|
-
* other outcome, and one a cancel will discard, as it is. Only a cancel stops the upload: after a
|
|
400
|
-
* shutdown or a deadline the outcome is still recorded, so the next advance replays it.
|
|
401
|
-
*
|
|
402
|
-
* Its cap is what its step's budget has left (`resultLimit`): a step's results are one transcript
|
|
403
|
-
* entry. Parallel results are counted under the session lock, each reserving its share on its
|
|
404
|
-
* row (`resultBytes`) before it is shaped, so two never spend the same room.
|
|
405
|
-
*/
|
|
406
|
-
async function shaped(scope, effectId, value) {
|
|
407
|
-
const { ctx, lease, signal } = scope;
|
|
408
|
-
if (abortKind(signal) === "cancel" || !mayNeedShaping(value))
|
|
409
|
-
return value;
|
|
410
|
-
const call = await ctx.store.tx(async (t) => {
|
|
411
|
-
const s = await t.lockSession(lease.sessionId);
|
|
412
|
-
const effect = await t.get("effects", effectId);
|
|
413
|
-
if (!s || !effect || effect.status === "completed")
|
|
414
|
-
return undefined;
|
|
415
|
-
const request = effect.request;
|
|
416
|
-
// An agent's tool; a flow's HTTP stage or verifier names no tool, and its output is data.
|
|
417
|
-
if (request.kind !== "tool" || request.toolName === undefined)
|
|
418
|
-
return undefined;
|
|
419
|
-
const mcp = mcpToolOf(s.mcpSnapshot, request) !== undefined;
|
|
420
|
-
if (!mcp && !isHttpToolCall(s.manifest, request))
|
|
421
|
-
return undefined;
|
|
422
|
-
const step = stepOf(request);
|
|
423
|
-
let used = 0;
|
|
424
|
-
if (step !== undefined)
|
|
425
|
-
for (const other of await t.effectsForTurn(s.id, request.turnId, [
|
|
426
|
-
"invoking",
|
|
427
|
-
"completed",
|
|
428
|
-
])) {
|
|
429
|
-
if (other.request.effectId === effectId || stepOf(other.request) !== step)
|
|
430
|
-
continue;
|
|
431
|
-
used +=
|
|
432
|
-
other.resultBytes ??
|
|
433
|
-
(other.status === "completed" ? resultBytes(other.outcome?.value) : 0);
|
|
434
|
-
}
|
|
435
|
-
const limit = resultLimit(used);
|
|
436
|
-
effect.resultBytes = Math.min(resultBytes(value), limit);
|
|
437
|
-
await t.put("effects", effectId, effect);
|
|
438
|
-
return { request, session: { id: s.id, ownerUserId: s.ownerUserId }, mcp, limit };
|
|
439
|
-
});
|
|
440
|
-
return call ? shapeToolOutcome(ctx, call, value, abortOn(signal, ["cancel"])) : value;
|
|
441
|
-
}
|
|
442
|
-
/** The model step a tool call answers, and whose agent: its results share one transcript entry. */
|
|
443
|
-
function stepOf(request) {
|
|
444
|
-
if (request.kind !== "tool")
|
|
445
|
-
return undefined;
|
|
446
|
-
const stepId = request.context?.stepId;
|
|
447
|
-
return typeof stepId === "string" ? JSON.stringify([request.agent?.id ?? null, stepId]) : undefined;
|
|
448
|
-
}
|
|
449
394
|
/** What a journal row keeps of a request: a model call without its prompt. */
|
|
450
395
|
function storedRequest(request) {
|
|
451
396
|
if (request.kind !== "model" || request.input === undefined)
|
|
@@ -18,7 +18,7 @@ export type Renewal = {
|
|
|
18
18
|
} | {
|
|
19
19
|
ok: false;
|
|
20
20
|
};
|
|
21
|
-
/** How often a lease is renewed: a third of its length. */
|
|
21
|
+
/** How often a lease is renewed: a third of its length, and at least 1 ms, a timer's least delay. */
|
|
22
22
|
export declare function renewEveryMs(ctx: TenantContext): number;
|
|
23
23
|
/** The run token the advance of `lease` holds, as a run grant carries it. */
|
|
24
24
|
export declare function tokenOf(ctx: TenantContext, lease: Lease): {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { dropRunGrant, renewRunGrant } from "../tenant/run-grants.js";
|
|
2
2
|
import { AdvanceAbort } from "../tenant/worker.js";
|
|
3
|
-
/** How often a lease is renewed: a third of its length. */
|
|
3
|
+
/** How often a lease is renewed: a third of its length, and at least 1 ms, a timer's least delay. */
|
|
4
4
|
export function renewEveryMs(ctx) {
|
|
5
|
-
return Math.max(
|
|
5
|
+
return Math.max(1, Math.floor(ctx.ownerLeaseMs / 3));
|
|
6
6
|
}
|
|
7
7
|
/** The run token the advance of `lease` holds, as a run grant carries it. */
|
|
8
8
|
export function tokenOf(ctx, lease) {
|
|
@@ -59,14 +59,6 @@ export type RunEnd = {
|
|
|
59
59
|
/** No harness took the run within `offerWaitMs`. */
|
|
60
60
|
| {
|
|
61
61
|
readonly kind: "unavailable";
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* The harness that would take the run cannot: a tool it runs itself (`features.tools`) has the
|
|
65
|
-
* name of a tool of the turn's agents. The turn fails with `message`.
|
|
66
|
-
*/
|
|
67
|
-
| {
|
|
68
|
-
readonly kind: "refused";
|
|
69
|
-
readonly message: string;
|
|
70
62
|
};
|
|
71
63
|
export interface HarnessApiServer {
|
|
72
64
|
/** Serves a harness's channel until it closes. Returns a function that detaches it. */
|
|
@@ -112,16 +104,9 @@ export declare class NoWorkspaceHarness extends Error {
|
|
|
112
104
|
constructor(pod?: string | undefined);
|
|
113
105
|
}
|
|
114
106
|
export interface HarnessApiServerOptions {
|
|
107
|
+
/** How long an offered run waits for a harness. Default `harnessApi.offerWaitMs` (Host tuning). */
|
|
115
108
|
offerWaitMs?: number;
|
|
116
109
|
/** The sandbox backend preference a harness that serves workspaces selects with. */
|
|
117
110
|
sandboxPreference?: string;
|
|
118
111
|
}
|
|
119
112
|
export declare function createHarnessApiServer(ctx: TenantContext, options?: HarnessApiServerOptions): HarnessApiServer;
|
|
120
|
-
/**
|
|
121
|
-
* The tools a harness runs itself (`features.tools`) whose names the turn already uses: a tool of
|
|
122
|
-
* the turn's agents (their own and the Runtime's `runtime` tools), a session tool, `tool_search` or
|
|
123
|
-
* `tool_call` (session tools a later step may get). Tools are known by name alone, so a native
|
|
124
|
-
* tool must not take one (Harness API 3); `hello` already refuses a name with `__`, which names an
|
|
125
|
-
* MCP server's tools. A flow turn runs no native tools.
|
|
126
|
-
*/
|
|
127
|
-
export declare function nativeToolClashes(tools: ReadonlySet<string> | undefined, start: TurnStart): string[];
|