@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
|
@@ -8,10 +8,14 @@
|
|
|
8
8
|
* - The gate also writes a `tool_crossings` row before it calls the server, and the answer
|
|
9
9
|
* after. A re-send that finds the answer gets it. One that finds a row without an answer,
|
|
10
10
|
* for a call this gateway is not running, was lost with an earlier gateway (a restart mid
|
|
11
|
-
* call): it
|
|
11
|
+
* call): it is started again under the same key (R5.3), so the tool sees the key twice and
|
|
12
|
+
* a tool that honors it acts once. Core counts the sends and stops at its cap (R5.4).
|
|
13
|
+
* - A re-send that another gateway process started or settled between this one's read and its
|
|
14
|
+
* write answers `{uncertain: true}`: not answered here, so the caller sends it again later.
|
|
12
15
|
*
|
|
13
|
-
* A cancel aborts the call and
|
|
14
|
-
*
|
|
16
|
+
* A cancel aborts the call and settles its row as cancelled: it never runs again under its key.
|
|
17
|
+
* A shutdown leaves the row open, so the next gateway starts it again. Settled rows are deleted
|
|
18
|
+
* a day later (`prune`); a re-send after that runs the call again, which at least once allows.
|
|
15
19
|
*/
|
|
16
20
|
import type { Logger } from "../tenant/types.js";
|
|
17
21
|
import { type InflightCallsOptions, type InflightOwner } from "./inflight.js";
|
|
@@ -29,8 +33,9 @@ export interface ToolCalls {
|
|
|
29
33
|
*/
|
|
30
34
|
run(tenantId: string | undefined, key: string, hash: string, call: (signal: AbortSignal) => Promise<ToolCallAnswer>, owner?: InflightOwner): Promise<ToolCallAnswer>;
|
|
31
35
|
/**
|
|
32
|
-
* Aborts the call under `key
|
|
33
|
-
* when the running call is another session's (nothing
|
|
36
|
+
* Aborts the call under `key` and settles its crossing as cancelled: it is never run again
|
|
37
|
+
* under that key. With `sessionId`, false when the running call is another session's (nothing
|
|
38
|
+
* is aborted).
|
|
34
39
|
*/
|
|
35
40
|
cancel(key: string, sessionId?: string): boolean;
|
|
36
41
|
/** Aborts every running call (gateway shutdown). */
|
package/dist/gates/tool-calls.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { createInflightCalls, InflightConflict, } from "./inflight.js";
|
|
2
2
|
/** How long a settled crossing is kept. */
|
|
3
3
|
export const TOOL_CROSSING_TTL_MS = 24 * 60 * 60_000;
|
|
4
|
-
const
|
|
4
|
+
const CANCELLED = {
|
|
5
|
+
ok: false,
|
|
6
|
+
error: { message: "The call was cancelled while it ran; it may have reached its server" },
|
|
7
|
+
};
|
|
8
|
+
const ELSEWHERE = {
|
|
5
9
|
ok: false,
|
|
6
10
|
error: {
|
|
7
11
|
uncertain: true,
|
|
8
|
-
message: "
|
|
12
|
+
message: "Another gateway process is running this tool call; send it again",
|
|
9
13
|
},
|
|
10
14
|
};
|
|
11
15
|
export function createToolCalls(options) {
|
|
@@ -16,7 +20,7 @@ export function createToolCalls(options) {
|
|
|
16
20
|
return {
|
|
17
21
|
async run(tenantId, key, hash, call, owner) {
|
|
18
22
|
if (inflight.has(key))
|
|
19
|
-
return inflight.run(key, hash, () => Promise.resolve(
|
|
23
|
+
return inflight.run(key, hash, () => Promise.resolve(ELSEWHERE), owner);
|
|
20
24
|
const vault = await vaults.open(tenantId);
|
|
21
25
|
const store = vault.store;
|
|
22
26
|
const row = await store.tx((t) => t.toolCrossing(key));
|
|
@@ -25,16 +29,19 @@ export function createToolCalls(options) {
|
|
|
25
29
|
throw new InflightConflict(`A different request already ran under ${key}`);
|
|
26
30
|
if (row.answer !== null && row.answer !== undefined)
|
|
27
31
|
return row.answer;
|
|
28
|
-
// Started here a moment ago
|
|
32
|
+
// Started here a moment ago: join it.
|
|
29
33
|
if (inflight.has(key))
|
|
30
|
-
return inflight.run(key, hash, () => Promise.resolve(
|
|
31
|
-
|
|
34
|
+
return inflight.run(key, hash, () => Promise.resolve(ELSEWHERE), owner);
|
|
35
|
+
// Otherwise it was lost with an earlier gateway: it starts again below (R5.3).
|
|
32
36
|
}
|
|
33
37
|
return inflight.run(key, hash, async (signal) => {
|
|
34
|
-
const
|
|
35
|
-
|
|
38
|
+
const startedAt = iso();
|
|
39
|
+
const started = await store.tx((t) => row
|
|
40
|
+
? t.restartToolCrossing({ key, hash, startedAt })
|
|
41
|
+
: t.startToolCrossing({ key, hash, startedAt }));
|
|
42
|
+
// Another gateway process started or settled it between the read and now.
|
|
36
43
|
if (!started)
|
|
37
|
-
return
|
|
44
|
+
return ELSEWHERE;
|
|
38
45
|
const answer = await call(signal);
|
|
39
46
|
// A cancel or a shutdown: the call may have reached the server; the row stays open.
|
|
40
47
|
if (signal.aborted)
|
|
@@ -48,7 +55,18 @@ export function createToolCalls(options) {
|
|
|
48
55
|
return answer;
|
|
49
56
|
}, owner);
|
|
50
57
|
},
|
|
51
|
-
cancel
|
|
58
|
+
cancel(key, sessionId) {
|
|
59
|
+
if (!inflight.cancel(key, sessionId))
|
|
60
|
+
return false;
|
|
61
|
+
void vaults
|
|
62
|
+
.open(undefined)
|
|
63
|
+
.then((vault) => vault.store.tx((t) => t.settleToolCrossing(key, CANCELLED, iso())))
|
|
64
|
+
.catch((error) => logger.warn("tool_crossing_unsettled", {
|
|
65
|
+
effect: key,
|
|
66
|
+
message: error instanceof Error ? error.message : String(error),
|
|
67
|
+
}));
|
|
68
|
+
return true;
|
|
69
|
+
},
|
|
52
70
|
close: () => inflight.close(),
|
|
53
71
|
async prune() {
|
|
54
72
|
try {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { ToolGate } from "./tool-gate.js";
|
|
2
2
|
import type { RunTokens } from "../tenant/run-grants.js";
|
|
3
|
+
/**
|
|
4
|
+
* A keyed call whose answer the hop lost (R5.3): the gate never got it, the connection broke,
|
|
5
|
+
* the gate answered `5xx`, or another gateway process holds the call. Sending it again with the
|
|
6
|
+
* same key is safe: the gate joins the call, answers it from its crossing, or runs it again.
|
|
7
|
+
*/
|
|
8
|
+
export declare class GateCallLost extends Error {
|
|
9
|
+
readonly name = "GateCallLost";
|
|
10
|
+
}
|
|
3
11
|
export interface HttpToolGateOptions {
|
|
4
12
|
/** The gates service, e.g. `http://gateway:4100` (`NYLORUN_GATES_URL`). */
|
|
5
13
|
readonly url: string;
|
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
* Failures keep the meaning they had in the loop's own process:
|
|
9
9
|
* - An MCP request that fails throws, so the pool reports a diagnostic. A tool call's coded
|
|
10
10
|
* failure (R2b C7) throws the `McpCallFailed` the loop's own call would have, which becomes a
|
|
11
|
-
* failed outcome the model sees.
|
|
12
|
-
*
|
|
13
|
-
* -
|
|
14
|
-
*
|
|
11
|
+
* failed outcome the model sees.
|
|
12
|
+
* - An HTTP tool call throws only for the hop: its own failures are outcomes.
|
|
13
|
+
* - A hop that lost the answer (the gate unreachable, the connection lost, a `5xx`, or a call
|
|
14
|
+
* another gateway process holds) throws `GateCallLost`: sending the call again with the same
|
|
15
|
+
* key joins it, collects its answer, or runs it again (R5.3). A gate's refusal (`4xx`) throws
|
|
16
|
+
* a plain error.
|
|
15
17
|
*
|
|
16
18
|
* Credentials (F5): a session's MCP requests and keyed cancels carry its run token, read per
|
|
17
19
|
* request from the advance's grant, and leave the session out of the body: the gate takes it
|
|
@@ -26,6 +28,14 @@ import { McpCallFailed, } from "../mcp/connect.js";
|
|
|
26
28
|
import { TENANT_HEADER } from "./contract.js";
|
|
27
29
|
import { GATE_CLIENT_TIMEOUT_MS } from "./http-client.js";
|
|
28
30
|
import { HTTP_CALLS_PATH, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, TOOL_CALLS_PATH, } from "./tool-contract.js";
|
|
31
|
+
/**
|
|
32
|
+
* A keyed call whose answer the hop lost (R5.3): the gate never got it, the connection broke,
|
|
33
|
+
* the gate answered `5xx`, or another gateway process holds the call. Sending it again with the
|
|
34
|
+
* same key is safe: the gate joins the call, answers it from its crossing, or runs it again.
|
|
35
|
+
*/
|
|
36
|
+
export class GateCallLost extends Error {
|
|
37
|
+
name = "GateCallLost";
|
|
38
|
+
}
|
|
29
39
|
/** How long a close or a cancel may take; neither changes an outcome. */
|
|
30
40
|
const SHORT_TIMEOUT_MS = 2_000;
|
|
31
41
|
export function httpToolGate(options) {
|
|
@@ -111,8 +121,7 @@ export function httpToolGate(options) {
|
|
|
111
121
|
}
|
|
112
122
|
/**
|
|
113
123
|
* The answer of an MCP or HTTP tool request, or a throw: a coded MCP failure (`McpCallFailed`),
|
|
114
|
-
*
|
|
115
|
-
* `uncertain`.
|
|
124
|
+
* a lost hop (`GateCallLost`, sent again), or a gate's refusal.
|
|
116
125
|
*/
|
|
117
126
|
async function answer(path, scope, request) {
|
|
118
127
|
const result = await exchange(path, scope.body, {
|
|
@@ -123,8 +132,10 @@ export function httpToolGate(options) {
|
|
|
123
132
|
if (result.kind === "aborted")
|
|
124
133
|
throw result.reason ?? new Error("aborted");
|
|
125
134
|
if (result.kind !== "answer")
|
|
126
|
-
throw new
|
|
135
|
+
throw new GateCallLost(result.message);
|
|
127
136
|
const parsed = parse(result.text);
|
|
137
|
+
if (result.status >= 500)
|
|
138
|
+
throw new GateCallLost(gateRefusal(result.status, parsed));
|
|
128
139
|
if (result.status !== 200 || !parsed || !("ok" in parsed))
|
|
129
140
|
throw new Error(gateRefusal(result.status, parsed));
|
|
130
141
|
if (parsed.ok)
|
|
@@ -176,7 +187,9 @@ export function httpToolGate(options) {
|
|
|
176
187
|
async callHttp(call, signal) {
|
|
177
188
|
const token = options.runTokens?.token(call.tool.sessionId);
|
|
178
189
|
const { sessionId: _, ...unnamed } = call.tool;
|
|
179
|
-
|
|
190
|
+
// The gate reads the call's span context from its journal row (R7.4), not from the caller.
|
|
191
|
+
const { traceparent: _traceparent, ...sent } = call;
|
|
192
|
+
const body = { ...sent, tool: token ? unnamed : { ...call.tool } };
|
|
180
193
|
return answered(HTTP_CALLS_PATH, { body, ...(token ? { bearer: token } : {}) }, { signal, idempotencyKey: call.effectId });
|
|
181
194
|
},
|
|
182
195
|
async cancel(request) {
|
|
@@ -190,10 +203,13 @@ export function httpToolGate(options) {
|
|
|
190
203
|
}
|
|
191
204
|
/** An MCP failure the gate reported, as the loop's own MCP code would have thrown it. */
|
|
192
205
|
function mcpError(error) {
|
|
193
|
-
//
|
|
194
|
-
if (error.
|
|
206
|
+
// Held by another gateway process: send it again (R5.3).
|
|
207
|
+
if (error.uncertain)
|
|
208
|
+
return new GateCallLost(error.message);
|
|
209
|
+
// Coded (R2b C7): the model sees it.
|
|
210
|
+
if (error.failure)
|
|
195
211
|
return McpCallFailed.from(error.failure);
|
|
196
|
-
const thrown = new Error(error.
|
|
212
|
+
const thrown = new Error(error.message);
|
|
197
213
|
if (error.code !== undefined)
|
|
198
214
|
thrown.code = error.code;
|
|
199
215
|
if (error.credentialIds !== undefined)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The Tool Gate's wire format (blueprint §12, F4.1): the routes the loop calls on the gates
|
|
3
|
-
* service for remote MCP servers and HTTP tools.
|
|
4
|
-
*
|
|
3
|
+
* service for remote MCP servers and HTTP tools. Like the model call route (`contract.ts`): same
|
|
4
|
+
* optional Tenant header, bodies published in `@nylorun/core/harness-api` (R4.5).
|
|
5
5
|
*
|
|
6
6
|
* Credentials (F5). A session's MCP requests carry its run token, and the gate takes the
|
|
7
7
|
* session from it: `server.sessionId` is then absent (or the token's). Core's credential
|
|
@@ -25,78 +25,21 @@
|
|
|
25
25
|
* answer, not a gate error. A tool call's failure is coded (`error.failure`, R2b C7), and neither
|
|
26
26
|
* a result nor a failure carries a credential value the gate sent (C8). An answer past 8 MiB is
|
|
27
27
|
* `mcp.too-large` (C11), as an HTTP tool's is `http.too-large`; core shapes what fits into a
|
|
28
|
-
* result the model can take (`tenant/tool-results.ts`). A keyed call whose
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* result the model can take (`tenant/tool-results.ts`). A keyed call whose earlier attempt was
|
|
29
|
+
* lost with the gateway runs again under the same key (R5.3); one another gateway process holds
|
|
30
|
+
* answers `{ok: false, error: {uncertain: true}}`, and the caller sends it again.
|
|
31
31
|
*
|
|
32
32
|
* HTTP tools (R2 M3). `POST /nylorun/v1/http-calls` `{tool, effectId, turnId, input}`: one call
|
|
33
|
-
* of an HTTP tool. The loop names the tool (`{sessionId?, agentId?,
|
|
33
|
+
* of an HTTP tool. The loop names the tool (`{sessionId?, agentId?, toolName}`), or a
|
|
34
34
|
* flow's HTTP stage or HTTP verifier by its stage key (`{sessionId?, stage}`); the gate finds its
|
|
35
35
|
* URL, method and credential in the session's pinned manifest
|
|
36
36
|
* (`gates/http-tool.ts`). A run token's turn is the call's; `turnId` counts only under core's
|
|
37
37
|
* credential. Keyed like a tool call, and cancelled by the same route. It answers
|
|
38
38
|
* `200 {ok: true, result}` with the tool outcome (a failed request is a failed outcome the
|
|
39
|
-
* model sees), or `{ok: false, error: {uncertain: true}}` for a call
|
|
39
|
+
* model sees), or `{ok: false, error: {uncertain: true}}` for a call another gateway process holds.
|
|
40
40
|
*/
|
|
41
|
-
import { z } from "zod";
|
|
42
41
|
import type { McpCallFailure } from "../mcp/connect.js";
|
|
43
|
-
export
|
|
44
|
-
export declare const MCP_LIST_PATH = "/nylorun/v1/mcp/list";
|
|
45
|
-
export declare const MCP_CLOSE_PATH = "/nylorun/v1/mcp/close";
|
|
46
|
-
export declare const TOOL_CALLS_PATH = "/nylorun/v1/tool-calls";
|
|
47
|
-
export declare const HTTP_CALLS_PATH = "/nylorun/v1/http-calls";
|
|
48
|
-
/** Largest tool call body the gate reads. */
|
|
49
|
-
export declare const MAX_TOOL_BODY_BYTES: number;
|
|
50
|
-
export declare const McpServerRefSchema: z.ZodObject<{
|
|
51
|
-
sessionId: z.ZodOptional<z.ZodString>;
|
|
52
|
-
agentId: z.ZodOptional<z.ZodString>;
|
|
53
|
-
capabilityId: z.ZodString;
|
|
54
|
-
serverName: z.ZodString;
|
|
55
|
-
}, z.core.$strip>;
|
|
56
|
-
export declare const McpServerBodySchema: z.ZodObject<{
|
|
57
|
-
server: z.ZodObject<{
|
|
58
|
-
sessionId: z.ZodOptional<z.ZodString>;
|
|
59
|
-
agentId: z.ZodOptional<z.ZodString>;
|
|
60
|
-
capabilityId: z.ZodString;
|
|
61
|
-
serverName: z.ZodString;
|
|
62
|
-
}, z.core.$strip>;
|
|
63
|
-
}, z.core.$strip>;
|
|
64
|
-
export declare const McpListBodySchema: z.ZodObject<{
|
|
65
|
-
server: z.ZodObject<{
|
|
66
|
-
sessionId: z.ZodOptional<z.ZodString>;
|
|
67
|
-
agentId: z.ZodOptional<z.ZodString>;
|
|
68
|
-
capabilityId: z.ZodString;
|
|
69
|
-
serverName: z.ZodString;
|
|
70
|
-
}, z.core.$strip>;
|
|
71
|
-
cursor: z.ZodOptional<z.ZodString>;
|
|
72
|
-
}, z.core.$strip>;
|
|
73
|
-
export declare const ToolCallBodySchema: z.ZodObject<{
|
|
74
|
-
server: z.ZodObject<{
|
|
75
|
-
sessionId: z.ZodOptional<z.ZodString>;
|
|
76
|
-
agentId: z.ZodOptional<z.ZodString>;
|
|
77
|
-
capabilityId: z.ZodString;
|
|
78
|
-
serverName: z.ZodString;
|
|
79
|
-
}, z.core.$strip>;
|
|
80
|
-
effectId: z.ZodString;
|
|
81
|
-
name: z.ZodString;
|
|
82
|
-
arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
83
|
-
}, z.core.$strip>;
|
|
84
|
-
export type ToolCallBody = z.infer<typeof ToolCallBodySchema>;
|
|
85
|
-
export declare const HttpCallBodySchema: z.ZodObject<{
|
|
86
|
-
tool: z.ZodUnion<readonly [z.ZodObject<{
|
|
87
|
-
sessionId: z.ZodOptional<z.ZodString>;
|
|
88
|
-
agentId: z.ZodOptional<z.ZodString>;
|
|
89
|
-
capabilityId: z.ZodString;
|
|
90
|
-
toolName: z.ZodString;
|
|
91
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
92
|
-
sessionId: z.ZodOptional<z.ZodString>;
|
|
93
|
-
stage: z.ZodString;
|
|
94
|
-
}, z.core.$strip>]>;
|
|
95
|
-
effectId: z.ZodString;
|
|
96
|
-
turnId: z.ZodString;
|
|
97
|
-
input: z.ZodUnknown;
|
|
98
|
-
}, z.core.$strip>;
|
|
99
|
-
export type HttpCallBody = z.infer<typeof HttpCallBodySchema>;
|
|
42
|
+
export { HTTP_CALLS_PATH, HttpCallBodySchema, MAX_TOOL_BODY_BYTES, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, McpServerRefSchema, TOOL_CALLS_PATH, ToolCallBodySchema, type HttpCallBody, type ToolCallBody, } from "@nylorun/core/harness-api";
|
|
100
43
|
/** Why an MCP request failed, as the loop's diagnostics read it (`mcp/connect.ts`). */
|
|
101
44
|
export interface McpGateError {
|
|
102
45
|
readonly message: string;
|
|
@@ -104,13 +47,12 @@ export interface McpGateError {
|
|
|
104
47
|
readonly code?: number;
|
|
105
48
|
/** The vault credentials a refused authorization names. */
|
|
106
49
|
readonly credentialIds?: readonly string[];
|
|
107
|
-
/**
|
|
50
|
+
/** Not answered here: another gateway process holds the keyed call. Send it again (R5.3). */
|
|
108
51
|
readonly uncertain?: boolean;
|
|
109
52
|
/**
|
|
110
53
|
* How the request failed, coded (R2b C1, C7): the loop's `McpCallFailed`, which a tool call
|
|
111
|
-
* turns into a failed outcome the model sees (`mcp.lost`
|
|
112
|
-
*
|
|
113
|
-
* credential was sent. Its message has no credential value in it (C8).
|
|
54
|
+
* turns into a failed outcome the model sees (`mcp.lost` included). `credential_rejected` for a
|
|
55
|
+
* `401`, with the server. Its message has no credential value in it (C8).
|
|
114
56
|
*/
|
|
115
57
|
readonly failure?: McpCallFailure;
|
|
116
58
|
}
|
|
@@ -1,85 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* The Tool Gate's wire format (blueprint §12, F4.1): the routes the loop calls on the gates
|
|
3
|
-
* service for remote MCP servers and HTTP tools. Internal, like the model call route
|
|
4
|
-
* (`contract.ts`): same optional Tenant header, not in the published OpenAPI documents.
|
|
5
|
-
*
|
|
6
|
-
* Credentials (F5). A session's MCP requests carry its run token, and the gate takes the
|
|
7
|
-
* session from it: `server.sessionId` is then absent (or the token's). Core's credential
|
|
8
|
-
* (`NYLORUN_GATES_TOKEN`) is accepted too, for requests made outside a run, and then
|
|
9
|
-
* `server.sessionId` names the session.
|
|
10
|
-
*
|
|
11
|
-
* Remote MCP. The gate holds the connection and the vault credential; the loop names the
|
|
12
|
-
* server, never a URL or a credential, and the gate finds it in the session's pinned manifest.
|
|
13
|
-
* - `POST /nylorun/v1/mcp/connect` `{server}`: opens the server's connection (vault
|
|
14
|
-
* authorization included), or keeps the open one. Its result is `{instructions}` when the
|
|
15
|
-
* server gave instructions at `initialize` (R2b C10, for the note on its deferred tools), else
|
|
16
|
-
* `null`.
|
|
17
|
-
* - `POST /nylorun/v1/mcp/list` `{server, cursor?}`: one page of `tools/list`.
|
|
18
|
-
* - `POST /nylorun/v1/tool-calls` `{server, effectId, name, arguments}`: one
|
|
19
|
-
* `tools/call`. With an `Idempotency-Key` (the effect id) the call outlives its client and runs
|
|
20
|
-
* once (G3); a re-send joins it or gets its outcome.
|
|
21
|
-
* - `POST /nylorun/v1/tool-calls/{key}/cancel`: aborts a keyed call; `204` either way, `403
|
|
22
|
-
* gate_forbidden` for another session's call under a run token.
|
|
23
|
-
* - `POST /nylorun/v1/mcp/close` `{server}`: closes the server's connection; `204`.
|
|
24
|
-
* Each answers `200 {ok: true, result}` or `200 {ok: false, error}`: an MCP failure is an
|
|
25
|
-
* answer, not a gate error. A tool call's failure is coded (`error.failure`, R2b C7), and neither
|
|
26
|
-
* a result nor a failure carries a credential value the gate sent (C8). An answer past 8 MiB is
|
|
27
|
-
* `mcp.too-large` (C11), as an HTTP tool's is `http.too-large`; core shapes what fits into a
|
|
28
|
-
* result the model can take (`tenant/tool-results.ts`). A keyed call whose
|
|
29
|
-
* earlier attempt was lost with the gateway answers `{ok: false, error: {uncertain: true}}` and
|
|
30
|
-
* is never run again.
|
|
31
|
-
*
|
|
32
|
-
* HTTP tools (R2 M3). `POST /nylorun/v1/http-calls` `{tool, effectId, turnId, input}`: one call
|
|
33
|
-
* of an HTTP tool. The loop names the tool (`{sessionId?, agentId?, capabilityId, toolName}`), or a
|
|
34
|
-
* flow's HTTP stage or HTTP verifier by its stage key (`{sessionId?, stage}`); the gate finds its
|
|
35
|
-
* URL, method and credential in the session's pinned manifest
|
|
36
|
-
* (`gates/http-tool.ts`). A run token's turn is the call's; `turnId` counts only under core's
|
|
37
|
-
* credential. Keyed like a tool call, and cancelled by the same route. It answers
|
|
38
|
-
* `200 {ok: true, result}` with the tool outcome (a failed request is a failed outcome the
|
|
39
|
-
* model sees), or `{ok: false, error: {uncertain: true}}` for a call lost with the gateway.
|
|
40
|
-
*/
|
|
41
|
-
import { z } from "zod";
|
|
42
|
-
export const MCP_CONNECT_PATH = "/nylorun/v1/mcp/connect";
|
|
43
|
-
export const MCP_LIST_PATH = "/nylorun/v1/mcp/list";
|
|
44
|
-
export const MCP_CLOSE_PATH = "/nylorun/v1/mcp/close";
|
|
45
|
-
export const TOOL_CALLS_PATH = "/nylorun/v1/tool-calls";
|
|
46
|
-
export const HTTP_CALLS_PATH = "/nylorun/v1/http-calls";
|
|
47
|
-
/** Largest tool call body the gate reads. */
|
|
48
|
-
export const MAX_TOOL_BODY_BYTES = 8 * 1024 * 1024;
|
|
49
|
-
export const McpServerRefSchema = z.object({
|
|
50
|
-
/** Required with core's credential; a run token names the session itself. */
|
|
51
|
-
sessionId: z.string().min(1).optional(),
|
|
52
|
-
agentId: z.string().min(1).optional(),
|
|
53
|
-
capabilityId: z.string().min(1),
|
|
54
|
-
serverName: z.string().min(1),
|
|
55
|
-
});
|
|
56
|
-
export const McpServerBodySchema = z.object({ server: McpServerRefSchema });
|
|
57
|
-
export const McpListBodySchema = z.object({
|
|
58
|
-
server: McpServerRefSchema,
|
|
59
|
-
cursor: z.string().optional(),
|
|
60
|
-
});
|
|
61
|
-
export const ToolCallBodySchema = z.object({
|
|
62
|
-
server: McpServerRefSchema,
|
|
63
|
-
effectId: z.string().min(1),
|
|
64
|
-
name: z.string().min(1),
|
|
65
|
-
arguments: z.record(z.string(), z.unknown()),
|
|
66
|
-
});
|
|
67
|
-
export const HttpCallBodySchema = z.object({
|
|
68
|
-
tool: z.union([
|
|
69
|
-
z.object({
|
|
70
|
-
/** Required with core's credential; a run token names the session itself. */
|
|
71
|
-
sessionId: z.string().min(1).optional(),
|
|
72
|
-
agentId: z.string().min(1).optional(),
|
|
73
|
-
capabilityId: z.string().min(1),
|
|
74
|
-
toolName: z.string().min(1),
|
|
75
|
-
}),
|
|
76
|
-
z.object({
|
|
77
|
-
sessionId: z.string().min(1).optional(),
|
|
78
|
-
/** A flow's HTTP stage or HTTP verifier. */
|
|
79
|
-
stage: z.string().min(1),
|
|
80
|
-
}),
|
|
81
|
-
]),
|
|
82
|
-
effectId: z.string().min(1),
|
|
83
|
-
turnId: z.string().min(1),
|
|
84
|
-
input: z.unknown(),
|
|
85
|
-
});
|
|
1
|
+
export { HTTP_CALLS_PATH, HttpCallBodySchema, MAX_TOOL_BODY_BYTES, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, McpListBodySchema, McpServerBodySchema, McpServerRefSchema, TOOL_CALLS_PATH, ToolCallBodySchema, } from "@nylorun/core/harness-api";
|
|
@@ -28,7 +28,7 @@ export interface ToolGate {
|
|
|
28
28
|
/**
|
|
29
29
|
* True when a keyed MCP or HTTP tool call outlives the caller's process (the gates service,
|
|
30
30
|
* G3): after a takeover or a shutdown, re-sending it joins the call or returns its outcome,
|
|
31
|
-
* and a call lost with the gateway
|
|
31
|
+
* and a call lost with the gateway runs again under the same key (R5.3).
|
|
32
32
|
*/
|
|
33
33
|
readonly recovers?: boolean;
|
|
34
34
|
/** Stops a keyed tool call that outlives its caller (a user cancel). Never rejects. */
|
package/dist/harness/calls.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export interface ToolRouting {
|
|
|
26
26
|
readonly mcpSnapshot?: McpSnapshot;
|
|
27
27
|
/** The session that owns the tree's sandbox, and the sandbox resource it is attached to. */
|
|
28
28
|
readonly sandboxOwnerId: string;
|
|
29
|
-
readonly
|
|
29
|
+
readonly environmentId?: string;
|
|
30
30
|
/** Variables every sandbox command gets (R2c): secret names set to the sentinel, plain values. */
|
|
31
31
|
readonly environment?: Readonly<Record<string, string>>;
|
|
32
32
|
readonly activeTurnId: string | null;
|
|
@@ -36,9 +36,12 @@ export interface ToolRouting {
|
|
|
36
36
|
/**
|
|
37
37
|
* Call the model for one effect. A provider failure comes back as a failure outcome
|
|
38
38
|
* (Model Calls §6), whichever provider serves the call; only an abort throws, and the
|
|
39
|
-
* advance decides what the abort means.
|
|
39
|
+
* advance decides what the abort means. `atGate` sends the call to the Model Gate even when the
|
|
40
|
+
* Tenant's model is not from the vault: the Tenant's fixture model is answered there (R4.3).
|
|
40
41
|
*/
|
|
41
|
-
export declare function invokeModel(route: ModelRoute, request: HostEffect, signal: AbortSignal,
|
|
42
|
+
export declare function invokeModel(route: ModelRoute, request: HostEffect, signal: AbortSignal, options?: {
|
|
43
|
+
readonly atGate?: boolean;
|
|
44
|
+
}): Promise<unknown>;
|
|
42
45
|
/**
|
|
43
46
|
* A signal that follows `signal` only for the abort kinds in `kinds`. An MCP call stops on a
|
|
44
47
|
* cancel; at the Tool Gate it also stops waiting on a shutdown, since the gate keeps the call
|
|
@@ -46,17 +49,21 @@ export declare function invokeModel(route: ModelRoute, request: HostEffect, sign
|
|
|
46
49
|
* so the next advance replays it.
|
|
47
50
|
*/
|
|
48
51
|
export declare function abortOn(signal: AbortSignal, kinds: readonly AbortReason[]): AbortSignal;
|
|
49
|
-
/** True when `request` calls `save_artifact
|
|
52
|
+
/** True when `request` calls `save_artifact`, which the Runtime pinned on `manifest`. */
|
|
50
53
|
export declare function isSaveArtifactCall(manifest: AgentManifest | undefined, request: HostEffect): boolean;
|
|
51
|
-
/** True when `request` calls `read_artifact` (R2b C11)
|
|
54
|
+
/** True when `request` calls `read_artifact` (R2b C11), which the Runtime pinned on `manifest`. */
|
|
52
55
|
export declare function isReadArtifactCall(manifest: AgentManifest | undefined, request: HostEffect): boolean;
|
|
53
56
|
/** True when `request` calls a tool of a declared MCP server (every one is remote). */
|
|
54
57
|
export declare function isRemoteMcpCall(routing: Pick<ToolRouting, "rootManifest" | "mcpSnapshot">, request: HostEffect): boolean;
|
|
55
|
-
export declare function callMcpTool(mcp: McpPool, routing: ToolRouting, request: HostEffect, signal: AbortSignal
|
|
58
|
+
export declare function callMcpTool(mcp: McpPool, routing: ToolRouting, request: HostEffect, signal: AbortSignal,
|
|
59
|
+
/** The call's span context (R7.4), sent as `traceparent` where this process holds the connection. */
|
|
60
|
+
traceparent?: string): Promise<unknown>;
|
|
56
61
|
/**
|
|
57
62
|
* Calls an HTTP tool through the Tool Gate (R2 M3), keyed by the effect id: an agent's (the
|
|
58
63
|
* effect's agent used as a tool, or the root), or a flow's HTTP stage or HTTP verifier. Its
|
|
59
64
|
* outcome is the effect's value; a throw leaves the effect `uncertain`.
|
|
60
65
|
*/
|
|
61
|
-
export declare function callHttpTool(gate: Pick<ToolGate, "callHttp">, request: HostEffect, signal: AbortSignal
|
|
66
|
+
export declare function callHttpTool(gate: Pick<ToolGate, "callHttp">, request: HostEffect, signal: AbortSignal,
|
|
67
|
+
/** The call's span context (R7.4); the gates service reads its own from the journal. */
|
|
68
|
+
traceparent?: string): Promise<unknown>;
|
|
62
69
|
export declare function callSandboxTool(sandbox: SandboxManager, routing: ToolRouting, request: HostEffect, signal: AbortSignal): Promise<unknown>;
|
package/dist/harness/calls.js
CHANGED
|
@@ -3,23 +3,23 @@
|
|
|
3
3
|
* Tenant's provider), the Tool Gate, the MCP pool, the SandboxManager. No store, no record: the
|
|
4
4
|
* session's routing comes with the run (`TurnStart.routing`).
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { READ_ARTIFACT_TOOL, SAVE_ARTIFACT_TOOL, } from "@nylorun/core/define";
|
|
7
7
|
import { runAbortKind } from "@nylorun/harness/api";
|
|
8
8
|
import { httpToolRefOf } from "../gates/http-tool.js";
|
|
9
9
|
import { classifyThrown } from "../model/classify.js";
|
|
10
10
|
import { findServer } from "../mcp/pool.js";
|
|
11
11
|
import { manifestFor, mcpToolOf } from "../mcp/snapshot.js";
|
|
12
|
-
import {
|
|
12
|
+
import { isPinnedRuntimeTool, sandboxToolSpec } from "../sandbox/runtime-tools.js";
|
|
13
13
|
/**
|
|
14
14
|
* Call the model for one effect. A provider failure comes back as a failure outcome
|
|
15
15
|
* (Model Calls §6), whichever provider serves the call; only an abort throws, and the
|
|
16
|
-
* advance decides what the abort means.
|
|
16
|
+
* advance decides what the abort means. `atGate` sends the call to the Model Gate even when the
|
|
17
|
+
* Tenant's model is not from the vault: the Tenant's fixture model is answered there (R4.3).
|
|
17
18
|
*/
|
|
18
|
-
export async function invokeModel(route, request, signal,
|
|
19
|
+
export async function invokeModel(route, request, signal, options = {}) {
|
|
20
|
+
const atGate = route.useVaultModel || options.atGate === true;
|
|
19
21
|
try {
|
|
20
|
-
if (
|
|
21
|
-
return await model(request, signal);
|
|
22
|
-
if (!route.useVaultModel)
|
|
22
|
+
if (!atGate)
|
|
23
23
|
return await route.modelProvider(request, signal);
|
|
24
24
|
return await route.modelGate.call({
|
|
25
25
|
tenantId: route.tenantId,
|
|
@@ -35,7 +35,7 @@ export async function invokeModel(route, request, signal, model) {
|
|
|
35
35
|
if (signal.aborted) {
|
|
36
36
|
// A call that outlives this process stops only when told to: on a user cancel. After a
|
|
37
37
|
// shutdown or a lost lease the next owner re-sends it and picks up its outcome (P1.2).
|
|
38
|
-
if (
|
|
38
|
+
if (atGate && runAbortKind(signal) === "cancel" && route.modelGate.cancel)
|
|
39
39
|
await route.modelGate.cancel({
|
|
40
40
|
tenantId: route.tenantId,
|
|
41
41
|
sessionId: request.sessionId,
|
|
@@ -65,20 +65,18 @@ export function abortOn(signal, kinds) {
|
|
|
65
65
|
signal.addEventListener("abort", follow, { once: true });
|
|
66
66
|
return controller.signal;
|
|
67
67
|
}
|
|
68
|
-
/** True when `request` calls `save_artifact
|
|
68
|
+
/** True when `request` calls `save_artifact`, which the Runtime pinned on `manifest`. */
|
|
69
69
|
export function isSaveArtifactCall(manifest, request) {
|
|
70
70
|
return isArtifactsToolCall(manifest, request, SAVE_ARTIFACT_TOOL);
|
|
71
71
|
}
|
|
72
|
-
/** True when `request` calls `read_artifact` (R2b C11)
|
|
72
|
+
/** True when `request` calls `read_artifact` (R2b C11), which the Runtime pinned on `manifest`. */
|
|
73
73
|
export function isReadArtifactCall(manifest, request) {
|
|
74
74
|
return isArtifactsToolCall(manifest, request, READ_ARTIFACT_TOOL);
|
|
75
75
|
}
|
|
76
76
|
function isArtifactsToolCall(manifest, request, toolName) {
|
|
77
77
|
return (request.kind === "tool" &&
|
|
78
|
-
request.capabilityId === ARTIFACTS_CAPABILITY_ID &&
|
|
79
78
|
request.toolName === toolName &&
|
|
80
|
-
manifest
|
|
81
|
-
capability.tools?.some((tool) => tool.name === toolName) === true) === true);
|
|
79
|
+
isPinnedRuntimeTool(manifest, toolName));
|
|
82
80
|
}
|
|
83
81
|
/** True when `request` calls a tool of a declared MCP server (every one is remote). */
|
|
84
82
|
export function isRemoteMcpCall(routing, request) {
|
|
@@ -87,23 +85,23 @@ export function isRemoteMcpCall(routing, request) {
|
|
|
87
85
|
const tool = mcpToolOf(routing.mcpSnapshot, request);
|
|
88
86
|
if (!tool)
|
|
89
87
|
return false;
|
|
90
|
-
return findServer(routing.rootManifest, tool.agentId, tool.
|
|
88
|
+
return findServer(routing.rootManifest, tool.agentId, tool.serverName) !== undefined;
|
|
91
89
|
}
|
|
92
|
-
export async function callMcpTool(mcp, routing, request, signal
|
|
90
|
+
export async function callMcpTool(mcp, routing, request, signal,
|
|
91
|
+
/** The call's span context (R7.4), sent as `traceparent` where this process holds the connection. */
|
|
92
|
+
traceparent) {
|
|
93
93
|
const tool = mcpToolOf(routing.mcpSnapshot, request);
|
|
94
94
|
if (!tool)
|
|
95
95
|
throw new Error(`MCP tool '${request.toolName ?? ""}' is not in the session snapshot`);
|
|
96
96
|
return mcp.call({
|
|
97
97
|
sessionId: request.sessionId,
|
|
98
98
|
...(tool.agentId === undefined ? {} : { agentId: tool.agentId }),
|
|
99
|
-
capabilityId: tool.capabilityId,
|
|
100
99
|
serverName: tool.serverName,
|
|
101
100
|
serverToolName: tool.serverToolName,
|
|
102
101
|
args: request.input,
|
|
103
102
|
manifest: routing.rootManifest,
|
|
104
103
|
effectId: request.effectId,
|
|
105
|
-
|
|
106
|
-
retrySafe: tool.annotations?.readOnlyHint === true || tool.annotations?.idempotentHint === true,
|
|
104
|
+
...(traceparent ? { traceparent } : {}),
|
|
107
105
|
signal,
|
|
108
106
|
});
|
|
109
107
|
}
|
|
@@ -112,22 +110,30 @@ export async function callMcpTool(mcp, routing, request, signal) {
|
|
|
112
110
|
* effect's agent used as a tool, or the root), or a flow's HTTP stage or HTTP verifier. Its
|
|
113
111
|
* outcome is the effect's value; a throw leaves the effect `uncertain`.
|
|
114
112
|
*/
|
|
115
|
-
export async function callHttpTool(gate, request, signal
|
|
113
|
+
export async function callHttpTool(gate, request, signal,
|
|
114
|
+
/** The call's span context (R7.4); the gates service reads its own from the journal. */
|
|
115
|
+
traceparent) {
|
|
116
116
|
if (!gate.callHttp)
|
|
117
117
|
throw new Error("This Runtime has no Tool Gate for HTTP tools");
|
|
118
|
-
return gate.callHttp({
|
|
118
|
+
return gate.callHttp({
|
|
119
|
+
tool: httpToolRefOf(request),
|
|
120
|
+
effectId: request.effectId,
|
|
121
|
+
turnId: request.turnId,
|
|
122
|
+
input: request.input,
|
|
123
|
+
...(traceparent ? { traceparent } : {}),
|
|
124
|
+
}, signal);
|
|
119
125
|
}
|
|
120
126
|
export async function callSandboxTool(sandbox, routing, request, signal) {
|
|
121
|
-
const
|
|
122
|
-
if (!
|
|
127
|
+
const spec = sandboxToolSpec(manifestFor(routing.rootManifest, request.agent), request.toolName);
|
|
128
|
+
if (!spec)
|
|
123
129
|
throw new Error(`'${request.toolName ?? ""}' is not a sandbox tool`);
|
|
124
130
|
// Agents used as tools share the session's sandbox; the tree declares one sandbox spec.
|
|
125
131
|
return sandbox.run({
|
|
126
132
|
id: routing.sandboxOwnerId,
|
|
127
133
|
activeTurnId: routing.activeTurnId,
|
|
128
134
|
manifest: routing.rootManifest,
|
|
129
|
-
...(routing.
|
|
135
|
+
...(routing.environmentId === undefined ? {} : { environmentId: routing.environmentId }),
|
|
130
136
|
...(routing.environment === undefined ? {} : { environment: routing.environment }),
|
|
131
137
|
...(routing.claim === undefined ? {} : { claim: routing.claim }),
|
|
132
|
-
},
|
|
138
|
+
}, spec, request.toolName, request.input, signal);
|
|
133
139
|
}
|