@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.
Files changed (301) hide show
  1. package/CHANGELOG.md +252 -0
  2. package/README.md +87 -28
  3. package/dist/adapters/execution/restate.js +1 -1
  4. package/dist/adapters/replication/pgoutput.d.ts +2 -0
  5. package/dist/adapters/replication/pgoutput.js +6 -3
  6. package/dist/adapters/sandbox/local.d.ts +9 -1
  7. package/dist/adapters/sandbox/local.js +16 -4
  8. package/dist/adapters/sandbox/virtual.js +4 -1
  9. package/dist/api/a2a/card.d.ts +11 -1
  10. package/dist/api/a2a/card.js +26 -2
  11. package/dist/api/a2a/endpoint.js +9 -3
  12. package/dist/api/a2a/protocol.d.ts +25 -2
  13. package/dist/api/a2a/protocol.js +20 -3
  14. package/dist/api/a2a/routes.d.ts +6 -1
  15. package/dist/api/a2a/routes.js +67 -9
  16. package/dist/api/a2a/tasks.js +2 -1
  17. package/dist/api/ag-ui/endpoint.js +8 -3
  18. package/dist/api/ag-ui/history.d.ts +6 -1
  19. package/dist/api/ag-ui/history.js +39 -3
  20. package/dist/api/ag-ui/routes.d.ts +4 -1
  21. package/dist/api/ag-ui/routes.js +63 -20
  22. package/dist/api/ag-ui/translate.js +3 -2
  23. package/dist/api/components.d.ts +5327 -1091
  24. package/dist/api/components.js +40 -16
  25. package/dist/api/gate/keys.d.ts +2 -1
  26. package/dist/api/gate/keys.js +14 -1
  27. package/dist/api/gate/routes.d.ts +6 -0
  28. package/dist/api/gate/routes.js +52 -3
  29. package/dist/api/http/app.js +17 -6
  30. package/dist/api/http/body.d.ts +3 -3
  31. package/dist/api/http/body.js +7 -7
  32. package/dist/api/http/define.d.ts +6 -0
  33. package/dist/api/http/define.js +13 -1
  34. package/dist/api/http/respond.js +1 -1
  35. package/dist/api/http/routes/artifacts.js +35 -8
  36. package/dist/api/http/routes/coverage.d.ts +9 -0
  37. package/dist/api/http/routes/coverage.js +34 -0
  38. package/dist/api/http/routes/environment-manifests.d.ts +9 -0
  39. package/dist/api/http/routes/environment-manifests.js +118 -0
  40. package/dist/api/http/routes/environments.d.ts +11 -0
  41. package/dist/api/http/routes/environments.js +332 -0
  42. package/dist/api/http/routes/mcp.d.ts +1 -1
  43. package/dist/api/http/routes/mcp.js +2 -2
  44. package/dist/api/http/routes/me.js +1 -1
  45. package/dist/api/http/routes/reads.d.ts +94 -9
  46. package/dist/api/http/routes/reads.js +54 -5
  47. package/dist/api/http/routes/sessions.js +24 -9
  48. package/dist/api/http/routes/tenant.js +65 -15
  49. package/dist/api/inbound-files.d.ts +65 -0
  50. package/dist/api/inbound-files.js +115 -0
  51. package/dist/api/openapi.js +48 -28
  52. package/dist/artifacts/disk.d.ts +59 -0
  53. package/dist/artifacts/disk.js +569 -0
  54. package/dist/artifacts/export.d.ts +1 -1
  55. package/dist/artifacts/export.js +2 -3
  56. package/dist/artifacts/folders.d.ts +6 -3
  57. package/dist/artifacts/folders.js +17 -12
  58. package/dist/artifacts/media-types.d.ts +15 -0
  59. package/dist/artifacts/media-types.js +56 -4
  60. package/dist/artifacts/parts.d.ts +12 -3
  61. package/dist/artifacts/parts.js +15 -4
  62. package/dist/artifacts/service.d.ts +2 -1
  63. package/dist/artifacts/service.js +6 -1
  64. package/dist/artifacts/workspace.d.ts +5 -5
  65. package/dist/artifacts/workspace.js +7 -19
  66. package/dist/core/flow-host.d.ts +3 -4
  67. package/dist/core/flow-host.js +5 -2
  68. package/dist/core/provider.d.ts +3 -2
  69. package/dist/core/provider.js +5 -37
  70. package/dist/core/sandbox-routes.d.ts +2 -21
  71. package/dist/core/sandbox-routes.js +11 -44
  72. package/dist/core/turn-manifest.d.ts +3 -2
  73. package/dist/core/turn-manifest.js +29 -5
  74. package/dist/execution/types.d.ts +1 -1
  75. package/dist/gates/contract.d.ts +3 -24
  76. package/dist/gates/contract.js +1 -36
  77. package/dist/gates/egress-credentials.d.ts +9 -0
  78. package/dist/gates/egress-credentials.js +11 -4
  79. package/dist/gates/egress.d.ts +22 -1
  80. package/dist/gates/egress.js +116 -10
  81. package/dist/gates/fixture-model.d.ts +28 -0
  82. package/dist/gates/fixture-model.js +92 -0
  83. package/dist/gates/handler.js +4 -4
  84. package/dist/gates/http-tool.d.ts +9 -6
  85. package/dist/gates/http-tool.js +11 -17
  86. package/dist/gates/in-process.d.ts +5 -0
  87. package/dist/gates/in-process.js +12 -1
  88. package/dist/gates/journal.d.ts +30 -0
  89. package/dist/gates/journal.js +51 -0
  90. package/dist/gates/mcp-handler.d.ts +4 -0
  91. package/dist/gates/mcp-handler.js +7 -4
  92. package/dist/gates/meter.d.ts +10 -2
  93. package/dist/gates/meter.js +20 -5
  94. package/dist/gates/policy.d.ts +49 -0
  95. package/dist/gates/policy.js +132 -0
  96. package/dist/gates/tenant-vaults.d.ts +7 -7
  97. package/dist/gates/tenant-vaults.js +5 -5
  98. package/dist/gates/tool-calls.d.ts +10 -5
  99. package/dist/gates/tool-calls.js +28 -10
  100. package/dist/gates/tool-client.d.ts +8 -0
  101. package/dist/gates/tool-client.js +27 -11
  102. package/dist/gates/tool-contract.d.ts +11 -69
  103. package/dist/gates/tool-contract.js +1 -85
  104. package/dist/gates/tool-gate.d.ts +1 -1
  105. package/dist/harness/calls.d.ts +14 -7
  106. package/dist/harness/calls.js +30 -24
  107. package/dist/harness/executors.js +12 -9
  108. package/dist/harness/main.js +24 -5
  109. package/dist/harness/pod.d.ts +39 -0
  110. package/dist/harness/pod.js +46 -0
  111. package/dist/harness/service.d.ts +0 -1
  112. package/dist/harness/service.js +17 -9
  113. package/dist/harness/setup.d.ts +29 -0
  114. package/dist/harness/setup.js +174 -0
  115. package/dist/harness/ws-client.js +3 -2
  116. package/dist/harness/ws-port.d.ts +1 -5
  117. package/dist/harness/ws-port.js +1 -5
  118. package/dist/harness-api/in-process.js +3 -3
  119. package/dist/harness-api/record.d.ts +15 -1
  120. package/dist/harness-api/record.js +180 -50
  121. package/dist/harness-api/redact.d.ts +3 -0
  122. package/dist/harness-api/redact.js +45 -0
  123. package/dist/harness-api/server.d.ts +35 -4
  124. package/dist/harness-api/server.js +130 -17
  125. package/dist/harness-api/start.d.ts +10 -3
  126. package/dist/harness-api/start.js +40 -10
  127. package/dist/harness-api/tool-journal.d.ts +105 -0
  128. package/dist/harness-api/tool-journal.js +132 -0
  129. package/dist/harness-api/tool-status.d.ts +13 -0
  130. package/dist/harness-api/tool-status.js +26 -0
  131. package/dist/harness-api/workspace.d.ts +12 -7
  132. package/dist/harness-api/workspace.js +47 -25
  133. package/dist/harness-api/ws-server.d.ts +11 -3
  134. package/dist/harness-api/ws-server.js +94 -15
  135. package/dist/host/gates.d.ts +2 -1
  136. package/dist/host/gates.js +10 -2
  137. package/dist/host/main.js +54 -5
  138. package/dist/host/operate.js +67 -5
  139. package/dist/host/stack-config.d.ts +64 -0
  140. package/dist/host/stack-config.js +62 -2
  141. package/dist/keys/client.js +4 -1
  142. package/dist/keys/keys.d.ts +13 -6
  143. package/dist/keys/keys.js +9 -8
  144. package/dist/management-openapi.json +1264 -2171
  145. package/dist/mcp/connect.d.ts +26 -22
  146. package/dist/mcp/connect.js +30 -34
  147. package/dist/mcp/pool.d.ts +3 -6
  148. package/dist/mcp/pool.js +14 -28
  149. package/dist/mcp/preview.d.ts +3 -3
  150. package/dist/mcp/preview.js +10 -21
  151. package/dist/mcp/snapshot.d.ts +16 -24
  152. package/dist/mcp/snapshot.js +33 -45
  153. package/dist/model/capabilities.d.ts +26 -0
  154. package/dist/model/capabilities.js +44 -0
  155. package/dist/model/catalog.d.ts +34 -3
  156. package/dist/model/catalog.js +38 -2
  157. package/dist/model/models.d.ts +2 -0
  158. package/dist/model/models.js +1 -1
  159. package/dist/model/native-blocks.d.ts +35 -0
  160. package/dist/model/native-blocks.js +170 -0
  161. package/dist/model/pi-model.js +114 -94
  162. package/dist/openapi.json +12822 -3943
  163. package/dist/reads/types.d.ts +16 -3
  164. package/dist/record/append.d.ts +3 -1
  165. package/dist/record/append.js +1 -0
  166. package/dist/record/envelope.d.ts +5 -1
  167. package/dist/record/envelope.js +7 -3
  168. package/dist/record/environment.d.ts +25 -0
  169. package/dist/record/environment.js +44 -0
  170. package/dist/record/index.d.ts +1 -1
  171. package/dist/record/index.js +1 -1
  172. package/dist/sandbox/disk-fs.d.ts +95 -0
  173. package/dist/sandbox/disk-fs.js +206 -0
  174. package/dist/sandbox/join.d.ts +17 -18
  175. package/dist/sandbox/join.js +46 -15
  176. package/dist/sandbox/manager.d.ts +47 -21
  177. package/dist/sandbox/manager.js +162 -107
  178. package/dist/sandbox/placement.d.ts +14 -13
  179. package/dist/sandbox/placement.js +31 -14
  180. package/dist/sandbox/pods/client.d.ts +9 -2
  181. package/dist/sandbox/pods/lifecycle.d.ts +36 -27
  182. package/dist/sandbox/pods/lifecycle.js +29 -26
  183. package/dist/sandbox/pods/reconcile.js +18 -12
  184. package/dist/sandbox/pods/spec.d.ts +15 -13
  185. package/dist/sandbox/pods/spec.js +17 -20
  186. package/dist/sandbox/records.d.ts +2 -2
  187. package/dist/sandbox/records.js +3 -3
  188. package/dist/sandbox/resolve.d.ts +37 -27
  189. package/dist/sandbox/resolve.js +73 -41
  190. package/dist/sandbox/runtime-tools.d.ts +9 -0
  191. package/dist/sandbox/runtime-tools.js +16 -0
  192. package/dist/sandbox/session-sandbox.d.ts +4 -6
  193. package/dist/sandbox/session-sandbox.js +47 -94
  194. package/dist/sandbox/setup.d.ts +64 -0
  195. package/dist/sandbox/setup.js +160 -0
  196. package/dist/sandbox/share.d.ts +21 -26
  197. package/dist/sandbox/share.js +36 -63
  198. package/dist/sandbox/skills.d.ts +8 -6
  199. package/dist/sandbox/skills.js +24 -23
  200. package/dist/sandbox/tenant-config.d.ts +12 -14
  201. package/dist/sandbox/tenant-config.js +12 -17
  202. package/dist/sandbox/types.d.ts +6 -0
  203. package/dist/store/postgres/drizzle/0020_environments.sql +63 -0
  204. package/dist/store/postgres/drizzle/0021_disk_versions.sql +7 -0
  205. package/dist/store/postgres/drizzle/0022_model_usage_timing.sql +5 -0
  206. package/dist/store/postgres/drizzle/0023_artifact_pages.sql +1 -0
  207. package/dist/store/postgres/drizzle/0024_flat_manifest.sql +7 -0
  208. package/dist/store/postgres/drizzle/0025_environment_manifests.sql +14 -0
  209. package/dist/store/postgres/drizzle/0026_environment_forks.sql +1 -0
  210. package/dist/store/postgres/drizzle/0027_environment_image_digest.sql +1 -0
  211. package/dist/store/postgres/drizzle/meta/_journal.json +56 -0
  212. package/dist/store/postgres/reads.js +123 -17
  213. package/dist/store/postgres/record-writer.d.ts +4 -4
  214. package/dist/store/postgres/record-writer.js +9 -9
  215. package/dist/store/postgres/record.d.ts +7 -0
  216. package/dist/store/postgres/record.js +23 -2
  217. package/dist/store/postgres/schema.d.ts +1126 -736
  218. package/dist/store/postgres/schema.js +136 -73
  219. package/dist/store/postgres/store.js +195 -67
  220. package/dist/store/types.d.ts +165 -50
  221. package/dist/tenant/advance.d.ts +7 -6
  222. package/dist/tenant/advance.js +118 -42
  223. package/dist/tenant/artifact-tool.d.ts +1 -1
  224. package/dist/tenant/artifact-tool.js +46 -26
  225. package/dist/tenant/commands.d.ts +15 -2
  226. package/dist/tenant/commands.js +115 -14
  227. package/dist/tenant/context.d.ts +56 -24
  228. package/dist/tenant/context.js +4 -15
  229. package/dist/tenant/effects.d.ts +1 -1
  230. package/dist/tenant/effects.js +44 -29
  231. package/dist/tenant/environment-manifests.d.ts +57 -0
  232. package/dist/tenant/environment-manifests.js +200 -0
  233. package/dist/tenant/environments.d.ts +174 -0
  234. package/dist/tenant/environments.js +1044 -0
  235. package/dist/tenant/harness-tokens.d.ts +21 -0
  236. package/dist/tenant/harness-tokens.js +61 -0
  237. package/dist/tenant/host-token.d.ts +1 -1
  238. package/dist/tenant/host-token.js +2 -4
  239. package/dist/tenant/identity-file.d.ts +4 -4
  240. package/dist/tenant/identity-file.js +17 -8
  241. package/dist/tenant/issuers.js +3 -3
  242. package/dist/tenant/model-setting.d.ts +14 -0
  243. package/dist/tenant/model-setting.js +51 -0
  244. package/dist/tenant/principals.js +1 -1
  245. package/dist/tenant/reset.js +3 -3
  246. package/dist/tenant/runtime.d.ts +6 -1
  247. package/dist/tenant/runtime.js +7 -1
  248. package/dist/tenant/session.d.ts +3 -3
  249. package/dist/tenant/session.js +0 -14
  250. package/dist/tenant/sessions.d.ts +18 -14
  251. package/dist/tenant/sessions.js +99 -143
  252. package/dist/tenant/signing-keys.d.ts +5 -1
  253. package/dist/tenant/skill-tool.d.ts +3 -3
  254. package/dist/tenant/skill-tool.js +6 -11
  255. package/dist/tenant/status.js +3 -3
  256. package/dist/tenant/sweep.js +13 -7
  257. package/dist/tenant/tool-results.js +1 -1
  258. package/dist/tenant/tool-search.d.ts +7 -11
  259. package/dist/tenant/tool-search.js +8 -5
  260. package/dist/tenant/transcript.d.ts +245 -36
  261. package/dist/tenant/transcript.js +64 -12
  262. package/dist/tenant/turn-timing.d.ts +43 -0
  263. package/dist/tenant/turn-timing.js +39 -0
  264. package/dist/tenant/types.d.ts +2 -0
  265. package/dist/traces/ids.d.ts +41 -0
  266. package/dist/traces/ids.js +81 -0
  267. package/dist/traces/key.d.ts +6 -0
  268. package/dist/traces/key.js +37 -0
  269. package/dist/traces/map.d.ts +113 -0
  270. package/dist/traces/map.js +289 -0
  271. package/dist/traces/options.d.ts +7 -0
  272. package/dist/traces/options.js +1 -0
  273. package/dist/traces/otlp.d.ts +42 -0
  274. package/dist/traces/otlp.js +84 -0
  275. package/dist/traces/projector.d.ts +58 -0
  276. package/dist/traces/projector.js +200 -0
  277. package/dist/traces/read.d.ts +23 -0
  278. package/dist/traces/read.js +16 -0
  279. package/dist/vault/coverage.d.ts +26 -0
  280. package/dist/vault/coverage.js +62 -0
  281. package/dist/vault/error.d.ts +11 -1
  282. package/dist/vault/error.js +5 -1
  283. package/dist/vault/host-model.d.ts +4 -1
  284. package/dist/vault/host-model.js +10 -2
  285. package/dist/vault/service.d.ts +92 -48
  286. package/dist/vault/service.js +462 -376
  287. package/dist/vault/sources.d.ts +5 -16
  288. package/dist/vault/sources.js +6 -8
  289. package/dist/version.d.ts +1 -1
  290. package/dist/version.js +2 -2
  291. package/package.json +13 -13
  292. package/dist/api/http/routes/sandboxes.d.ts +0 -9
  293. package/dist/api/http/routes/sandboxes.js +0 -153
  294. package/dist/api/http/routes/vaults.d.ts +0 -10
  295. package/dist/api/http/routes/vaults.js +0 -139
  296. package/dist/record/sandbox.d.ts +0 -25
  297. package/dist/record/sandbox.js +0 -43
  298. package/dist/sandbox/capability.d.ts +0 -3
  299. package/dist/sandbox/capability.js +0 -10
  300. package/dist/tenant/sandboxes.d.ts +0 -123
  301. package/dist/tenant/sandboxes.js +0 -566
@@ -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, approvals become interrupts resumed through `resume`, and the last AG-UI
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";
@@ -33,7 +36,7 @@ import { fail, HttpError } from "../../tenant/http.js";
33
36
  import { observeSession, readHistory, StreamClosed, streamHolderOf, } from "../../tenant/session-streams.js";
34
37
  import { putSession, sessionView } from "../../tenant/sessions.js";
35
38
  import { mayUseAgent } from "../../tenant/auth.js";
36
- import { sandboxGrantsOf } from "../../tenant/sandboxes.js";
39
+ import { environmentGrantsOf } from "../../tenant/environments.js";
37
40
  const HEARTBEAT_MS = 15_000;
38
41
  const TERMINAL = new Set([
39
42
  "turn.completed",
@@ -60,11 +63,38 @@ function runError(error) {
60
63
  : error.message;
61
64
  return { type: EventType.RUN_ERROR, message, code };
62
65
  }
63
- /** The trailing user message: the Runtime keeps the transcript, AG-UI resends all of it. */
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
@@ -83,8 +113,7 @@ function sessionOptions(input, scope) {
83
113
  return {};
84
114
  const parsed = PutSessionRequestSchema.pick({
85
115
  info: true,
86
- vaultIds: true,
87
- credentialSelections: true,
116
+ environment: true,
88
117
  })
89
118
  .strict()
90
119
  .safeParse(raw);
@@ -99,11 +128,11 @@ function sessionOptions(input, scope) {
99
128
  });
100
129
  return parsed.data;
101
130
  }
102
- async function accepted(ctx, id, body, scope) {
103
- const result = (await command(ctx, id, body, scope));
131
+ async function accepted(ctx, id, body, scope, trace) {
132
+ const result = (await command(ctx, id, body, scope, trace ? { trace } : {}));
104
133
  return result?.cursor ?? null;
105
134
  }
106
- async function submit(ctx, id, input, scope) {
135
+ async function submit(ctx, id, input, scope, trace) {
107
136
  if (input.resume?.length) {
108
137
  // The interaction's kind is on the session's pending view, not in its id.
109
138
  const view = (await ctx.store.tx(async (t) => sessionView(t, await sessionOf(t, id, accessOf(scope)))));
@@ -139,12 +168,23 @@ async function submit(ctx, id, input, scope) {
139
168
  const message = lastUserMessage(input.messages);
140
169
  // The AG-UI message id is the idempotency key: a retried run replays the same turn, and
141
170
  // history gives the message back its client id.
142
- return accepted(ctx, id, {
143
- type: "message",
144
- requestId: randomUUID(),
145
- idempotencyKey: message.id,
146
- content: message.text,
147
- }, scope);
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
+ }
148
188
  }
149
189
  /**
150
190
  * Streams translated events until the run ends. Closing the connection stops the read, never
@@ -229,7 +269,9 @@ export function agUiCaller(scope, agentId) {
229
269
  return { subject, access: accessOf(scope) };
230
270
  }
231
271
  /** `POST /v1/ag-ui/agents/:agent`: start a run, and stream it on `response`. */
232
- export async function startRun(ctx, scope, agentId, caller, body, response) {
272
+ export async function startRun(ctx, scope, agentId, caller, body, response,
273
+ /** The request's trace context (R7.4): the turn the run starts joins the caller's trace. */
274
+ trace) {
233
275
  const parsed = RunAgentInputSchema.safeParse(body);
234
276
  if (!parsed.success)
235
277
  return fail(400, "Invalid RunAgentInput", { code: "invalid_request" });
@@ -245,16 +287,17 @@ export async function startRun(ctx, scope, agentId, caller, body, response) {
245
287
  ...sessionOptions(input, scope),
246
288
  }, caller.access, {
247
289
  createOnly: true,
248
- ...(sandboxGrantsOf(scope) === undefined ? {} : { sandboxGrants: sandboxGrantsOf(scope) }),
290
+ ...(environmentGrantsOf(scope) === undefined ? {} : { environmentGrants: environmentGrantsOf(scope) }),
249
291
  });
250
292
  const translator = new RunTranslator(input.threadId, input.runId);
251
293
  let cursor;
252
294
  try {
253
- cursor = await submit(ctx, id, input, scope);
295
+ cursor = await submit(ctx, id, input, scope, trace);
254
296
  }
255
297
  catch (error) {
256
- // A busy session or a limit is a run that could not start, not a transport failure.
257
- if (error instanceof HttpError && (error.status === 409 || error.status === 429))
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))
258
301
  return stream(response, translator, undefined, [runError(error)]);
259
302
  throw error;
260
303
  }
@@ -4,7 +4,7 @@
4
4
  * `<callId>:result`, so live runs and `messagesFromEvents` agree.
5
5
  */
6
6
  import { EventType } from "@ag-ui/core";
7
- import { parseTranscriptEvent, } from "@nylorun/core/contracts";
7
+ import { isEmptyAssistantMessage, parseTranscriptEvent, } from "@nylorun/core/contracts";
8
8
  /** The text a tool result shows; `undefined` while there is no result yet. */
9
9
  export function toolResultText(result) {
10
10
  const value = result;
@@ -89,7 +89,8 @@ export class RunTranslator {
89
89
  switch (event.type) {
90
90
  case "message.assistant": {
91
91
  const p = event.payload;
92
- if (p.agent)
92
+ // A step that said nothing is in the log for its timing (R7.1), never a message.
93
+ if (p.agent || isEmptyAssistantMessage(p))
93
94
  return none;
94
95
  this.sawAssistant = true;
95
96
  return { events: assistantEvents(p), finished: false };