@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,100 +0,0 @@
1
- import { z } from "zod";
2
- import { PutEndpointsRequestSchema } from "@nylorun/core/contracts";
3
- import { DeleteEndpointResponse, EndpointPingResponse, ListEndpointsResponse, PutEndpointsRequest, } from "../../components.js";
4
- import { ActionOutcomeSchema } from "@nylorun/core/contracts";
5
- import { ActionOutcome, ActionResultReceipt } from "../../components.js";
6
- import { deliveryResult, pingEndpoint } from "../../../tenant/delivery.js";
7
- import { requireApplication } from "../../../tenant/auth.js";
8
- import { fail } from "../../../tenant/http.js";
9
- import { deleteEndpoint, listEndpoints, putEndpoints, } from "../../../tenant/endpoints.js";
10
- import { readJson } from "../body.js";
11
- import { tenantRoute } from "../define.js";
12
- import { jsonResponse } from "../respond.js";
13
- const APPLICATION = { credentials: ["application"], scopes: "never" };
14
- const json = (schema, description) => ({
15
- description,
16
- content: { "application/json": { schema } },
17
- });
18
- export function endpointRoutes(api) {
19
- tenantRoute(api, APPLICATION, {
20
- method: "get",
21
- path: "/v1/endpoints",
22
- tags: ["Action endpoints"],
23
- summary: "List Action endpoints",
24
- description: "Each agent's Action endpoint, with what recent deliveries say about it.",
25
- responses: { 200: json(ListEndpointsResponse, "The endpoints") },
26
- }, async (c) => {
27
- requireApplication(c.get("scope"));
28
- return jsonResponse(200, await listEndpoints(c.env.tenant));
29
- });
30
- tenantRoute(api, APPLICATION, {
31
- method: "put",
32
- path: "/v1/endpoints",
33
- tags: ["Action endpoints"],
34
- summary: "Register Action endpoints",
35
- description: "Points the Runtime at the URL that runs each agent's Actions. A new URL starts with no " +
36
- "health.",
37
- request: {
38
- body: { required: true, content: { "application/json": { schema: PutEndpointsRequest } } },
39
- },
40
- responses: { 200: json(ListEndpointsResponse, "The registered endpoints") },
41
- }, async (c) => {
42
- const principalId = requireApplication(c.get("scope"));
43
- return jsonResponse(200, await putEndpoints(c.env.tenant, principalId, PutEndpointsRequestSchema.parse(await readJson(c.req.raw))));
44
- });
45
- tenantRoute(api, APPLICATION, {
46
- method: "delete",
47
- path: "/v1/endpoints/{agentId}",
48
- tags: ["Action endpoints"],
49
- summary: "Remove an agent's Action endpoint",
50
- description: "The agent's pending Actions wait until an endpoint is registered again.",
51
- request: { params: z.object({ agentId: z.string() }) },
52
- responses: {
53
- 200: json(DeleteEndpointResponse, "The endpoint was removed"),
54
- 404: { description: "The agent has no endpoint" },
55
- },
56
- }, async (c) => {
57
- requireApplication(c.get("scope"));
58
- return jsonResponse(200, await deleteEndpoint(c.env.tenant, c.req.param("agentId")));
59
- });
60
- tenantRoute(api, APPLICATION, {
61
- method: "post",
62
- path: "/v1/endpoints/{agentId}/ping",
63
- tags: ["Action endpoints"],
64
- summary: "Ping an agent's Action endpoint",
65
- description: "Sends a signed ping through the endpoint and records what it answers it serves. A " +
66
- "wrong URL, a tunnel that is down or a handler that does not serve the agent answers 502.",
67
- request: { params: z.object({ agentId: z.string() }) },
68
- responses: {
69
- 200: json(EndpointPingResponse, "What the endpoint serves"),
70
- 404: { description: "The agent has no endpoint" },
71
- 502: { description: "The endpoint did not answer the ping" },
72
- },
73
- }, async (c) => {
74
- requireApplication(c.get("scope"));
75
- return jsonResponse(200, await pingEndpoint(c.env.tenant, c.req.param("agentId")));
76
- });
77
- tenantRoute(api, { credentials: ["delivery"], scopes: "never" }, {
78
- method: "post",
79
- path: "/v1/actions/{actionId}/result",
80
- tags: ["Action endpoints"],
81
- summary: "Post the outcome of an Action answered with 202",
82
- description: "Called by an Action endpoint with the Action's delivery token after it answered the " +
83
- "delivery with 202. The same result again returns the first receipt.",
84
- request: {
85
- params: z.object({ actionId: z.string() }),
86
- body: { required: true, content: { "application/json": { schema: ActionOutcome } } },
87
- },
88
- responses: {
89
- 200: json(ActionResultReceipt, "The outcome was recorded"),
90
- 409: {
91
- description: "The delivery was cancelled, lost or sent again, or the Action has another result",
92
- },
93
- },
94
- }, async (c) => {
95
- const scope = c.get("scope");
96
- if (scope.kind !== "delivery")
97
- return fail(403, "A delivery token is required");
98
- return jsonResponse(200, await deliveryResult(c.env.tenant, scope, c.req.param("actionId"), ActionOutcomeSchema.parse(await readJson(c.req.raw))));
99
- });
100
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * The Admin API (`/v1/admin/**`): the Host's status and shutdown, for a caller with the admin
3
- * key. A Host serves one Tenant, so there are no Tenant routes: the status names the Tenant
4
- * and, when it could not be opened, why (tenancy.md §9). The Host checks the listener, the
5
- * protocol and the admin key first (`app.ts`); what gets here is authorized. Routes are
6
- * declared once, for serving and for the OpenAPI document.
7
- */
8
- import { OpenAPIHono } from "@hono/zod-openapi";
9
- import type { AdminStatus } from "@nylorun/core/contracts";
10
- import type { NodeBindings } from "../tenant/types.js";
11
- export interface AdminApiOptions {
12
- /** `GET /v1/admin/status`. */
13
- status(): Promise<AdminStatus>;
14
- /** Stops the Host once the shutdown answer is sent. */
15
- shutdown(): void;
16
- /** `GET /v1/admin/openapi.json`: this API's OpenAPI document (`api/openapi.ts`). */
17
- document?(): unknown;
18
- }
19
- type AdminEnv = {
20
- Bindings: NodeBindings;
21
- };
22
- export declare function createAdminApi(options: AdminApiOptions): OpenAPIHono<AdminEnv>;
23
- export {};
@@ -1,74 +0,0 @@
1
- /**
2
- * The Admin API (`/v1/admin/**`): the Host's status and shutdown, for a caller with the admin
3
- * key. A Host serves one Tenant, so there are no Tenant routes: the status names the Tenant
4
- * and, when it could not be opened, why (tenancy.md §9). The Host checks the listener, the
5
- * protocol and the admin key first (`app.ts`); what gets here is authorized. Routes are
6
- * declared once, for serving and for the OpenAPI document.
7
- */
8
- import { OpenAPIHono } from "@hono/zod-openapi";
9
- import { z } from "zod";
10
- import { AdminStatus as AdminStatusBody, HostShutdownResponse, ProtocolRejected, Rejected, } from "../api/components.js";
11
- import { serveRoute } from "../api/route.js";
12
- import { jsonResponse, rejectedResponse } from "./http.js";
13
- const json = (schema, description) => ({
14
- description,
15
- content: { "application/json": { schema } },
16
- });
17
- const rejected = (description) => json(Rejected, description);
18
- /** What every Admin route may answer before its own logic runs. */
19
- const gated = {
20
- 404: rejected("Not found: an unknown admin key, or the public listener"),
21
- 426: json(ProtocolRejected, "`Nylorun-Protocol` missing or unsupported"),
22
- };
23
- function adminRoute(route) {
24
- return {
25
- ...route,
26
- tags: ["Admin"],
27
- security: [{ adminKey: [] }],
28
- responses: { ...gated, ...route.responses },
29
- };
30
- }
31
- export function createAdminApi(options) {
32
- const api = new OpenAPIHono();
33
- // HEAD is not a GET here: an Admin route answers only the methods it declares.
34
- api.use(async (c, next) => {
35
- if (c.req.method === "HEAD")
36
- return notFound();
37
- await next();
38
- });
39
- // D12: `/v1/admin/status` and `/v1/admin/host` are one answer.
40
- for (const path of ["/v1/admin/status", "/v1/admin/host"])
41
- serveRoute(api, adminRoute({
42
- method: "get",
43
- path,
44
- summary: path.endsWith("host") ? "Get the Host's status (alias)" : "Get the Host's status",
45
- responses: { 200: json(AdminStatusBody, "Version, protocol, the Tenant and the Host") },
46
- }), async () => jsonResponse(200, await options.status()));
47
- serveRoute(api, adminRoute({
48
- method: "post",
49
- path: "/v1/admin/host/shutdown",
50
- summary: "Shut the Host down",
51
- description: "Answers, then stops the Host. Served by a self-hosted Runtime only.",
52
- responses: { 200: json(HostShutdownResponse, "The Host is stopping") },
53
- }), (c) => {
54
- c.env.outgoing.once("finish", () => options.shutdown());
55
- return jsonResponse(200, { status: "shutting_down" });
56
- });
57
- serveRoute(api, adminRoute({
58
- method: "get",
59
- path: "/v1/admin/openapi.json",
60
- summary: "Get this document",
61
- responses: { 200: { description: "The Admin API's OpenAPI document" } },
62
- }), () => options.document
63
- ? jsonResponse(200, options.document(), { "cache-control": "no-cache" })
64
- : notFound());
65
- api.notFound(() => notFound());
66
- // The Host answers what a route throws (`app.ts`), as it did before Hono.
67
- api.onError((error) => {
68
- throw error;
69
- });
70
- return api;
71
- }
72
- function notFound() {
73
- return rejectedResponse(404, "not_found", "Route not found");
74
- }
@@ -1,27 +0,0 @@
1
- /**
2
- * Browser access at the Host (Host feature `browser-access`). A preflight carries no
3
- * credentials and no header values, so it cannot name a Tenant: the Host answers it from the
4
- * route alone, permissively for browser routes, and the Tenant enforces the publishable key's
5
- * origin allowlist on the actual request (`tenant/browser.ts`). A cached preflight therefore
6
- * never widens access, and it grants no credentials.
7
- */
8
- import type { IncomingMessage, ServerResponse } from "node:http";
9
- /** Request headers a browser may send to the Runtime. */
10
- export declare const BROWSER_REQUEST_HEADERS: readonly ["authorization", "content-type", "nylorun-key", "nylorun-tenant", "nylorun-protocol", "last-event-id"];
11
- /**
12
- * Tenant routes a browser may call: agents (list), sessions (not the sandbox tool route),
13
- * vaults, AG-UI and the JWKS. Tokens, access management, endpoints, actions and Tenant
14
- * settings never are.
15
- */
16
- /** The `Origin` header if it is a serialized origin (not `null`, not a path). */
17
- export declare function browserOrigin(request: IncomingMessage): string | undefined;
18
- /**
19
- * Answers a CORS preflight: `204` with the allowed methods and headers for a browser route,
20
- * `403` without any CORS header otherwise.
21
- */
22
- export declare function answerPreflight(request: IncomingMessage, response: ServerResponse, segments: readonly string[], isBrowserRoute: (method: string, segments: readonly string[]) => boolean): number;
23
- /**
24
- * CORS headers for an actual request from an allowed origin; set once with `setHeader`, so
25
- * every response that follows (JSON, errors, SSE) carries them.
26
- */
27
- export declare function setCorsHeaders(response: ServerResponse, origin: string): void;
package/dist/host/cors.js DELETED
@@ -1,64 +0,0 @@
1
- import { isSerializedOrigin } from "@nylorun/core/contracts";
2
- /** Request headers a browser may send to the Runtime. */
3
- export const BROWSER_REQUEST_HEADERS = [
4
- "authorization",
5
- "content-type",
6
- "nylorun-key",
7
- "nylorun-tenant",
8
- "nylorun-protocol",
9
- "last-event-id",
10
- ];
11
- const BROWSER_METHODS = ["GET", "POST", "PUT", "DELETE"];
12
- const PREFLIGHT_MAX_AGE_SECONDS = 600;
13
- /**
14
- * Tenant routes a browser may call: agents (list), sessions (not the sandbox tool route),
15
- * vaults, AG-UI and the JWKS. Tokens, access management, endpoints, actions and Tenant
16
- * settings never are.
17
- */
18
- /** The `Origin` header if it is a serialized origin (not `null`, not a path). */
19
- export function browserOrigin(request) {
20
- const raw = request.headers.origin;
21
- const origin = Array.isArray(raw) ? raw[0] : raw;
22
- return origin !== undefined && isSerializedOrigin(origin) ? origin : undefined;
23
- }
24
- /**
25
- * Answers a CORS preflight: `204` with the allowed methods and headers for a browser route,
26
- * `403` without any CORS header otherwise.
27
- */
28
- export function answerPreflight(request, response, segments, isBrowserRoute) {
29
- const origin = browserOrigin(request);
30
- const method = String(request.headers["access-control-request-method"] ?? "").toUpperCase();
31
- const requested = String(request.headers["access-control-request-headers"] ?? "")
32
- .split(",")
33
- .map((name) => name.trim().toLowerCase())
34
- .filter(Boolean);
35
- const allowed = origin !== undefined &&
36
- BROWSER_METHODS.includes(method) &&
37
- isBrowserRoute(method, segments) &&
38
- requested.every((name) => BROWSER_REQUEST_HEADERS.includes(name));
39
- if (!allowed) {
40
- response.writeHead(403, { "content-length": "0" });
41
- response.end();
42
- return 403;
43
- }
44
- response.writeHead(204, {
45
- "access-control-allow-origin": origin,
46
- "access-control-allow-methods": BROWSER_METHODS.join(", "),
47
- "access-control-allow-headers": requested.join(", "),
48
- "access-control-max-age": String(PREFLIGHT_MAX_AGE_SECONDS),
49
- vary: "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
50
- "content-length": "0",
51
- });
52
- response.end();
53
- return 204;
54
- }
55
- /**
56
- * CORS headers for an actual request from an allowed origin; set once with `setHeader`, so
57
- * every response that follows (JSON, errors, SSE) carries them.
58
- */
59
- export function setCorsHeaders(response, origin) {
60
- response.setHeader("access-control-allow-origin", origin);
61
- response.setHeader("vary", "Origin");
62
- response.setHeader("access-control-expose-headers", "retry-after, www-authenticate");
63
- response.setHeader("cache-control", "no-store");
64
- }
@@ -1,17 +0,0 @@
1
- import type { McpServerManifest } from "@nylorun/core/define";
2
- /** Single-pass replacement. Text inserted for a token is not scanned again. */
3
- export declare function expandPluginPlaceholders(value: string, pluginRoot: string, pluginData: string): string;
4
- export interface StdioLaunch {
5
- readonly command: string;
6
- readonly args: readonly string[];
7
- readonly cwd: string;
8
- readonly env: Readonly<Record<string, string>>;
9
- }
10
- export declare function prepareStdioLaunch(server: Extract<McpServerManifest, {
11
- type: "stdio";
12
- }>, options: {
13
- readonly pluginRoot?: string;
14
- readonly pluginData: string;
15
- /** Allowlisted base env (Tenant HOME/TMPDIR/PATH). Manifest env overlays it (A9). */
16
- readonly childEnv?: Readonly<Record<string, string>>;
17
- }): StdioLaunch;
package/dist/mcp/stdio.js DELETED
@@ -1,82 +0,0 @@
1
- import { mkdirSync } from "node:fs";
2
- import { isAbsolute, relative, resolve, sep } from "node:path";
3
- const ROOT_TOKEN = "${PLUGIN_ROOT}";
4
- const DATA_TOKEN = "${PLUGIN_DATA}";
5
- /** Single-pass replacement. Text inserted for a token is not scanned again. */
6
- export function expandPluginPlaceholders(value, pluginRoot, pluginData) {
7
- let out = "";
8
- for (let index = 0; index < value.length;) {
9
- if (value.startsWith(ROOT_TOKEN, index)) {
10
- out += pluginRoot;
11
- index += ROOT_TOKEN.length;
12
- continue;
13
- }
14
- if (value.startsWith(DATA_TOKEN, index)) {
15
- out += pluginData;
16
- index += DATA_TOKEN.length;
17
- continue;
18
- }
19
- out += value[index];
20
- index += 1;
21
- }
22
- return out;
23
- }
24
- export function prepareStdioLaunch(server, options) {
25
- const pluginData = options.pluginData;
26
- mkdirSync(pluginData, { recursive: true });
27
- const pluginRoot = options.pluginRoot;
28
- if (needsPluginRoot(server) && !pluginRoot)
29
- throw new Error("stdio server requires a plugin root");
30
- for (const key of Object.keys(server.env ?? {})) {
31
- if (key === "PLUGIN_ROOT" || key === "PLUGIN_DATA")
32
- throw new Error(`stdio env must not set ${key}`);
33
- }
34
- const command = server.command.startsWith("./")
35
- ? resolve(pluginRoot, server.command)
36
- : server.command;
37
- const args = (server.args ?? []).map((arg) => expand(arg, pluginRoot, pluginData));
38
- const cwd = server.cwd
39
- ? resolveContainedCwd(server.cwd, pluginRoot, pluginData)
40
- : (pluginRoot ?? pluginData);
41
- // childEnv under manifest env; HOME/TMPDIR from childEnv override Host defaults
42
- // that StdioClientTransport merges via getDefaultEnvironment() (R2).
43
- const env = { ...(options.childEnv ?? {}) };
44
- for (const [key, value] of Object.entries(server.env ?? {}))
45
- env[key] = expand(value, pluginRoot, pluginData);
46
- if (pluginRoot)
47
- env.PLUGIN_ROOT = pluginRoot;
48
- env.PLUGIN_DATA = pluginData;
49
- return { command, args, cwd, env };
50
- }
51
- function needsPluginRoot(server) {
52
- if (server.command.startsWith("./"))
53
- return true;
54
- const values = [
55
- ...(server.args ?? []),
56
- ...Object.values(server.env ?? {}),
57
- ...(server.cwd === undefined ? [] : [server.cwd]),
58
- ];
59
- return values.some((value) => value.includes(ROOT_TOKEN));
60
- }
61
- function expand(value, pluginRoot, pluginData) {
62
- if (value.includes(ROOT_TOKEN) && !pluginRoot)
63
- throw new Error("stdio server requires a plugin root");
64
- return expandPluginPlaceholders(value, pluginRoot ?? "", pluginData);
65
- }
66
- function resolveContainedCwd(cwd, pluginRoot, pluginData) {
67
- const expanded = expand(cwd, pluginRoot, pluginData);
68
- const base = cwdTargetsData(cwd) ? pluginData : pluginRoot;
69
- if (!base)
70
- throw new Error("stdio server requires a plugin root");
71
- const absolute = isAbsolute(expanded) ? expanded : resolve(base, expanded);
72
- if (!isInside(base, absolute))
73
- throw new Error(`Working directory escapes ${base}`);
74
- return absolute;
75
- }
76
- function cwdTargetsData(cwd) {
77
- return cwd === DATA_TOKEN || cwd.startsWith(`${DATA_TOKEN}/`);
78
- }
79
- function isInside(root, target) {
80
- const rel = relative(root, target);
81
- return rel === "" || (!rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel));
82
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * The Tenant's access policy (Host feature `subject-tokens`): the roles subject tokens are
3
- * minted for, what a publishable key grants alone (`anon`), and how long tokens live. One
4
- * validated JSON document in the Tenant settings; a Tenant that never set one has no roles,
5
- * so nothing can be minted.
6
- *
7
- * A token's permissions are resolved from the policy on every request, so editing a role
8
- * changes outstanding tokens at their next request and removing one ends them.
9
- */
10
- import { type AccessPolicy, type RoleLimits, type TokenScope } from "@nylorun/core/contracts";
11
- import type { Tx } from "../store/types.js";
12
- export declare const ACCESS_POLICY_SETTING = "access.policy";
13
- export declare function readPolicy(t: Tx): Promise<AccessPolicy>;
14
- export declare function writePolicy(t: Tx, policy: AccessPolicy): Promise<void>;
15
- /** What a token may do right now: its role narrowed by what the mint asked for. */
16
- export interface EffectiveAccess {
17
- readonly role: string;
18
- readonly scopes: ReadonlySet<TokenScope>;
19
- readonly agents: ReadonlySet<string> | "*";
20
- readonly limits?: RoleLimits;
21
- }
22
- /** Agents both lists allow; `"*"` allows every agent. */
23
- export declare function intersectAgents(a: readonly string[] | "*", b: readonly string[] | "*" | undefined): ReadonlySet<string> | "*";
24
- /**
25
- * The role's permissions narrowed to `scopes` and `agents`, or undefined when the role no
26
- * longer exists.
27
- */
28
- export declare function resolveRole(policy: AccessPolicy, role: string, scopes: readonly TokenScope[], agents?: readonly string[]): EffectiveAccess | undefined;
29
- /** True when `agentId` is allowed by `agents`. */
30
- export declare function agentAllowed(agents: ReadonlySet<string> | "*", agentId: string): boolean;
@@ -1,52 +0,0 @@
1
- /**
2
- * The Tenant's access policy (Host feature `subject-tokens`): the roles subject tokens are
3
- * minted for, what a publishable key grants alone (`anon`), and how long tokens live. One
4
- * validated JSON document in the Tenant settings; a Tenant that never set one has no roles,
5
- * so nothing can be minted.
6
- *
7
- * A token's permissions are resolved from the policy on every request, so editing a role
8
- * changes outstanding tokens at their next request and removing one ends them.
9
- */
10
- import { AccessPolicySchema, DEFAULT_ACCESS_POLICY, } from "@nylorun/core/contracts";
11
- export const ACCESS_POLICY_SETTING = "access.policy";
12
- export async function readPolicy(t) {
13
- const stored = await t.getSetting(ACCESS_POLICY_SETTING);
14
- if (stored === undefined)
15
- return DEFAULT_ACCESS_POLICY;
16
- // Only `writePolicy` stores it, after validation.
17
- return AccessPolicySchema.parse(JSON.parse(stored));
18
- }
19
- export async function writePolicy(t, policy) {
20
- await t.putSetting(ACCESS_POLICY_SETTING, JSON.stringify(AccessPolicySchema.parse(policy)));
21
- }
22
- /** Agents both lists allow; `"*"` allows every agent. */
23
- export function intersectAgents(a, b) {
24
- if (b === undefined || b === "*")
25
- return a === "*" ? "*" : new Set(a);
26
- if (a === "*")
27
- return new Set(b);
28
- const allowed = new Set(a);
29
- return new Set(b.filter((agent) => allowed.has(agent)));
30
- }
31
- /**
32
- * The role's permissions narrowed to `scopes` and `agents`, or undefined when the role no
33
- * longer exists.
34
- */
35
- export function resolveRole(policy, role, scopes, agents) {
36
- const entry = Object.hasOwn(policy.roles, role)
37
- ? policy.roles[role]
38
- : undefined;
39
- if (!entry)
40
- return undefined;
41
- const allowed = new Set(entry.scopes);
42
- return {
43
- role,
44
- scopes: new Set(scopes.filter((scope) => allowed.has(scope))),
45
- agents: intersectAgents(entry.agents, agents),
46
- ...(entry.limits ? { limits: entry.limits } : {}),
47
- };
48
- }
49
- /** True when `agentId` is allowed by `agents`. */
50
- export function agentAllowed(agents, agentId) {
51
- return agents === "*" || agents.has(agentId);
52
- }
@@ -1,14 +0,0 @@
1
- import { type SandboxRouteDeps } from "../core/sandbox-routes.js";
2
- import { type TenantContext } from "./context.js";
3
- import type { DeliveryScope } from "./delivery-token.js";
4
- /** Session and Action lookups for the sandbox route handlers. */
5
- export declare function sandboxRouteDeps(ctx: TenantContext): SandboxRouteDeps;
6
- /** `POST /v1/actions/:id/sandbox/:tool`: a sandbox tool call for the Action being delivered. */
7
- export declare function actionSandboxTool(ctx: TenantContext, scope: DeliveryScope, actionId: string, toolName: string, body: () => Promise<unknown>, signal: AbortSignal): Promise<{
8
- kind: "completed";
9
- output: unknown;
10
- } | {
11
- kind: "failed";
12
- code: string;
13
- message: string;
14
- }>;
@@ -1,29 +0,0 @@
1
- import { SandboxRouteError, handleActionSandboxTool, } from "../core/sandbox-routes.js";
2
- import { scoped } from "./auth.js";
3
- import { sandboxLookup, sessionOf } from "./context.js";
4
- import { fail } from "./http.js";
5
- /** Session and Action lookups for the sandbox route handlers. */
6
- export function sandboxRouteDeps(ctx) {
7
- return {
8
- sandbox: ctx.sandbox,
9
- session: (id) => ctx.store.tx(async (t) => {
10
- const session = await sessionOf(t, id);
11
- return { session, lookup: await sandboxLookup(t, id) };
12
- }),
13
- getAction: (id) => ctx.store.tx((t) => t.get("actions", id)),
14
- };
15
- }
16
- /** `POST /v1/actions/:id/sandbox/:tool`: a sandbox tool call for the Action being delivered. */
17
- export async function actionSandboxTool(ctx, scope, actionId, toolName, body, signal) {
18
- const action = (await ctx.store.tx((t) => t.get("actions", actionId))) ??
19
- fail(404, "Action not found");
20
- scoped(scope, action);
21
- try {
22
- return await handleActionSandboxTool(sandboxRouteDeps(ctx), actionId, toolName, await body(), signal, { generation: scope.generation });
23
- }
24
- catch (error) {
25
- if (error instanceof SandboxRouteError)
26
- fail(error.status, error.message);
27
- throw error;
28
- }
29
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * Which client app a request comes from (Host feature `browser-access`), decided before the
3
- * bearer is looked at. `Nylorun-Key` names a publishable key of this Tenant; an `Origin` must
4
- * be on that key's allowlist, and only then does the response carry CORS headers. The
5
- * allowlist protects browsers from other sites' pages; it is not authentication, since a
6
- * non-browser can send any `Origin`: tokens authorize.
7
- */
8
- import type { IncomingMessage, ServerResponse } from "node:http";
9
- import type { TenantContext } from "./context.js";
10
- /** The client app of a request: its publishable key, and the origin when from a browser. */
11
- export interface BrowserClient {
12
- readonly keyId: string;
13
- readonly origin?: string;
14
- }
15
- export declare function identifyClient(ctx: TenantContext, request: IncomingMessage, response: ServerResponse): Promise<BrowserClient | undefined>;
@@ -1,39 +0,0 @@
1
- import { PUBLISHABLE_KEY_HEADER } from "@nylorun/core/compatibility";
2
- import { originAllowed } from "@nylorun/core/contracts";
3
- import { browserOrigin, setCorsHeaders } from "../host/cors.js";
4
- import { fail, failOpaque } from "./http.js";
5
- function single(request, name) {
6
- const raw = request.headers[name.toLowerCase()];
7
- return Array.isArray(raw) ? raw[0] : raw;
8
- }
9
- export async function identifyClient(ctx, request, response) {
10
- const key = single(request, PUBLISHABLE_KEY_HEADER);
11
- const hasOrigin = request.headers.origin !== undefined;
12
- if (key === undefined) {
13
- if (hasOrigin)
14
- fail(403, `Browser requests need ${PUBLISHABLE_KEY_HEADER}`, {
15
- code: "origin_rejected",
16
- });
17
- return undefined;
18
- }
19
- const row = await ctx.store.tx((t) => t.publishableKeyByKey(key));
20
- if (!row || row.revokedAt !== null) {
21
- ctx.config.logger.warn("credential rejected", {
22
- reason: "publishable_key_rejected",
23
- });
24
- return failOpaque();
25
- }
26
- if (!hasOrigin)
27
- return { keyId: row.id };
28
- const origin = browserOrigin(request);
29
- const origins = JSON.parse(row.originsJson);
30
- if (origin === undefined || !originAllowed(origins, origin)) {
31
- ctx.config.logger.warn("credential rejected", {
32
- reason: "origin_not_allowed",
33
- keyId: row.id,
34
- });
35
- return failOpaque();
36
- }
37
- setCorsHeaders(response, origin);
38
- return { keyId: row.id, origin };
39
- }
@@ -1,41 +0,0 @@
1
- import type { AuthScope, TenantContext } from "./context.js";
2
- /** What a delivery token is for: one delivery of an Action, or a ping. */
3
- export type DeliveryTokenFor = {
4
- kind: "action";
5
- actionId: string;
6
- agentId: string;
7
- generation: number;
8
- } | {
9
- kind: "ping";
10
- agentId: string;
11
- };
12
- export interface MintedDeliveryToken {
13
- token: string;
14
- /** Milliseconds since the epoch. */
15
- expiresAt: number;
16
- tokenId: string;
17
- keyId: string;
18
- }
19
- /** The request scope of a verified delivery token (`AuthScope` kind `delivery`). */
20
- export type DeliveryScope = Extract<AuthScope, {
21
- kind: "delivery";
22
- }>;
23
- /** base64url SHA-256 of a request body: the token's `bdy` claim. */
24
- export declare function bodyHash(body: string | Uint8Array): string;
25
- /**
26
- * Signs a token for `delivery`, for the endpoint at `audience`, covering `body`. `ttlSeconds`
27
- * is capped at `DELIVERY_TOKEN_MAX_TTL_SECONDS`.
28
- */
29
- export declare function mintDeliveryToken(ctx: TenantContext, options: {
30
- for: DeliveryTokenFor;
31
- audience: string;
32
- body: string | Uint8Array;
33
- ttlSeconds: number;
34
- }): Promise<MintedDeliveryToken>;
35
- /**
36
- * Verifies a delivery token presented as a bearer. Answers `401 token_expired` for an expired
37
- * token or a revoked key, and the opaque 404 for everything else, a ping token included: only
38
- * an Action's token reaches its callbacks. Whether the Action is still being delivered at the
39
- * token's generation is checked where the Action is read (`auth.ts` `scoped`).
40
- */
41
- export declare function verifyDeliveryToken(ctx: TenantContext, raw: string): Promise<DeliveryScope>;