@nylorun/runtime 0.16.0-beta → 0.19.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 (256) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/README.md +105 -63
  3. package/dist/adapters/execution/restate.d.ts +1 -3
  4. package/dist/adapters/execution/restate.js +4 -31
  5. package/dist/adapters/replication/pgoutput.js +1 -1
  6. package/dist/adapters/sandbox/local.js +1 -1
  7. package/dist/adapters/sandbox/virtual.js +1 -1
  8. package/dist/api/ag-ui/endpoint.js +1 -2
  9. package/dist/api/ag-ui/routes.d.ts +1 -1
  10. package/dist/api/ag-ui/routes.js +11 -13
  11. package/dist/api/ag-ui/translate.d.ts +1 -3
  12. package/dist/api/ag-ui/translate.js +2 -17
  13. package/dist/api/components.d.ts +4783 -2588
  14. package/dist/api/components.js +19 -21
  15. package/dist/api/gate/routes.d.ts +7 -8
  16. package/dist/api/gate/routes.js +58 -52
  17. package/dist/api/http/app.d.ts +6 -0
  18. package/dist/api/http/app.js +20 -14
  19. package/dist/api/http/define.d.ts +22 -13
  20. package/dist/api/http/define.js +43 -39
  21. package/dist/api/http/routes/access.d.ts +3 -19
  22. package/dist/api/http/routes/access.js +25 -184
  23. package/dist/api/http/routes/artifacts.js +3 -7
  24. package/dist/api/http/routes/files.d.ts +8 -0
  25. package/dist/api/http/routes/files.js +77 -0
  26. package/dist/api/http/routes/keys.d.ts +10 -0
  27. package/dist/api/http/routes/keys.js +64 -0
  28. package/dist/api/http/routes/me.d.ts +13 -0
  29. package/dist/api/http/routes/me.js +48 -0
  30. package/dist/api/http/routes/reads.d.ts +66 -0
  31. package/dist/api/http/routes/reads.js +127 -0
  32. package/dist/api/http/routes/sandboxes.d.ts +2 -2
  33. package/dist/api/http/routes/sandboxes.js +8 -7
  34. package/dist/api/http/routes/sessions.js +31 -20
  35. package/dist/api/http/routes/tenant.js +15 -18
  36. package/dist/api/http/routes/vaults.d.ts +13 -3
  37. package/dist/api/http/routes/vaults.js +136 -64
  38. package/dist/api/openapi.d.ts +10 -11
  39. package/dist/api/openapi.js +292 -68
  40. package/dist/artifacts/links.js +6 -6
  41. package/dist/artifacts/service.js +1 -1
  42. package/dist/core/flow-host.d.ts +44 -23
  43. package/dist/core/flow-host.js +88 -106
  44. package/dist/core/provider.d.ts +4 -1
  45. package/dist/core/provider.js +6 -1
  46. package/dist/core/sandbox-routes.d.ts +0 -9
  47. package/dist/core/sandbox-routes.js +2 -21
  48. package/dist/execution/memory.d.ts +4 -5
  49. package/dist/execution/memory.js +11 -25
  50. package/dist/execution/types.d.ts +3 -33
  51. package/dist/execution/types.js +2 -12
  52. package/dist/gates/http-tool.d.ts +86 -0
  53. package/dist/gates/http-tool.js +197 -0
  54. package/dist/gates/mcp-handler.d.ts +3 -0
  55. package/dist/gates/mcp-handler.js +6 -4
  56. package/dist/gates/meter.d.ts +2 -2
  57. package/dist/gates/meter.js +6 -0
  58. package/dist/gates/tenant-vaults.d.ts +19 -14
  59. package/dist/gates/tenant-vaults.js +17 -12
  60. package/dist/gates/tool-calls.d.ts +7 -15
  61. package/dist/gates/tool-calls.js +4 -4
  62. package/dist/gates/tool-client.d.ts +1 -1
  63. package/dist/gates/tool-client.js +23 -47
  64. package/dist/gates/tool-contract.d.ts +27 -39
  65. package/dist/gates/tool-contract.js +30 -21
  66. package/dist/gates/tool-gate.d.ts +25 -24
  67. package/dist/gates/tool-gate.js +11 -7
  68. package/dist/harness/calls.d.ts +10 -4
  69. package/dist/harness/calls.js +15 -6
  70. package/dist/harness/executors.d.ts +1 -1
  71. package/dist/harness/executors.js +17 -12
  72. package/dist/harness/main.d.ts +2 -2
  73. package/dist/harness/main.js +5 -13
  74. package/dist/harness/service.d.ts +4 -5
  75. package/dist/harness/service.js +9 -2
  76. package/dist/harness-api/in-process.js +2 -2
  77. package/dist/harness-api/record.d.ts +6 -3
  78. package/dist/harness-api/record.js +65 -72
  79. package/dist/harness-api/server.d.ts +1 -9
  80. package/dist/harness-api/server.js +19 -17
  81. package/dist/harness-api/start.js +1 -5
  82. package/dist/harness-api/workspace.js +2 -3
  83. package/dist/harness-api/ws-server.js +1 -1
  84. package/dist/host/app.d.ts +2 -10
  85. package/dist/host/app.js +24 -44
  86. package/dist/host/config-for.d.ts +5 -5
  87. package/dist/host/config-for.js +2 -3
  88. package/dist/host/config.d.ts +0 -11
  89. package/dist/host/create-host.d.ts +3 -40
  90. package/dist/host/create-host.js +18 -91
  91. package/dist/host/environment.d.ts +0 -3
  92. package/dist/host/environment.js +0 -9
  93. package/dist/host/gates.d.ts +4 -1
  94. package/dist/host/gates.js +9 -3
  95. package/dist/host/http.d.ts +1 -2
  96. package/dist/host/http.js +1 -7
  97. package/dist/host/index.d.ts +2 -2
  98. package/dist/host/index.js +2 -2
  99. package/dist/host/main.js +55 -40
  100. package/dist/host/operate.d.ts +29 -0
  101. package/dist/host/operate.js +223 -0
  102. package/dist/host/stack-config.d.ts +23 -20
  103. package/dist/host/stack-config.js +28 -44
  104. package/dist/index.d.ts +4 -1
  105. package/dist/index.js +3 -1
  106. package/dist/infra/workers.d.ts +1 -1
  107. package/dist/keys/client.js +9 -1
  108. package/dist/keys/keys.d.ts +12 -2
  109. package/dist/keys/keys.js +10 -2
  110. package/dist/management-openapi.json +6491 -0
  111. package/dist/mcp/connect.d.ts +8 -4
  112. package/dist/mcp/connect.js +8 -27
  113. package/dist/mcp/pool.d.ts +6 -9
  114. package/dist/mcp/pool.js +8 -18
  115. package/dist/mcp/snapshot.d.ts +8 -2
  116. package/dist/mcp/snapshot.js +29 -2
  117. package/dist/media.d.ts +1 -1
  118. package/dist/media.js +1 -1
  119. package/dist/model/pi-model.js +3 -0
  120. package/dist/openapi.json +6228 -15615
  121. package/dist/reads/access.d.ts +4 -0
  122. package/dist/reads/access.js +12 -0
  123. package/dist/reads/cursor.d.ts +11 -0
  124. package/dist/reads/cursor.js +80 -0
  125. package/dist/reads/types.d.ts +25 -0
  126. package/dist/reads/types.js +1 -0
  127. package/dist/sandbox/manager.d.ts +16 -0
  128. package/dist/sandbox/manager.js +40 -0
  129. package/dist/sandbox/session-sandbox.js +13 -3
  130. package/dist/sandbox/skills.d.ts +13 -0
  131. package/dist/sandbox/skills.js +46 -0
  132. package/dist/sandbox/types.d.ts +2 -2
  133. package/dist/store/ownership.d.ts +9 -0
  134. package/dist/store/ownership.js +13 -0
  135. package/dist/store/postgres/connect.d.ts +2 -0
  136. package/dist/store/postgres/connect.js +29 -0
  137. package/dist/store/postgres/drizzle/0008_installation_vaults.sql +2 -0
  138. package/dist/store/postgres/drizzle/0009_oauth_pending.sql +19 -0
  139. package/dist/store/postgres/drizzle/0010_oss_auth_removals.sql +3 -0
  140. package/dist/store/postgres/drizzle/0011_key_roles.sql +3 -0
  141. package/dist/store/postgres/drizzle/0012_session_reads.sql +8 -0
  142. package/dist/store/postgres/drizzle/0013_definition_files.sql +16 -0
  143. package/dist/store/postgres/drizzle/0014_action_endpoints_removed.sql +2 -0
  144. package/dist/store/postgres/drizzle/meta/_journal.json +49 -0
  145. package/dist/store/postgres/reads.d.ts +3 -0
  146. package/dist/store/postgres/reads.js +272 -0
  147. package/dist/store/postgres/schema.d.ts +423 -594
  148. package/dist/store/postgres/schema.js +84 -101
  149. package/dist/store/postgres/store.js +96 -248
  150. package/dist/store/postgres/tenant.d.ts +34 -2
  151. package/dist/store/postgres/tenant.js +16 -32
  152. package/dist/store/types.d.ts +44 -119
  153. package/dist/store/types.js +0 -1
  154. package/dist/streams/control.d.ts +0 -7
  155. package/dist/streams/control.js +0 -13
  156. package/dist/streams/types.d.ts +2 -20
  157. package/dist/streams/types.js +1 -1
  158. package/dist/tenant/advance.d.ts +3 -3
  159. package/dist/tenant/advance.js +10 -7
  160. package/dist/tenant/auth.d.ts +24 -15
  161. package/dist/tenant/auth.js +44 -55
  162. package/dist/tenant/cause.d.ts +3 -3
  163. package/dist/tenant/cause.js +1 -1
  164. package/dist/tenant/commands.d.ts +2 -18
  165. package/dist/tenant/commands.js +38 -179
  166. package/dist/tenant/context.d.ts +33 -45
  167. package/dist/tenant/definition-files.d.ts +24 -0
  168. package/dist/tenant/definition-files.js +103 -0
  169. package/dist/tenant/effects.d.ts +20 -18
  170. package/dist/tenant/effects.js +59 -133
  171. package/dist/tenant/ephemeral.d.ts +21 -8
  172. package/dist/tenant/ephemeral.js +11 -12
  173. package/dist/tenant/host-token.js +5 -5
  174. package/dist/tenant/identity-file.d.ts +75 -0
  175. package/dist/tenant/identity-file.js +202 -0
  176. package/dist/tenant/issuers.d.ts +48 -0
  177. package/dist/tenant/issuers.js +311 -0
  178. package/dist/tenant/jwt.js +3 -3
  179. package/dist/tenant/module.d.ts +1 -4
  180. package/dist/tenant/module.js +3 -12
  181. package/dist/tenant/operator-keys.d.ts +44 -0
  182. package/dist/tenant/operator-keys.js +87 -0
  183. package/dist/tenant/outbound.d.ts +40 -1
  184. package/dist/tenant/outbound.js +167 -18
  185. package/dist/tenant/paths.d.ts +1 -1
  186. package/dist/tenant/paths.js +1 -3
  187. package/dist/tenant/principals.d.ts +13 -13
  188. package/dist/tenant/principals.js +35 -36
  189. package/dist/tenant/run-token.js +6 -6
  190. package/dist/tenant/runtime.d.ts +5 -3
  191. package/dist/tenant/runtime.js +29 -15
  192. package/dist/tenant/sandboxes.d.ts +9 -6
  193. package/dist/tenant/sandboxes.js +16 -5
  194. package/dist/tenant/scheduler.d.ts +1 -5
  195. package/dist/tenant/scheduler.js +2 -5
  196. package/dist/tenant/session-streams.d.ts +8 -11
  197. package/dist/tenant/session-streams.js +48 -32
  198. package/dist/tenant/session.d.ts +8 -41
  199. package/dist/tenant/session.js +0 -37
  200. package/dist/tenant/sessions.d.ts +2 -2
  201. package/dist/tenant/sessions.js +17 -9
  202. package/dist/tenant/signing-keys.d.ts +3 -2
  203. package/dist/tenant/signing-keys.js +5 -5
  204. package/dist/tenant/skill-tool.d.ts +20 -0
  205. package/dist/tenant/skill-tool.js +72 -0
  206. package/dist/tenant/slim.d.ts +1 -1
  207. package/dist/tenant/slim.js +1 -1
  208. package/dist/tenant/status.js +7 -12
  209. package/dist/tenant/store-pg.d.ts +15 -0
  210. package/dist/tenant/store-pg.js +7 -3
  211. package/dist/tenant/streams.d.ts +3 -11
  212. package/dist/tenant/streams.js +2 -29
  213. package/dist/tenant/sweep.js +0 -5
  214. package/dist/tenant/transcript.d.ts +2 -2
  215. package/dist/tenant/transcript.js +2 -2
  216. package/dist/tenant/types.d.ts +33 -19
  217. package/dist/tenant/worker.d.ts +1 -3
  218. package/dist/tenant/worker.js +3 -8
  219. package/dist/vault/crypto.d.ts +7 -0
  220. package/dist/vault/crypto.js +16 -0
  221. package/dist/vault/oauth.d.ts +55 -0
  222. package/dist/vault/oauth.js +186 -0
  223. package/dist/vault/service.d.ts +54 -7
  224. package/dist/vault/service.js +261 -17
  225. package/dist/vault/sources.d.ts +60 -0
  226. package/dist/vault/sources.js +196 -0
  227. package/dist/version.d.ts +1 -1
  228. package/dist/version.js +1 -1
  229. package/package.json +5 -4
  230. package/dist/admin-openapi.json +0 -604
  231. package/dist/api/http/routes/actions.d.ts +0 -8
  232. package/dist/api/http/routes/actions.js +0 -76
  233. package/dist/api/http/routes/endpoints.d.ts +0 -7
  234. package/dist/api/http/routes/endpoints.js +0 -100
  235. package/dist/host/admin-api.d.ts +0 -23
  236. package/dist/host/admin-api.js +0 -74
  237. package/dist/host/cors.d.ts +0 -27
  238. package/dist/host/cors.js +0 -64
  239. package/dist/mcp/stdio.d.ts +0 -17
  240. package/dist/mcp/stdio.js +0 -82
  241. package/dist/tenant/access-policy.d.ts +0 -30
  242. package/dist/tenant/access-policy.js +0 -52
  243. package/dist/tenant/actions.d.ts +0 -14
  244. package/dist/tenant/actions.js +0 -29
  245. package/dist/tenant/browser.d.ts +0 -15
  246. package/dist/tenant/browser.js +0 -39
  247. package/dist/tenant/delivery-token.d.ts +0 -41
  248. package/dist/tenant/delivery-token.js +0 -104
  249. package/dist/tenant/delivery.d.ts +0 -62
  250. package/dist/tenant/delivery.js +0 -481
  251. package/dist/tenant/endpoints.d.ts +0 -67
  252. package/dist/tenant/endpoints.js +0 -90
  253. package/dist/tenant/subject-limits.d.ts +0 -16
  254. package/dist/tenant/subject-limits.js +0 -45
  255. package/dist/tenant/tokens.d.ts +0 -14
  256. package/dist/tenant/tokens.js +0 -187
@@ -1,11 +1,10 @@
1
1
  /**
2
- * The Runtime's OpenAPI 3.2 documents, generated from the routes as declared for serving:
3
- *
4
- * - the Tenant API (`tenantDocument`): every Tenant route, with `/health`, `/ready` and
5
- * `/openapi.json`. Served at `GET /openapi.json`, packed as `@nylorun/runtime/openapi.json`
6
- * and attached to each release.
7
- * - the Admin API (`adminDocument`): served at `GET /v1/admin/openapi.json` behind the admin
8
- * key, packed as `@nylorun/runtime/admin-openapi.json`.
2
+ * The Runtime's two OpenAPI 3.2 documents, generated from the routes as declared for serving
3
+ * (protocol 8): the Runtime API (`runtimeDocument`: `/openapi/runtime.json`, alias
4
+ * `/openapi.json`, `@nylorun/runtime/openapi.json`) and the Management API (`managementDocument`:
5
+ * `/openapi/management.json`, `@nylorun/runtime/management-openapi.json`). Both are attached to
6
+ * each release. Each has described tags in the order a developer uses them; the Runtime API
7
+ * groups them (`x-tagGroups`).
9
8
  *
10
9
  * Event streams are `text/event-stream` with an `itemSchema` (OpenAPI 3.2). Nothing here reads
11
10
  * the environment: the same Runtime makes the same document.
@@ -13,7 +12,6 @@
13
12
  import { OpenAPIRegistry, OpenApiGeneratorV32, } from "@asteasolutions/zod-to-openapi";
14
13
  import { HOST_PROTOCOL } from "@nylorun/core/compatibility";
15
14
  import { HealthResponseSchema, ReadyResponseSchema } from "@nylorun/core/contracts";
16
- import { createAdminApi } from "../host/admin-api.js";
17
15
  import { RUNTIME_VERSION } from "../version.js";
18
16
  import { tenantApi } from "./http/app.js";
19
17
  const PROTOCOL = {
@@ -49,7 +47,7 @@ function hostRoutes() {
49
47
  path: "/ready",
50
48
  tags: ["Host"],
51
49
  summary: "Check the Runtime is ready",
52
- description: "The listeners, the Tenant (open), Postgres, Restate and S2.",
50
+ description: "The listener, the Tenant (open), Postgres, Restate and S2, and the open Tenant's harnesses.",
53
51
  responses: {
54
52
  200: {
55
53
  description: "Ready",
@@ -58,80 +56,306 @@ function hostRoutes() {
58
56
  503: { description: "Not ready: `checks` says what is not" },
59
57
  },
60
58
  });
59
+ route({
60
+ method: "get",
61
+ path: "/openapi/runtime.json",
62
+ tags: ["Host"],
63
+ summary: "Get the Runtime API's document",
64
+ description: "This document. `/openapi.json` is the same.",
65
+ responses: { 200: { description: "The Runtime API's OpenAPI document" } },
66
+ });
61
67
  route({
62
68
  method: "get",
63
69
  path: "/openapi.json",
64
70
  tags: ["Host"],
65
- summary: "Get this document",
66
- responses: { 200: { description: "The Tenant API's OpenAPI document" } },
71
+ summary: "Get the Runtime API's document (alias)",
72
+ responses: { 200: { description: "The Runtime API's OpenAPI document" } },
73
+ });
74
+ route({
75
+ method: "get",
76
+ path: "/openapi/management.json",
77
+ tags: ["Host"],
78
+ summary: "Get the Management API's document",
79
+ responses: { 200: { description: "The Management API's OpenAPI document" } },
67
80
  });
68
81
  return registry;
69
82
  }
70
83
  function tenantSchemes(registry) {
71
- registry.registerComponent("securitySchemes", "applicationKey", bearer("An application key of the Tenant, or a key derived from the admin key. With `Nylorun-Subject` and `Nylorun-Scopes`, it acts for that person, narrowed to those scopes."));
72
- registry.registerComponent("securitySchemes", "subjectToken", bearer("A subject token (`POST /v1/tokens`): one person and one role of the access policy, for at most 15 minutes.", "JWT"));
73
- registry.registerComponent("securitySchemes", "deliveryToken", bearer("The delivery token the Runtime signs each Action delivery with (`Nylorun-Signature`), sent back by the Action endpoint. It reaches only that Action's heartbeat, result and sandbox routes, while that delivery is current, for at most 15 minutes.", "JWT"));
74
- registry.registerComponent("securitySchemes", "publishableKey", {
75
- type: "apiKey",
76
- in: "header",
77
- name: "Nylorun-Key",
78
- description: "A publishable key, sent by a browser page on one of its origins. Public by design: it grants the access policy's anonymous scopes.",
79
- });
84
+ registry.registerComponent("securitySchemes", "applicationKey", bearer("An application key of the Tenant (`PUT /v1/tenant/keys/{keyId}`), or Studio's key, derived from the admin key. With `Nylorun-Subject` and `Nylorun-Scopes`, it acts for that person, narrowed to those scopes. Never accepted from a browser (`Origin`)."));
85
+ registry.registerComponent("securitySchemes", "managementKey", bearer("A management key of the Tenant (role `management`): it reaches the Management API (`/v1/tenant/*`) and `/v1/me`, as itself, never for a subject. Issued only on the Tenant's machine (`nylorun-operate keys put <id> --role management`) or from `NYLORUN_MANAGEMENT_KEY_FILE`. Never accepted from a browser (`Origin`)."));
86
+ registry.registerComponent("securitySchemes", "issuerToken", bearer("A JWT from a trusted issuer of the Host's identity file (Host feature `trusted-issuers`): one person, with the issuer's scopes, agents and sandbox grants, until it expires. Accepted from servers and browsers alike; CORS is the operator's proxy's.", "JWT"));
80
87
  }
81
- let tenant;
82
- let admin;
83
- /** The Tenant API's document. */
84
- export function tenantDocument() {
85
- if (tenant)
86
- return tenant;
88
+ const RUNTIME_TAGS = [
89
+ {
90
+ name: "Runtime",
91
+ group: "Get started",
92
+ description: "Check a Runtime is up and speaks your protocol, ask who your credential is, and read the public keys of the tokens it signs. `/health`, `/ready`, the JWKS and the documents need no key.",
93
+ operations: [
94
+ "GET /health",
95
+ "GET /ready",
96
+ "GET /v1/me",
97
+ "GET /v1/access/jwks",
98
+ "GET /openapi/runtime.json",
99
+ "GET /openapi.json",
100
+ ],
101
+ },
102
+ {
103
+ name: "Agents",
104
+ group: "Agents",
105
+ description: "The agents a Tenant can run: put a definition, list what is there. In `@nylorun/agents`.",
106
+ operations: ["PUT /v1/agents/{agentId}", "GET /v1/agents"],
107
+ },
108
+ {
109
+ name: "Definition files",
110
+ group: "Agents",
111
+ description: "The files a definition names by the SHA-256 of their bytes (each skill's folder): upload each once before putting the definition, which is refused while it names one the Runtime does not hold (`definition_files_missing`). `saveAgent` in `@nylorun/agents` does both.",
112
+ operations: ["PUT /v1/files/{file}", "HEAD /v1/files/{file}"],
113
+ },
114
+ {
115
+ name: "Sessions API",
116
+ group: "Sessions",
117
+ description: "A conversation with an agent: open a session, send commands, follow its events, read its history. In `@nylorun/agents`.",
118
+ operations: [
119
+ "PUT /v1/sessions/{sessionId}",
120
+ "GET /v1/sessions",
121
+ "GET /v1/sessions/{sessionId}",
122
+ "POST /v1/sessions/{sessionId}/commands",
123
+ "GET /v1/sessions/{sessionId}/events",
124
+ "GET /v1/sessions/{sessionId}/items",
125
+ "GET /v1/sessions/{sessionId}/manifest",
126
+ "GET /v1/sessions/{sessionId}/usage",
127
+ "GET /v1/sessions/{sessionId}/calls/model",
128
+ "POST /v1/sessions/{sessionId}/sandbox/{tool}",
129
+ ],
130
+ },
131
+ {
132
+ name: "AG-UI",
133
+ group: "Sessions",
134
+ description: "The same sessions through AG-UI: a thread is one session per person, agent and thread, and each run is a turn.",
135
+ operations: [
136
+ "POST /v1/ag-ui/agents/{agentId}",
137
+ "GET /v1/ag-ui/agents/{agentId}/threads/{threadId}/events",
138
+ "GET /v1/ag-ui/agents/{agentId}/threads/{threadId}/messages",
139
+ "POST /v1/ag-ui/agents/{agentId}/threads/{threadId}/cancel",
140
+ ],
141
+ },
142
+ {
143
+ name: "A2A",
144
+ group: "Sessions",
145
+ description: "The same sessions through Agent2Agent: a context is one session per subject, agent and `contextId`, and a task is one turn. The card is how an A2A client finds the agent.",
146
+ operations: ["GET /v1/a2a/agents/{agentId}/card", "POST /v1/a2a/agents/{agentId}"],
147
+ },
148
+ {
149
+ name: "Sandboxes",
150
+ group: "Sandboxes & artifacts",
151
+ description: "Isolated machines an agent works in: create or find one, watch its lifecycle, stop, reset or delete it. In `@nylorun/agents`.",
152
+ operations: [
153
+ "PUT /v1/sandboxes/{sandboxId}",
154
+ "GET /v1/sandboxes",
155
+ "GET /v1/sandboxes/{sandboxId}",
156
+ "GET /v1/sandboxes/{sandboxId}/events",
157
+ "POST /v1/sandboxes/{sandboxId}/stop",
158
+ "POST /v1/sandboxes/{sandboxId}/reset",
159
+ "DELETE /v1/sandboxes/{sandboxId}",
160
+ ],
161
+ },
162
+ {
163
+ name: "Artifacts",
164
+ group: "Sandboxes & artifacts",
165
+ description: "Files and folders agents and people produce, versioned, with short-lived capability links to share them. In `@nylorun/agents`.",
166
+ operations: [
167
+ "POST /v1/artifacts",
168
+ "GET /v1/artifacts",
169
+ "GET /v1/artifacts/{artifactId}",
170
+ "POST /v1/artifacts/{artifactId}/versions",
171
+ "GET /v1/artifacts/{artifactId}/versions/{version}/content",
172
+ "GET /v1/artifacts/{artifactId}/versions/{version}/tree",
173
+ "GET /v1/artifacts/{artifactId}/versions/{version}/files/{path}",
174
+ "GET /v1/artifacts/{artifactId}/versions/{version}/diff",
175
+ "GET /v1/artifacts/{artifactId}/versions/{version}/zip",
176
+ "POST /v1/artifacts/{artifactId}/links",
177
+ "GET /v1/artifact-links/{token}",
178
+ "DELETE /v1/artifacts/{artifactId}",
179
+ ],
180
+ },
181
+ ];
182
+ const MANAGEMENT_TAGS = [
183
+ {
184
+ name: "Tenant",
185
+ description: "The Tenant's status, and seeding or resetting it. `admin.tenant` in `@nylorun/admin`.",
186
+ operations: [
187
+ "GET /v1/tenant",
188
+ "PUT /v1/tenant/config/seed",
189
+ "POST /v1/tenant/reset",
190
+ "GET /v1/me",
191
+ "GET /openapi/management.json",
192
+ ],
193
+ },
194
+ {
195
+ name: "Application keys",
196
+ description: "The keys app servers call the Runtime API with: create, rotate, list and delete them. Management keys come only from the Tenant's machine. `admin.keys`.",
197
+ operations: ["GET /v1/tenant/keys", "PUT /v1/tenant/keys/{keyId}", "DELETE /v1/tenant/keys/{keyId}"],
198
+ },
199
+ {
200
+ name: "Models",
201
+ description: "Model providers, their credentials, the model the Tenant uses, what it spent, every model call for export, and the budgets that cap it. `admin.models`.",
202
+ operations: [
203
+ "GET /v1/tenant/models",
204
+ "GET /v1/tenant/providers",
205
+ "GET /v1/tenant/model",
206
+ "PUT /v1/tenant/model",
207
+ "PUT /v1/tenant/model/selection",
208
+ "GET /v1/tenant/usage",
209
+ "GET /v1/tenant/calls/model",
210
+ "GET /v1/tenant/budgets",
211
+ "PUT /v1/tenant/budgets",
212
+ ],
213
+ },
214
+ {
215
+ name: "Vaults",
216
+ description: "The installation's credentials for agents' tools: API keys and MCP OAuth connections. Sessions attach a vault by id. `admin.vaults`.",
217
+ operations: [
218
+ "POST /v1/tenant/vaults",
219
+ "GET /v1/tenant/vaults",
220
+ "GET /v1/tenant/vaults/{vaultId}",
221
+ "DELETE /v1/tenant/vaults/{vaultId}",
222
+ "POST /v1/tenant/vaults/{vaultId}/credentials",
223
+ "GET /v1/tenant/vaults/{vaultId}/credentials",
224
+ "GET /v1/tenant/vaults/{vaultId}/credentials/{credentialId}",
225
+ "POST /v1/tenant/vaults/{vaultId}/credentials/{credentialId}",
226
+ "DELETE /v1/tenant/vaults/{vaultId}/credentials/{credentialId}",
227
+ "POST /v1/tenant/vaults/{vaultId}/oauth/start",
228
+ "GET /v1/oauth/callback",
229
+ ],
230
+ },
231
+ {
232
+ name: "Signing keys",
233
+ description: "The keys the Runtime signs capability links and run tokens with; their public halves are the Runtime API's JWKS. `admin.signingKeys`.",
234
+ operations: [
235
+ "GET /v1/tenant/signing-keys",
236
+ "POST /v1/tenant/signing-keys/rotate",
237
+ "POST /v1/tenant/signing-keys/{kid}/revoke",
238
+ ],
239
+ },
240
+ {
241
+ name: "Settings",
242
+ description: "The Tenant's sandbox and artifact settings. `admin.settings`.",
243
+ operations: [
244
+ "GET /v1/tenant/sandbox",
245
+ "PUT /v1/tenant/sandbox",
246
+ "GET /v1/tenant/artifacts",
247
+ "PUT /v1/tenant/artifacts",
248
+ ],
249
+ },
250
+ ];
251
+ const METHODS = ["get", "head", "put", "post", "delete", "patch"];
252
+ const SERVERS = [
253
+ {
254
+ url: "{origin}",
255
+ description: "A Runtime: a local Tenant (`nylorun start`), or where yours runs",
256
+ variables: { origin: { default: "http://localhost:8787" } },
257
+ },
258
+ ];
259
+ /** The `#/components/schemas/…` names `value` refers to, followed through `schemas`. */
260
+ function referencedSchemas(value, schemas) {
261
+ const found = new Set();
262
+ const walk = (node) => {
263
+ if (Array.isArray(node))
264
+ return node.forEach(walk);
265
+ if (!node || typeof node !== "object")
266
+ return;
267
+ for (const [key, child] of Object.entries(node)) {
268
+ if (key === "$ref" && typeof child === "string" && child.startsWith("#/components/schemas/")) {
269
+ const name = child.slice("#/components/schemas/".length);
270
+ if (!found.has(name)) {
271
+ found.add(name);
272
+ walk(schemas[name]);
273
+ }
274
+ }
275
+ else
276
+ walk(child);
277
+ }
278
+ };
279
+ walk(value);
280
+ return found;
281
+ }
282
+ /** One reference document: `tags`' operations of `all`, in their order, with what they use. */
283
+ function document(all, tags, info) {
284
+ const paths = {};
285
+ for (const tag of tags)
286
+ for (const name of tag.operations) {
287
+ const [method, path] = name.split(" ");
288
+ const operation = all.paths?.[path]?.[method.toLowerCase()];
289
+ if (!operation)
290
+ throw new Error(`The Runtime has no operation ${name}`);
291
+ (paths[path] ??= {})[method.toLowerCase()] = { ...operation, tags: [tag.name] };
292
+ }
293
+ const schemas = (all.components?.schemas ?? {});
294
+ const used = referencedSchemas(paths, schemas);
295
+ const schemes = new Set();
296
+ for (const item of Object.values(paths))
297
+ for (const operation of Object.values(item))
298
+ for (const requirement of (operation.security ?? []))
299
+ for (const scheme of Object.keys(requirement))
300
+ schemes.add(scheme);
301
+ const groups = [...new Set(tags.flatMap((tag) => (tag.group ? [tag.group] : [])))];
302
+ return {
303
+ ...all,
304
+ info: { ...all.info, ...info },
305
+ tags: tags.map((tag) => ({ name: tag.name, description: tag.description })),
306
+ ...(groups.length
307
+ ? {
308
+ "x-tagGroups": groups.map((group) => ({
309
+ name: group,
310
+ tags: tags.filter((tag) => tag.group === group).map((tag) => tag.name),
311
+ })),
312
+ }
313
+ : {}),
314
+ paths,
315
+ components: {
316
+ ...all.components,
317
+ schemas: Object.fromEntries(Object.entries(schemas).filter(([name]) => used.has(name))),
318
+ securitySchemes: Object.fromEntries(Object.entries(all.components?.securitySchemes ?? {}).filter(([name]) => schemes.has(name))),
319
+ },
320
+ };
321
+ }
322
+ let built;
323
+ /** Both reference documents, built once from every route; throws when one is left out. */
324
+ function documents() {
325
+ if (built)
326
+ return built;
87
327
  const host = hostRoutes();
88
328
  tenantSchemes(host);
89
- tenant = new OpenApiGeneratorV32([
329
+ const all = new OpenApiGeneratorV32([
90
330
  ...host.definitions,
91
331
  ...tenantApi().openAPIRegistry.definitions,
92
332
  ]).generateDocument({
93
333
  openapi: "3.2.0",
94
- info: {
95
- title: "Nylorun Runtime: Tenant API",
96
- version: RUNTIME_VERSION,
97
- description: "Agents, sessions and their events, vaults, access and the Tenant's settings. A Runtime serves one Tenant: its URL is the Tenant's, and no request names it. Every request sends `Nylorun-Protocol`. Who may call each operation is its `security` and its `x-nylorun-credentials`, `x-nylorun-scopes` (the subject scopes that reach it) and `x-nylorun-browser` fields.",
98
- "x-nylorun-protocol": PROTOCOL,
99
- },
100
- servers: [
101
- {
102
- url: "{origin}",
103
- description: "A Runtime: a local Tenant (`nylorun start`), or where yours runs",
104
- variables: { origin: { default: "http://localhost:8787" } },
105
- },
106
- ],
334
+ info: { title: "Nylorun Runtime", version: RUNTIME_VERSION, "x-nylorun-protocol": PROTOCOL },
335
+ servers: SERVERS,
107
336
  });
108
- return tenant;
337
+ const listed = new Set([...RUNTIME_TAGS, ...MANAGEMENT_TAGS].flatMap((tag) => tag.operations));
338
+ for (const [path, item] of Object.entries(all.paths ?? {}))
339
+ for (const method of METHODS)
340
+ if (item[method] && !listed.has(`${method.toUpperCase()} ${path}`))
341
+ throw new Error(`${method.toUpperCase()} ${path} is in no reference tag (api/openapi.ts)`);
342
+ built = {
343
+ runtime: document(all, RUNTIME_TAGS, {
344
+ title: "Nylorun Runtime API",
345
+ description: "For developers: agents, sessions (with AG-UI and A2A), sandboxes and artifacts, through `@nylorun/agents`. Every Tenant serves it on its one URL, beside the Management API (`/openapi/management.json`). Every request sends `Nylorun-Protocol`. Who may call each operation is its `security` and its `x-nylorun-credentials` and `x-nylorun-scopes` (the subject scopes that reach it) fields: an application key (servers) or a trusted issuer's token (browsers and apps).",
346
+ }),
347
+ management: document(all, MANAGEMENT_TAGS, {
348
+ title: "Nylorun Management API",
349
+ description: "For operators: the Tenant's models, vaults, signing keys, settings and application keys, at `/v1/tenant/*` on the Tenant's URL, through `@nylorun/admin`. Every operation takes a management key, acting as itself: never for a subject and never from a browser. Management keys are issued only on the Tenant's machine (`nylorun key put <id> --management`) or from `NYLORUN_MANAGEMENT_KEY_FILE`.",
350
+ }),
351
+ };
352
+ return built;
109
353
  }
110
- /** The Admin API's document. */
111
- export function adminDocument() {
112
- if (admin)
113
- return admin;
114
- // Only the routes' declarations are read: nothing is served from this app.
115
- const api = createAdminApi({
116
- status: () => Promise.reject(new Error("Not served")),
117
- shutdown: () => { },
118
- });
119
- api.openAPIRegistry.registerComponent("securitySchemes", "adminKey", bearer("The Host's admin key (`host-credentials.json`). Never a Tenant bearer."));
120
- admin = new OpenApiGeneratorV32(api.openAPIRegistry.definitions).generateDocument({
121
- openapi: "3.2.0",
122
- info: {
123
- title: "Nylorun Runtime: Admin API",
124
- version: RUNTIME_VERSION,
125
- description: "The Host's status, its Tenant's state and shutdown, with the admin key. Served on the operator listener when the Host has one; the public listener answers these routes with the opaque 404.",
126
- "x-nylorun-protocol": PROTOCOL,
127
- },
128
- servers: [
129
- {
130
- url: "{origin}",
131
- description: "The operator listener: a local Tenant's, or where yours runs",
132
- variables: { origin: { default: "http://localhost:8788" } },
133
- },
134
- ],
135
- });
136
- return admin;
354
+ /** The Runtime API's document: `/openapi/runtime.json` and `/openapi.json`. */
355
+ export function runtimeDocument() {
356
+ return documents().runtime;
357
+ }
358
+ /** The Management API's document: `/openapi/management.json`. */
359
+ export function managementDocument() {
360
+ return documents().management;
137
361
  }
@@ -2,14 +2,14 @@
2
2
  * Capability links (protocol 6): a short-lived URL that opens one artifact version with no
3
3
  * other credential, for UIs, `<img>` tags and sharing. The token in the path is an ES256 JWT
4
4
  * (`typ: nylorun-artifact+jwt`) signed with the Tenant's current signing key by the keys
5
- * service, like subject and delivery tokens: `sub` is the artifact, `ver` the version, `aud`
6
- * `nylorun-artifact`, and it lives at most `ARTIFACT_LINK_MAX_TTL_SECONDS` (the subject-token
7
- * maximum, so a key rotation never revokes a live link). A link opens nothing once its artifact
5
+ * service, like run tokens: `sub` is the artifact, `ver` the version, `aud`
6
+ * `nylorun-artifact`, and it lives at most `ARTIFACT_LINK_MAX_TTL_SECONDS` (`TOKEN_TTL_MAX_SECONDS`,
7
+ * so a key rotation never revokes a live link). A link opens nothing once its artifact
8
8
  * is deleted. A folder's link (F8.2) opens its zip, or with a `path` claim one of its files.
9
9
  */
10
10
  import { randomUUID } from "node:crypto";
11
11
  import { errors, jwtVerify } from "jose";
12
- import { ARTIFACT_LINK_DEFAULT_TTL_SECONDS, ARTIFACT_LINK_MAX_TTL_SECONDS, ARTIFACT_LINK_TOKEN_TYPE, subjectTokenIssuer, } from "@nylorun/core/contracts";
12
+ import { ARTIFACT_LINK_DEFAULT_TTL_SECONDS, ARTIFACT_LINK_MAX_TTL_SECONDS, ARTIFACT_LINK_TOKEN_TYPE, tenantTokenIssuer, } from "@nylorun/core/contracts";
13
13
  import { isArtifactId } from "@nylorun/core/compatibility";
14
14
  import { failOpaque, HttpError } from "../tenant/http.js";
15
15
  import { CLOCK_TOLERANCE_SECONDS, tokenKeyId } from "../tenant/jwt.js";
@@ -24,7 +24,7 @@ export async function mintArtifactLink(ctx, link) {
24
24
  const { token } = await ctx.keys.sign({
25
25
  typ: ARTIFACT_LINK_TOKEN_TYPE,
26
26
  claims: {
27
- iss: subjectTokenIssuer(ctx.config.tenantId),
27
+ iss: tenantTokenIssuer(ctx.config.tenantId),
28
28
  aud: ARTIFACT_LINK_AUDIENCE,
29
29
  sub: link.artifactId,
30
30
  ver: link.version,
@@ -57,7 +57,7 @@ export async function verifyArtifactLink(ctx, raw) {
57
57
  try {
58
58
  const verified = await jwtVerify(raw, await ctx.signingKeys.publicKey(row), {
59
59
  algorithms: ["ES256"],
60
- issuer: subjectTokenIssuer(ctx.config.tenantId),
60
+ issuer: tenantTokenIssuer(ctx.config.tenantId),
61
61
  audience: ARTIFACT_LINK_AUDIENCE,
62
62
  typ: ARTIFACT_LINK_TOKEN_TYPE,
63
63
  clockTolerance: CLOCK_TOLERANCE_SECONDS,
@@ -11,7 +11,7 @@
11
11
  * module, after re-checking the Tenant total under the quota lock. Until it commits the object
12
12
  * is garbage, and a failed commit deletes it.
13
13
  * - **Access mirrors sessions.** An application principal reaches every artifact. A request acting
14
- * for a person (a subject token or subject headers) reaches only artifacts of that person's
14
+ * for a person (a trusted issuer's token or subject headers) reaches only artifacts of that person's
15
15
  * sessions; another person's, or a Tenant-wide one, is the same 404 as a missing artifact.
16
16
  *
17
17
  * Lock order, the same in every write: the session, then the quota lock, then the artifact row.
@@ -1,5 +1,5 @@
1
- import type { ActionOutcome } from "@nylorun/core/contracts";
2
- import type { JsonValue, WorkflowManifest } from "@nylorun/core/define";
1
+ import type { EffectOutcome } from "@nylorun/core/contracts";
2
+ import { type JsonValue, type WorkflowManifest } from "@nylorun/core/define";
3
3
  import type { HostEffect } from "@nylorun/harness/run";
4
4
  import type { Wake } from "../execution/types.js";
5
5
  import type { EffectDoc, Tx } from "../store/types.js";
@@ -20,6 +20,31 @@ export declare function isWorkflowManifest(manifest: unknown): manifest is Workf
20
20
  /** Flow tool-node effect: `tool` with path/key and no agent capabilityId. */
21
21
  export declare function isFlowToolEffect(request: HostEffect): boolean;
22
22
  export declare function isFlowEffect(request: HostEffect): boolean;
23
+ /**
24
+ * What a flow `agent` effect sends its linked session (D12): the stage's input, and, when the
25
+ * engine sent the flow's own input beside it, that input first as the original request. Pure,
26
+ * so a replayed effect sends the same message.
27
+ */
28
+ export declare function linkedMessageInput(body: {
29
+ readonly input: JsonValue;
30
+ readonly flowInput?: JsonValue;
31
+ }): JsonValue;
32
+ /**
33
+ * Settle a flow `agent` effect with its linked turn's outcome, in the caller's transaction,
34
+ * which holds the workflow session's lock. A verifier agent's verdict is recorded as
35
+ * `loop.verified`; an outcome that is not a verdict fails the Loop in the engine instead.
36
+ */
37
+ export declare function settleAgentEffect(input: {
38
+ readonly t: Tx;
39
+ readonly effect: FlowEffect;
40
+ readonly outcome: EffectOutcome;
41
+ }): Promise<void>;
42
+ /**
43
+ * Record a Loop verifier's verdict as `loop.verified`: a verifier agent's output, or an HTTP
44
+ * verifier's answer (`role: "verify-http"`, a completed HTTP outcome). Anything that is not a
45
+ * verdict records nothing; the engine fails the Loop on it.
46
+ */
47
+ export declare function recordVerdict(t: Tx, request: HostEffect, value: unknown): Promise<void>;
23
48
  export type FlowLink = {
24
49
  readonly workflowSessionId: string;
25
50
  readonly path: string;
@@ -60,30 +85,28 @@ export type FlowWait = {
60
85
  readonly path: string;
61
86
  readonly interactionId: string;
62
87
  readonly kind: string;
88
+ /** The interaction as asked (`prompt`, `metadata`), when the wait records it. */
89
+ readonly interaction?: unknown;
63
90
  readonly invocationId?: string;
64
91
  readonly wait?: unknown;
65
92
  readonly status?: string;
66
93
  };
67
94
  export type CancelSiblingResult = {
68
- readonly cancelledActions: string[];
69
- readonly uncertainActions: string[];
70
95
  readonly agentSessionIds: string[];
71
96
  };
72
97
  export type CascadeCancelPlan = {
73
98
  /** Linked agent sessions to cancel, deepest path first. */
74
99
  readonly agentSessionIds: string[];
75
- readonly pendingActionIds: string[];
76
- readonly deliveringActionIds: string[];
77
100
  };
78
101
  /** Wakes a session after commit (`DurableExecution.wake` through the Tenant context). */
79
102
  type Schedule = (sessionId: string, wake: Wake) => void | Promise<void>;
80
103
  /** Effect documents as the flow host writes them. */
81
104
  export type FlowEffect = EffectDoc & {
82
105
  agentSessionId?: string;
83
- outcome?: ActionOutcome;
106
+ outcome?: EffectOutcome;
84
107
  error?: string;
85
108
  };
86
- /** Active agent turns + pending/delivering actions for one workflow turn. */
109
+ /** Active agent turns + tool nodes in flight for one workflow turn. */
87
110
  export declare function countActiveFlowWork(t: Tx, workflowSessionId: string, turnId: string): Promise<number>;
88
111
  /** The `commands` document key of a session command's idempotency key (`tenant/commands.ts`). */
89
112
  export declare function commandKey(sessionId: string, idempotencyKey: string): string;
@@ -134,10 +157,7 @@ export declare function reconcilePendingAgentEffect(input: {
134
157
  }): Promise<boolean>;
135
158
  /** Path depth for deepest-first cancel ordering. */
136
159
  export declare function pathDepth(path: string): number;
137
- /**
138
- * Plan a cancel cascade for a workflow session: linked agents deepest first,
139
- * then pending → cancelled and delivering → uncertain actions (SD-P11 / WF-R53).
140
- */
160
+ /** Plan a cancel cascade for a workflow session: linked agents deepest first (SD-P11 / WF-R53). */
141
161
  export declare function planCancelCascade(input: {
142
162
  readonly t: Tx;
143
163
  readonly workflowSessionId: string;
@@ -145,8 +165,7 @@ export declare function planCancelCascade(input: {
145
165
  }): Promise<CascadeCancelPlan>;
146
166
  /**
147
167
  * Cancel sibling work under a Parallel/Map parent when one branch fails (PAR-R6).
148
- * Agent turns listed in `agentSessionIds` are returned for the caller to cancel;
149
- * pending actions → cancelled, delivering tool actions → uncertain.
168
+ * Agent turns listed in `agentSessionIds` are returned for the caller to cancel.
150
169
  * When `cancelEffectIds` is provided, those effects are marked cancelled and their
151
170
  * paths are included in the sibling path set.
152
171
  */
@@ -159,18 +178,12 @@ export declare function cancelSiblingWork(input: {
159
178
  /** Effect ids the flow engine marked for fail-fast cancel. */
160
179
  readonly cancelEffectIds?: readonly string[];
161
180
  }): Promise<CancelSiblingResult>;
162
- /**
163
- * Apply cancel fencing to workflow-session actions (pending→cancelled,
164
- * delivering→uncertain).
165
- */
166
- export declare function fenceWorkflowActions(input: {
181
+ /** Cancel a cancelled workflow turn's queued effects, which never started. */
182
+ export declare function cancelQueuedEffects(input: {
167
183
  readonly t: Tx;
168
184
  readonly workflowSessionId: string;
169
185
  readonly turnId: string | null;
170
- }): Promise<{
171
- cancelled: string[];
172
- uncertain: string[];
173
- }>;
186
+ }): Promise<string[]>;
174
187
  /**
175
188
  * Aggregate human waits across the workflow session and linked agent sessions (WF-R51).
176
189
  */
@@ -178,6 +191,14 @@ export declare function aggregateWaits(input: {
178
191
  readonly t: Tx;
179
192
  readonly workflowSessionId: string;
180
193
  }): Promise<FlowWait[]>;
194
+ /**
195
+ * The workflow-owned interaction `interactionId` among a workflow's `waits` (a tool node that
196
+ * asked), or undefined.
197
+ */
198
+ export declare function flowInteractionOf(raw: unknown, workflowSessionId: string, interactionId: string): {
199
+ readonly id: string;
200
+ readonly kind: string;
201
+ } | undefined;
181
202
  /**
182
203
  * Look up which session owns an interaction id. Used for 409 foreign approvals (WF-R52).
183
204
  */