@nylorun/runtime 0.24.0-beta → 0.26.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 +143 -0
- package/README.md +18 -4
- package/dist/api/a2a/card.d.ts +11 -1
- package/dist/api/a2a/card.js +26 -2
- package/dist/api/a2a/endpoint.js +4 -2
- package/dist/api/a2a/protocol.d.ts +25 -2
- package/dist/api/a2a/protocol.js +20 -3
- package/dist/api/a2a/routes.d.ts +4 -1
- package/dist/api/a2a/routes.js +65 -7
- package/dist/api/ag-ui/endpoint.js +5 -2
- package/dist/api/ag-ui/history.d.ts +6 -1
- package/dist/api/ag-ui/history.js +35 -2
- package/dist/api/ag-ui/routes.js +53 -11
- package/dist/api/components.d.ts +1165 -678
- package/dist/api/components.js +16 -1
- package/dist/api/gate/keys.d.ts +2 -1
- package/dist/api/gate/keys.js +7 -0
- package/dist/api/gate/routes.js +13 -0
- package/dist/api/http/app.d.ts +2 -2
- package/dist/api/http/app.js +15 -4
- package/dist/api/http/body.d.ts +3 -3
- package/dist/api/http/body.js +7 -7
- package/dist/api/http/define.d.ts +1 -1
- package/dist/api/http/respond.js +1 -1
- package/dist/api/http/routes/environment-manifests.d.ts +9 -0
- package/dist/api/http/routes/environment-manifests.js +118 -0
- package/dist/api/http/routes/environments.js +61 -12
- package/dist/api/http/routes/reads.d.ts +52 -3
- package/dist/api/http/routes/sessions.js +14 -4
- package/dist/api/http/routes/tenant.js +35 -7
- package/dist/api/inbound-files.d.ts +65 -0
- package/dist/api/inbound-files.js +115 -0
- package/dist/api/openapi.js +18 -3
- package/dist/artifacts/disk.js +20 -14
- package/dist/artifacts/media-types.d.ts +15 -0
- package/dist/artifacts/media-types.js +56 -4
- package/dist/artifacts/parts.d.ts +12 -3
- package/dist/artifacts/parts.js +15 -4
- package/dist/artifacts/workspace.d.ts +4 -4
- package/dist/artifacts/workspace.js +6 -18
- package/dist/core/flow-host.d.ts +1 -1
- package/dist/core/flow-host.js +2 -2
- package/dist/core/sandbox-routes.js +2 -2
- package/dist/core/turn-manifest.d.ts +3 -2
- package/dist/core/turn-manifest.js +29 -5
- package/dist/gates/egress-credentials.js +1 -1
- package/dist/gates/egress.d.ts +13 -19
- package/dist/gates/egress.js +32 -29
- package/dist/gates/http-tool.d.ts +3 -4
- package/dist/gates/http-tool.js +23 -19
- package/dist/gates/journal.js +0 -1
- package/dist/gates/mcp-handler.js +2 -3
- package/dist/gates/policy.js +1 -3
- package/dist/gates/tool-contract.d.ts +1 -1
- package/dist/harness/calls.d.ts +2 -2
- package/dist/harness/calls.js +9 -12
- package/dist/harness/main.js +7 -1
- package/dist/harness/pod.d.ts +6 -1
- package/dist/harness/pod.js +5 -0
- package/dist/harness/service.js +5 -5
- package/dist/harness/setup.d.ts +2 -0
- package/dist/harness/setup.js +25 -1
- package/dist/harness-api/record.d.ts +1 -1
- package/dist/harness-api/record.js +13 -13
- package/dist/harness-api/server.d.ts +27 -4
- package/dist/harness-api/server.js +41 -8
- package/dist/harness-api/tool-journal.d.ts +17 -8
- package/dist/harness-api/tool-journal.js +41 -11
- package/dist/harness-api/workspace.d.ts +7 -5
- package/dist/harness-api/workspace.js +25 -19
- package/dist/host/gates.js +2 -2
- package/dist/host/stack-config.js +1 -1
- package/dist/keys/contract.d.ts +1 -1
- package/dist/keys/contract.js +1 -1
- package/dist/keys/keys.d.ts +9 -2
- package/dist/keys/keys.js +4 -1
- package/dist/management-openapi.json +366 -61
- package/dist/mcp/connect.d.ts +1 -2
- package/dist/mcp/connect.js +1 -4
- package/dist/mcp/pool.d.ts +1 -4
- package/dist/mcp/pool.js +13 -27
- package/dist/mcp/preview.d.ts +1 -1
- package/dist/mcp/preview.js +1 -2
- package/dist/mcp/snapshot.d.ts +11 -13
- package/dist/mcp/snapshot.js +27 -38
- package/dist/model/capabilities.d.ts +26 -0
- package/dist/model/capabilities.js +44 -0
- package/dist/model/catalog.d.ts +34 -3
- package/dist/model/catalog.js +38 -2
- package/dist/model/models.d.ts +2 -0
- package/dist/model/models.js +1 -1
- package/dist/model/native-blocks.d.ts +35 -0
- package/dist/model/native-blocks.js +170 -0
- package/dist/model/pi-model.js +106 -94
- package/dist/openapi.json +9554 -5076
- package/dist/record/environment.js +1 -1
- package/dist/sandbox/join.js +4 -0
- package/dist/sandbox/manager.d.ts +32 -14
- package/dist/sandbox/manager.js +132 -93
- package/dist/sandbox/placement.d.ts +1 -1
- package/dist/sandbox/placement.js +2 -2
- package/dist/sandbox/pods/client.d.ts +3 -1
- package/dist/sandbox/pods/lifecycle.d.ts +8 -0
- package/dist/sandbox/pods/lifecycle.js +15 -0
- package/dist/sandbox/pods/spec.js +2 -1
- package/dist/sandbox/resolve.d.ts +5 -3
- package/dist/sandbox/resolve.js +9 -2
- package/dist/sandbox/runtime-tools.d.ts +9 -0
- package/dist/sandbox/runtime-tools.js +16 -0
- package/dist/sandbox/session-sandbox.d.ts +4 -6
- package/dist/sandbox/session-sandbox.js +47 -94
- package/dist/sandbox/setup.d.ts +4 -1
- package/dist/sandbox/setup.js +46 -9
- package/dist/sandbox/share.d.ts +12 -7
- package/dist/sandbox/share.js +27 -25
- package/dist/sandbox/skills.d.ts +8 -6
- package/dist/sandbox/skills.js +24 -23
- package/dist/store/postgres/drizzle/0024_flat_manifest.sql +7 -0
- package/dist/store/postgres/drizzle/0025_environment_manifests.sql +14 -0
- package/dist/store/postgres/drizzle/0026_environment_forks.sql +1 -0
- package/dist/store/postgres/drizzle/0027_environment_image_digest.sql +1 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
- package/dist/store/postgres/migrate.js +1 -1
- package/dist/store/postgres/reads.js +8 -2
- package/dist/store/postgres/schema.d.ts +217 -0
- package/dist/store/postgres/schema.js +36 -2
- package/dist/store/postgres/store.js +79 -4
- package/dist/store/types.d.ts +68 -14
- package/dist/tenant/advance.js +3 -0
- package/dist/tenant/artifact-tool.d.ts +1 -1
- package/dist/tenant/artifact-tool.js +43 -22
- package/dist/tenant/commands.js +24 -4
- package/dist/tenant/context.d.ts +10 -4
- package/dist/tenant/effects.js +7 -9
- package/dist/tenant/environment-manifests.d.ts +57 -0
- package/dist/tenant/environment-manifests.js +200 -0
- package/dist/tenant/environments.d.ts +54 -47
- package/dist/tenant/environments.js +309 -85
- package/dist/tenant/ephemeral.d.ts +1 -1
- package/dist/tenant/host-token.js +1 -1
- package/dist/tenant/identity-file.d.ts +1 -1
- package/dist/tenant/identity-file.js +1 -1
- package/dist/tenant/model-setting.d.ts +14 -0
- package/dist/tenant/model-setting.js +51 -0
- package/dist/tenant/outbound.d.ts +6 -5
- package/dist/tenant/outbound.js +8 -6
- package/dist/tenant/sessions.d.ts +5 -1
- package/dist/tenant/sessions.js +45 -12
- package/dist/tenant/skill-tool.d.ts +3 -3
- package/dist/tenant/skill-tool.js +6 -11
- package/dist/tenant/sweep.js +1 -1
- package/dist/tenant/tool-results.js +1 -1
- package/dist/tenant/tool-search.d.ts +7 -11
- package/dist/tenant/tool-search.js +8 -5
- package/dist/tenant/transcript.d.ts +51 -32
- package/dist/tenant/transcript.js +2 -1
- package/dist/tenant/types.d.ts +2 -2
- package/dist/traces/ids.d.ts +0 -1
- package/dist/traces/ids.js +0 -4
- package/dist/traces/map.d.ts +2 -2
- package/dist/traces/map.js +1 -29
- package/dist/vault/coverage.js +11 -13
- package/dist/vault/host-model.d.ts +4 -1
- package/dist/vault/host-model.js +10 -2
- package/dist/vault/service.d.ts +49 -4
- package/dist/vault/service.js +153 -6
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/sandbox/capability.d.ts +0 -3
- package/dist/sandbox/capability.js +0 -10
|
@@ -1,10 +1,44 @@
|
|
|
1
1
|
import { isEmptyAssistantMessage, parseTranscriptEvent, } from "@nylorun/core/contracts";
|
|
2
2
|
import { outputText, toolResultOf } from "./translate.js";
|
|
3
|
+
/** The `provider` of a file source that names one of the Tenant's artifacts. */
|
|
4
|
+
export const NYLORUN_FILE_PROVIDER = "nylorun";
|
|
5
|
+
/** A file part as an AG-UI media part, its kind from its media type when the log has it. */
|
|
6
|
+
function filePart(artifactId, mediaType) {
|
|
7
|
+
const top = mediaType?.split("/")[0];
|
|
8
|
+
const type = top === "image" || top === "audio" || top === "video" ? top : "document";
|
|
9
|
+
return {
|
|
10
|
+
type,
|
|
11
|
+
source: {
|
|
12
|
+
type: "file",
|
|
13
|
+
value: artifactId,
|
|
14
|
+
provider: NYLORUN_FILE_PROVIDER,
|
|
15
|
+
...(mediaType ? { mimeType: mediaType } : {}),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** A message's parts (protocol 6): its text, or text and media parts when it has files. */
|
|
20
|
+
function partsContent(parts, mediaTypes) {
|
|
21
|
+
if (!parts.some((part) => part.type === "file"))
|
|
22
|
+
return parts.flatMap((part) => (typeof part.text === "string" ? [part.text] : [])).join("\n");
|
|
23
|
+
return parts.flatMap((part) => part.type === "file" && typeof part.artifactId === "string"
|
|
24
|
+
? [filePart(part.artifactId, mediaTypes.get(part.artifactId))]
|
|
25
|
+
: typeof part.text === "string"
|
|
26
|
+
? [{ type: "text", text: part.text }]
|
|
27
|
+
: []);
|
|
28
|
+
}
|
|
3
29
|
export function messagesFromEvents(items) {
|
|
4
30
|
const messages = [];
|
|
5
31
|
const results = new Set();
|
|
32
|
+
// Each artifact's media type, from its events, for the files a message names.
|
|
33
|
+
const mediaTypes = new Map();
|
|
6
34
|
let sawAssistant = false;
|
|
7
35
|
for (const raw of items) {
|
|
36
|
+
if (raw.type === "artifact.created" || raw.type === "artifact.version.created") {
|
|
37
|
+
const p = (raw.payload ?? {});
|
|
38
|
+
if (typeof p.artifactId === "string" && typeof p.contentType === "string")
|
|
39
|
+
mediaTypes.set(p.artifactId, p.contentType);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
8
42
|
if (raw.type === "command.message") {
|
|
9
43
|
const p = (raw.payload ?? {});
|
|
10
44
|
messages.push({
|
|
@@ -14,8 +48,7 @@ export function messagesFromEvents(items) {
|
|
|
14
48
|
content: typeof p.content === "string"
|
|
15
49
|
? p.content
|
|
16
50
|
: Array.isArray(p.parts)
|
|
17
|
-
?
|
|
18
|
-
p.parts.flatMap((part) => (typeof part.text === "string" ? [part.text] : [])).join("\n")
|
|
51
|
+
? partsContent(p.parts, mediaTypes)
|
|
19
52
|
: JSON.stringify(p.data),
|
|
20
53
|
});
|
|
21
54
|
sawAssistant = false;
|
package/dist/api/ag-ui/routes.js
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* - `POST …/threads/:thread/cancel` — cancel the running turn.
|
|
13
13
|
*
|
|
14
14
|
* Each thread maps to one session per subject, agent and thread. The message id is the
|
|
15
|
-
* idempotency key,
|
|
15
|
+
* idempotency key, a message's media parts become file parts (bytes sent inline are stored as
|
|
16
|
+
* artifacts of the session, `../inbound-files.ts`; a file the model does not read is a
|
|
17
|
+
* `RUN_ERROR`), approvals become interrupts resumed through `resume`, and the last AG-UI
|
|
16
18
|
* event made from each Runtime event carries its cursor as the SSE id. A run's session is
|
|
17
19
|
* created on its first run with the options in `forwardedProps.nylorun.session` and never
|
|
18
20
|
* changed afterwards. A stream opened with an issuer token ends at the token's expiry with
|
|
@@ -22,7 +24,8 @@ import { randomUUID } from "node:crypto";
|
|
|
22
24
|
import { EventType, } from "@ag-ui/core";
|
|
23
25
|
import { RunAgentInputSchema } from "@ag-ui/core/schemas";
|
|
24
26
|
import { PutSessionRequestSchema, } from "@nylorun/core/contracts";
|
|
25
|
-
import { messagesFromEvents } from "./history.js";
|
|
27
|
+
import { messagesFromEvents, NYLORUN_FILE_PROVIDER } from "./history.js";
|
|
28
|
+
import { discardFiles, inlineFileName, messageParts, refuseUrl, } from "../inbound-files.js";
|
|
26
29
|
import { sessionIdFor } from "./session-id.js";
|
|
27
30
|
import { SSE_CONTENT_TYPE, SSE_HEARTBEAT, sseFrame } from "./sse.js";
|
|
28
31
|
import { RunTranslator } from "./translate.js";
|
|
@@ -60,11 +63,38 @@ function runError(error) {
|
|
|
60
63
|
: error.message;
|
|
61
64
|
return { type: EventType.RUN_ERROR, message, code };
|
|
62
65
|
}
|
|
63
|
-
/**
|
|
66
|
+
/** A media part's file: bytes sent inline, or an artifact the Runtime already holds. */
|
|
67
|
+
function inboundFile(part, index) {
|
|
68
|
+
const { source } = part;
|
|
69
|
+
if (source.type === "url")
|
|
70
|
+
return refuseUrl();
|
|
71
|
+
if (source.type === "file") {
|
|
72
|
+
if (source.provider !== NYLORUN_FILE_PROVIDER)
|
|
73
|
+
return fail(400, `A file source names an artifact: provider "${NYLORUN_FILE_PROVIDER}" and its artifact id`, { code: "invalid_request" });
|
|
74
|
+
return { type: "artifact", artifactId: source.value };
|
|
75
|
+
}
|
|
76
|
+
const metadata = (part.metadata ?? {});
|
|
77
|
+
const named = [metadata.filename, metadata.name].find((value) => typeof value === "string" && value !== "");
|
|
78
|
+
return {
|
|
79
|
+
type: "inline",
|
|
80
|
+
name: named ?? inlineFileName(source.mimeType, index),
|
|
81
|
+
mediaType: source.mimeType,
|
|
82
|
+
data: source.value,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The trailing user message: the Runtime keeps the transcript, AG-UI resends all of it. Its
|
|
87
|
+
* text, or its parts when it carries a media part.
|
|
88
|
+
*/
|
|
64
89
|
function lastUserMessage(messages) {
|
|
65
90
|
const last = messages.at(-1);
|
|
66
91
|
if (!last || last.role !== "user")
|
|
67
92
|
return fail(400, "The run's last message must be a user message");
|
|
93
|
+
if (typeof last.content !== "string" && last.content.some((part) => part.type !== "text")) {
|
|
94
|
+
let files = 0;
|
|
95
|
+
const parts = last.content.map((part) => part.type === "text" ? { type: "text", text: part.text } : inboundFile(part, files++));
|
|
96
|
+
return { id: last.id, text: "", parts };
|
|
97
|
+
}
|
|
68
98
|
const text = typeof last.content === "string"
|
|
69
99
|
? last.content
|
|
70
100
|
: last.content
|
|
@@ -138,12 +168,23 @@ async function submit(ctx, id, input, scope, trace) {
|
|
|
138
168
|
const message = lastUserMessage(input.messages);
|
|
139
169
|
// The AG-UI message id is the idempotency key: a retried run replays the same turn, and
|
|
140
170
|
// history gives the message back its client id.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
171
|
+
if (!message.parts)
|
|
172
|
+
return accepted(ctx, id, {
|
|
173
|
+
type: "message",
|
|
174
|
+
requestId: randomUUID(),
|
|
175
|
+
idempotencyKey: message.id,
|
|
176
|
+
content: message.text,
|
|
177
|
+
}, scope, trace);
|
|
178
|
+
const access = accessOf(scope);
|
|
179
|
+
const { parts, stored } = await messageParts(ctx, id, message.id, message.parts, access);
|
|
180
|
+
try {
|
|
181
|
+
return await accepted(ctx, id, { type: "message", requestId: randomUUID(), idempotencyKey: message.id, parts }, scope, trace);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
// A refused message leaves no files behind.
|
|
185
|
+
await discardFiles(ctx, stored, access);
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
147
188
|
}
|
|
148
189
|
/**
|
|
149
190
|
* Streams translated events until the run ends. Closing the connection stops the read, never
|
|
@@ -254,8 +295,9 @@ trace) {
|
|
|
254
295
|
cursor = await submit(ctx, id, input, scope, trace);
|
|
255
296
|
}
|
|
256
297
|
catch (error) {
|
|
257
|
-
// A busy session or a
|
|
258
|
-
|
|
298
|
+
// A busy session, a limit or a file the model does not read is a run that could not start,
|
|
299
|
+
// not a transport failure.
|
|
300
|
+
if (error instanceof HttpError && [409, 422, 429].includes(error.status))
|
|
259
301
|
return stream(response, translator, undefined, [runError(error)]);
|
|
260
302
|
throw error;
|
|
261
303
|
}
|