@nylorun/runtime 0.38.0-beta → 0.40.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 (40) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/dist/api/a2a/endpoint.js +1 -1
  3. package/dist/api/a2a/protocol.d.ts +6 -0
  4. package/dist/api/a2a/protocol.js +13 -0
  5. package/dist/api/a2a/routes.js +1 -0
  6. package/dist/api/components.d.ts +1726 -80
  7. package/dist/api/http/routes/agents.js +3 -3
  8. package/dist/core/turn-manifest.d.ts +23 -0
  9. package/dist/core/turn-manifest.js +36 -1
  10. package/dist/gates/policy.d.ts +13 -3
  11. package/dist/gates/policy.js +17 -4
  12. package/dist/harness/executors.d.ts +4 -2
  13. package/dist/harness/executors.js +26 -4
  14. package/dist/harness-api/record.js +4 -2
  15. package/dist/harness-api/server.js +37 -13
  16. package/dist/harness-api/start.js +43 -5
  17. package/dist/keys/keys.d.ts +6 -3
  18. package/dist/keys/keys.js +1 -1
  19. package/dist/management-openapi.json +6 -4
  20. package/dist/mcp/pool.d.ts +5 -0
  21. package/dist/mcp/pool.js +1 -1
  22. package/dist/mcp/snapshot.d.ts +3 -1
  23. package/dist/mcp/snapshot.js +5 -3
  24. package/dist/openapi.json +1637 -564
  25. package/dist/store/postgres/store.js +14 -0
  26. package/dist/store/types.d.ts +9 -0
  27. package/dist/tenant/agent-versions.d.ts +13 -5
  28. package/dist/tenant/agent-versions.js +30 -6
  29. package/dist/tenant/agents.d.ts +14 -2
  30. package/dist/tenant/agents.js +51 -13
  31. package/dist/tenant/commands.js +16 -8
  32. package/dist/tenant/context.d.ts +30 -1
  33. package/dist/tenant/session-model.d.ts +35 -6
  34. package/dist/tenant/session-model.js +77 -9
  35. package/dist/tenant/sessions.js +13 -3
  36. package/dist/vault/service.d.ts +44 -3
  37. package/dist/vault/service.js +68 -27
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,81 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.40.0-beta
4
+
5
+ ### Minor Changes
6
+
7
+ - 78787e2: A2A `SendMessage` takes `message.metadata.removeTools` (Host feature `remove-tools`): the tools a new message's turn may not use, by name, as a session message's `removeTools`. `createA2aClient`'s `send` takes `removeTools`.
8
+
9
+ ## 0.39.0-beta
10
+
11
+ ### Minor Changes
12
+
13
+ - 67ed2ea: A version that sets `harness.memory.index: false` (`agent-folder/2`, ADR-100) gets no memory index
14
+ rendered: `turn.start.memory` comes without `index`. The harness may claim `engine.diagnostic`,
15
+ which the OpenAPI document lists.
16
+ - 67ed2ea: An MCP server that failed at a session's first discovery is tried again at each later turn's first
17
+ segment, and joins the session's snapshot once it answers: its tools are offered from that turn on,
18
+ its diagnostic is replaced, and `mcp.discovered` names it again with `rejoined: true`. `session.mcp`
19
+ takes a later snapshot of servers the session lacks and merges them within `mcpSnapshotBytes`.
20
+ - 67ed2ea: The memory index a session pinned is refreshed at its next turn's first segment (never mid-turn)
21
+ when another session of the Agent, or the API, wrote the Agent's memory since its last turn started:
22
+ `turn.start.memory.refresh` (Harness API), and our engine pins the index again (`runDurable`'s
23
+ `refreshPinned`). The Runtime keeps the newest memory version a turn saw on the session
24
+ (`Session.memoryIndex`, `memoryWritesSince`). A session's own writes leave its index as pinned.
25
+ - 67ed2ea: A tool policy rule whose `agent` names the session's root agent (its manifest's name) also matches
26
+ the MCP and HTTP calls of the agents it uses as tools; a rule naming the subagent's id still matches
27
+ them. `PolicyCall.root` carries the root for a subagent's call. The `agent` selector's contract
28
+ comments say so.
29
+ - 67ed2ea: A message's `removeTools` (Host feature `remove-tools`): the tools its turn may not use, by name. A
30
+ declared tool or an agent used as a tool by its name (in the agent and the agents it uses as tools),
31
+ an MCP server's tool as `<server>__<tool>`, a whole server by its name. The Runtime applies it to the
32
+ version the turn runs, after the turn's first segment re-pins the session to its Agent's version, so
33
+ a session that always sends it still moves to new versions; names that version lacks are ignored.
34
+ A message's turn manifest is validated again against the version a re-pin moves to; one that is no
35
+ variant of it keeps the turn on the version it pinned (`turn.version_kept`). A variant may narrow an
36
+ agent it uses as a tool (`isVariantOf`; `withoutTools` in `@nylorun/core/define`). An HTTP tool call
37
+ is checked against the turn's manifest. `session.input` and `session.inputParts` take
38
+ `removeTools`.
39
+ - 67ed2ea: Secret routing: the agent folder names, the installation routes (Host feature `secret-routing`, no
40
+ protocol change). A `bearer` or `headers` secret slot (`runtime.json`, `runtime.secrets`) takes the
41
+ gateway's `toolPrefix`, with or without `via`, and a slot's value write
42
+ (`PUT /v1/agents/{id}/secrets/{name}` with `{ value }` or `{ headers }`) takes `via`, with the same
43
+ URL rules as a slot's. At each request the secret's `via` wins, else the slot's in the version the
44
+ Agent runs, else none (the slot's `url`); the slot's `toolPrefix` wins over the secret's and
45
+ applies only with a `via`; the slot's `url` still picks the credential, for MCP servers and HTTP
46
+ tools alike, and an HTTP tool whose URL has `{field}` parameters still fails behind a `via`. A
47
+ write whose `toolPrefix` differs from its slot's is accepted, with a warning in the log. A `via` a
48
+ write copied from its slot follows the slot when the Agent moves, and a fork keeps a secret's own
49
+ `via`. Secret views show the `via` and `toolPrefix` in force, never a value.
50
+ `client.agents.secrets.put` takes `{ value | headers, via?, toolPrefix? }` (`AgentSecretRouting`),
51
+ and `nylorun agents secrets put` takes `--via` and `--tool-prefix`, and a slot's JSON without a
52
+ `type`. The JSON Schemas that gained the slot's `toolPrefix` are published as
53
+ `agent-manifest/v8.2`, `runtime-manifest/v1.1` and `agent-folder/v1/runtime.1`, which `nylorun init`
54
+ maps; the old `$schema` URLs are still read.
55
+ - 67ed2ea: A session records the model its turns call and why (`SessionModelRecord`): `model` on `GET
56
+ /v1/sessions/{id}` is `{provider, model, source: "manifest" | "session" | "tenant", reason?,
57
+ requested?}`, with the fallback's `reason` (`provider_not_connected`, `not_in_catalog`,
58
+ `invalid_model`) and the model `requested` by the manifest or the session. It is set when the
59
+ session opens, chooses or clears its model, and again at each segment's start, and each change
60
+ writes the new `session.model` event with the `previous` record. `SessionView.model` in
61
+ `@nylorun/agents`.
62
+
63
+ ### Patch Changes
64
+
65
+ - Pin core to the tested release.
66
+ - Pin harness to the tested release.
67
+ - Updated dependencies [67ed2ea]
68
+ - Updated dependencies [67ed2ea]
69
+ - Updated dependencies [67ed2ea]
70
+ - Updated dependencies [67ed2ea]
71
+ - Updated dependencies [67ed2ea]
72
+ - Updated dependencies [67ed2ea]
73
+ - Updated dependencies [67ed2ea]
74
+ - Updated dependencies [67ed2ea]
75
+ - Updated dependencies
76
+ - @nylorun/core@0.34.0-beta
77
+ - @nylorun/harness@0.31.0-beta
78
+
3
79
  ## 0.38.0-beta
4
80
 
5
81
  ### Minor Changes
@@ -72,7 +72,7 @@ export function a2aRoutes(api) {
72
72
  path: "/v1/a2a/agents/{agentId}",
73
73
  tags: TAGS,
74
74
  summary: "Call an agent over A2A",
75
- description: "A2A 1.0 JSON-RPC, for a subject, under the Nylorun profile v2 (Host feature `a2a-profile-v2`). `SendMessage` blocks up to the Runtime limit `a2aWaitMs` (5 minutes by default; then the task is answered still `WORKING`) unless `returnImmediately`; `GetTask` (with `historyLength`), `CancelTask` and `ListTasks`; and the four push notification config methods, plus `configuration.taskPushNotificationConfig` in `SendMessage`: each update is POSTed as one `StreamResponse`, signed with Standard Webhooks (`webhook-id`, `webhook-timestamp`, `webhook-signature` with the Runtime's `a2a.push.secret`) and `X-A2A-Notification-Token`, at least once, retried for up to 24 hours, to hosts the Runtime allows (`a2a.push.allowHosts` for private ones). A message to a busy context is queued and answered with the task that will take it (`TASK_STATE_SUBMITTED`); `message.metadata.delivery: \"reject\"` asks for `UnsupportedOperationError` (reason `CONTEXT_BUSY`) instead. A message is text, one data part, or text with `raw` files (stored as artifacts of the context's session) and `url` files (fetched by the Runtime), each at most the Runtime limit `inlineFileBytes` (20 MiB by default). An approval, question or connection the task waits for (`AUTH_REQUIRED` or `INPUT_REQUIRED`) is shown under `interactions/v1` and answered on the same task with `{ interactionId, approved }` or `{ interactionId, value }` under that URI in the message's `metadata`; text never approves. Artifacts carry the turn's output and the files it wrote, as `url` parts at `/v1/a2a/files/…` with `files/v1`; the task's metadata carries `progress/v1`, `telemetry/v1` and `effects/v1`. Extension data is answered only for the extensions activated with `A2A-Extensions`. A context is one session per subject, agent and `contextId`; a task is one turn. JSON-RPC errors are answered with 200; limits, scopes and unavailable streams stay HTTP errors. Not served: streaming, `GetExtendedAgentCard`.",
75
+ description: "A2A 1.0 JSON-RPC, for a subject, under the Nylorun profile v2 (Host feature `a2a-profile-v2`). `SendMessage` blocks up to the Runtime limit `a2aWaitMs` (5 minutes by default; then the task is answered still `WORKING`) unless `returnImmediately`; `GetTask` (with `historyLength`), `CancelTask` and `ListTasks`; and the four push notification config methods, plus `configuration.taskPushNotificationConfig` in `SendMessage`: each update is POSTed as one `StreamResponse`, signed with Standard Webhooks (`webhook-id`, `webhook-timestamp`, `webhook-signature` with the Runtime's `a2a.push.secret`) and `X-A2A-Notification-Token`, at least once, retried for up to 24 hours, to hosts the Runtime allows (`a2a.push.allowHosts` for private ones). A message to a busy context is queued and answered with the task that will take it (`TASK_STATE_SUBMITTED`); `message.metadata.delivery: \"reject\"` asks for `UnsupportedOperationError` (reason `CONTEXT_BUSY`) instead. `message.metadata.removeTools` (Host feature `remove-tools`) names the tools a new message's turn may not use, as a session message's `removeTools`. A message is text, one data part, or text with `raw` files (stored as artifacts of the context's session) and `url` files (fetched by the Runtime), each at most the Runtime limit `inlineFileBytes` (20 MiB by default). An approval, question or connection the task waits for (`AUTH_REQUIRED` or `INPUT_REQUIRED`) is shown under `interactions/v1` and answered on the same task with `{ interactionId, approved }` or `{ interactionId, value }` under that URI in the message's `metadata`; text never approves. Artifacts carry the turn's output and the files it wrote, as `url` parts at `/v1/a2a/files/…` with `files/v1`; the task's metadata carries `progress/v1`, `telemetry/v1` and `effects/v1`. Extension data is answered only for the extensions activated with `A2A-Extensions`. A context is one session per subject, agent and `contextId`; a task is one turn. JSON-RPC errors are answered with 200; limits, scopes and unavailable streams stay HTTP errors. Not served: streaming, `GetExtendedAgentCard`.",
76
76
  externalDocs: A2A_SPECIFICATION,
77
77
  request: {
78
78
  params: agentId,
@@ -226,6 +226,12 @@ export interface SendParams {
226
226
  push?: PushConfigInput;
227
227
  /** `metadata.delivery`; default `queue`. */
228
228
  delivery: Delivery;
229
+ /**
230
+ * `metadata.removeTools` (Host feature `remove-tools`): the tools the message's turn may not
231
+ * use, by name, as a session message's `removeTools`. A new message only: a reply answers an
232
+ * interaction of a turn already running.
233
+ */
234
+ removeTools?: readonly string[];
229
235
  /** The answer the message carries under `interactions/v1`. */
230
236
  answer?: InteractionAnswer;
231
237
  }
@@ -223,6 +223,17 @@ export function parsePushConfig(value, field) {
223
223
  ...(authentication ? { authentication } : {}),
224
224
  };
225
225
  }
226
+ /** `metadata.removeTools`: at most 256 names of 1 to 256 characters (a session message's `removeTools`). */
227
+ function parseRemoveTools(metadata) {
228
+ const value = metadata.removeTools;
229
+ if (value === undefined || value === null)
230
+ return undefined;
231
+ if (!Array.isArray(value) ||
232
+ value.length > 256 ||
233
+ !value.every((name) => typeof name === "string" && name.length >= 1 && name.length <= 256))
234
+ return a2aFail("invalidParams", "message.metadata.removeTools must be at most 256 tool names of 1 to 256 characters", {}, "message.metadata.removeTools");
235
+ return value;
236
+ }
226
237
  /** `metadata.delivery`: `queue` (the default) or `reject`. */
227
238
  function parseDelivery(metadata) {
228
239
  const delivery = metadata.delivery;
@@ -272,6 +283,7 @@ export function parseSendParams(params) {
272
283
  // On the message (the profile's place), or on the request's own metadata.
273
284
  const delivery = parseDelivery(metadata.delivery === undefined && isObject(params.metadata) ? params.metadata : metadata);
274
285
  const answer = parseAnswer(metadata);
286
+ const removeTools = parseRemoveTools(metadata.removeTools === undefined && isObject(params.metadata) ? params.metadata : metadata);
275
287
  const configuration = params.configuration;
276
288
  if (configuration !== undefined && configuration !== null && !isObject(configuration))
277
289
  a2aFail("invalidParams", "configuration must be an object", {}, "configuration");
@@ -315,6 +327,7 @@ export function parseSendParams(params) {
315
327
  ...(historyLength !== undefined ? { historyLength } : {}),
316
328
  ...(push ? { push } : {}),
317
329
  delivery,
330
+ ...(removeTools ? { removeTools } : {}),
318
331
  ...(answer ? { answer } : {}),
319
332
  };
320
333
  }
@@ -335,6 +335,7 @@ async function sendMessage(caller, params, signal) {
335
335
  requestId: randomUUID(),
336
336
  idempotencyKey,
337
337
  ...body,
338
+ ...(send.removeTools ? { removeTools: [...send.removeTools] } : {}),
338
339
  }, async () => {
339
340
  const active = (await contextSession(caller, sessionId))?.activeTurnId;
340
341
  const taskId = active ? taskIdOf(context, active) : undefined;