@nylorun/runtime 0.17.0-beta → 0.19.1-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 (223) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/README.md +89 -58
  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/routes.js +1 -1
  9. package/dist/api/ag-ui/translate.d.ts +1 -3
  10. package/dist/api/ag-ui/translate.js +2 -17
  11. package/dist/api/components.d.ts +4871 -2614
  12. package/dist/api/components.js +12 -11
  13. package/dist/api/gate/routes.d.ts +7 -8
  14. package/dist/api/gate/routes.js +58 -52
  15. package/dist/api/http/app.d.ts +6 -0
  16. package/dist/api/http/app.js +18 -14
  17. package/dist/api/http/define.d.ts +14 -2
  18. package/dist/api/http/define.js +34 -15
  19. package/dist/api/http/routes/access.d.ts +3 -3
  20. package/dist/api/http/routes/access.js +18 -17
  21. package/dist/api/http/routes/artifacts.js +2 -4
  22. package/dist/api/http/routes/files.d.ts +8 -0
  23. package/dist/api/http/routes/files.js +77 -0
  24. package/dist/api/http/routes/keys.d.ts +10 -0
  25. package/dist/api/http/routes/keys.js +64 -0
  26. package/dist/api/http/routes/me.js +5 -2
  27. package/dist/api/http/routes/reads.d.ts +66 -0
  28. package/dist/api/http/routes/reads.js +127 -0
  29. package/dist/api/http/routes/sandboxes.js +7 -4
  30. package/dist/api/http/routes/sessions.js +25 -8
  31. package/dist/api/http/routes/tenant.js +15 -18
  32. package/dist/api/http/routes/vaults.d.ts +10 -9
  33. package/dist/api/http/routes/vaults.js +27 -23
  34. package/dist/api/openapi.d.ts +10 -11
  35. package/dist/api/openapi.js +288 -63
  36. package/dist/artifacts/links.js +1 -1
  37. package/dist/core/flow-host.d.ts +44 -23
  38. package/dist/core/flow-host.js +88 -106
  39. package/dist/core/provider.d.ts +4 -1
  40. package/dist/core/provider.js +6 -1
  41. package/dist/core/sandbox-routes.d.ts +0 -9
  42. package/dist/core/sandbox-routes.js +2 -21
  43. package/dist/execution/memory.d.ts +4 -5
  44. package/dist/execution/memory.js +11 -25
  45. package/dist/execution/types.d.ts +3 -33
  46. package/dist/execution/types.js +2 -12
  47. package/dist/gates/http-tool.d.ts +86 -0
  48. package/dist/gates/http-tool.js +197 -0
  49. package/dist/gates/mcp-handler.d.ts +3 -0
  50. package/dist/gates/mcp-handler.js +1 -3
  51. package/dist/gates/meter.d.ts +2 -2
  52. package/dist/gates/meter.js +6 -0
  53. package/dist/gates/tenant-vaults.d.ts +5 -9
  54. package/dist/gates/tool-calls.d.ts +7 -15
  55. package/dist/gates/tool-calls.js +4 -4
  56. package/dist/gates/tool-client.d.ts +1 -1
  57. package/dist/gates/tool-client.js +23 -47
  58. package/dist/gates/tool-contract.d.ts +27 -39
  59. package/dist/gates/tool-contract.js +30 -21
  60. package/dist/gates/tool-gate.d.ts +25 -24
  61. package/dist/gates/tool-gate.js +11 -7
  62. package/dist/harness/calls.d.ts +10 -4
  63. package/dist/harness/calls.js +15 -6
  64. package/dist/harness/executors.d.ts +1 -1
  65. package/dist/harness/executors.js +17 -12
  66. package/dist/harness/main.d.ts +2 -2
  67. package/dist/harness/main.js +5 -13
  68. package/dist/harness/service.d.ts +4 -5
  69. package/dist/harness/service.js +9 -2
  70. package/dist/harness-api/in-process.js +2 -2
  71. package/dist/harness-api/record.d.ts +6 -3
  72. package/dist/harness-api/record.js +65 -72
  73. package/dist/harness-api/server.d.ts +1 -9
  74. package/dist/harness-api/server.js +19 -17
  75. package/dist/harness-api/start.js +1 -5
  76. package/dist/harness-api/workspace.js +2 -3
  77. package/dist/harness-api/ws-server.js +1 -1
  78. package/dist/host/app.d.ts +2 -9
  79. package/dist/host/app.js +15 -25
  80. package/dist/host/config-for.d.ts +1 -5
  81. package/dist/host/config-for.js +0 -3
  82. package/dist/host/config.d.ts +0 -5
  83. package/dist/host/create-host.d.ts +3 -33
  84. package/dist/host/create-host.js +18 -94
  85. package/dist/host/environment.d.ts +0 -3
  86. package/dist/host/environment.js +0 -9
  87. package/dist/host/gates.d.ts +4 -1
  88. package/dist/host/gates.js +3 -2
  89. package/dist/host/http.d.ts +1 -2
  90. package/dist/host/http.js +1 -7
  91. package/dist/host/index.d.ts +2 -2
  92. package/dist/host/index.js +2 -2
  93. package/dist/host/main.js +27 -34
  94. package/dist/host/operate.d.ts +29 -0
  95. package/dist/host/operate.js +223 -0
  96. package/dist/host/stack-config.d.ts +12 -12
  97. package/dist/host/stack-config.js +5 -32
  98. package/dist/index.d.ts +1 -1
  99. package/dist/index.js +1 -1
  100. package/dist/infra/workers.d.ts +1 -1
  101. package/dist/keys/keys.js +2 -2
  102. package/dist/management-openapi.json +6491 -0
  103. package/dist/mcp/connect.d.ts +8 -4
  104. package/dist/mcp/connect.js +6 -26
  105. package/dist/mcp/pool.d.ts +5 -9
  106. package/dist/mcp/pool.js +8 -19
  107. package/dist/mcp/snapshot.d.ts +8 -2
  108. package/dist/mcp/snapshot.js +29 -2
  109. package/dist/media.d.ts +1 -1
  110. package/dist/media.js +1 -1
  111. package/dist/model/pi-model.js +3 -0
  112. package/dist/openapi.json +9372 -17030
  113. package/dist/reads/access.d.ts +4 -0
  114. package/dist/reads/access.js +12 -0
  115. package/dist/reads/cursor.d.ts +11 -0
  116. package/dist/reads/cursor.js +80 -0
  117. package/dist/reads/types.d.ts +25 -0
  118. package/dist/reads/types.js +1 -0
  119. package/dist/sandbox/manager.d.ts +16 -0
  120. package/dist/sandbox/manager.js +40 -0
  121. package/dist/sandbox/session-sandbox.js +13 -3
  122. package/dist/sandbox/skills.d.ts +13 -0
  123. package/dist/sandbox/skills.js +46 -0
  124. package/dist/sandbox/types.d.ts +2 -2
  125. package/dist/store/ownership.d.ts +9 -0
  126. package/dist/store/ownership.js +13 -0
  127. package/dist/store/postgres/connect.d.ts +2 -0
  128. package/dist/store/postgres/connect.js +29 -0
  129. package/dist/store/postgres/drizzle/0011_key_roles.sql +3 -0
  130. package/dist/store/postgres/drizzle/0012_session_reads.sql +8 -0
  131. package/dist/store/postgres/drizzle/0013_definition_files.sql +16 -0
  132. package/dist/store/postgres/drizzle/0014_action_endpoints_removed.sql +2 -0
  133. package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
  134. package/dist/store/postgres/reads.d.ts +3 -0
  135. package/dist/store/postgres/reads.js +272 -0
  136. package/dist/store/postgres/schema.d.ts +294 -489
  137. package/dist/store/postgres/schema.js +41 -76
  138. package/dist/store/postgres/store.js +51 -154
  139. package/dist/store/postgres/tenant.d.ts +34 -2
  140. package/dist/store/postgres/tenant.js +16 -32
  141. package/dist/store/types.d.ts +27 -96
  142. package/dist/store/types.js +0 -1
  143. package/dist/streams/control.d.ts +0 -2
  144. package/dist/streams/control.js +0 -5
  145. package/dist/streams/types.d.ts +1 -10
  146. package/dist/tenant/advance.d.ts +3 -3
  147. package/dist/tenant/advance.js +10 -7
  148. package/dist/tenant/auth.d.ts +14 -9
  149. package/dist/tenant/auth.js +24 -28
  150. package/dist/tenant/cause.d.ts +3 -3
  151. package/dist/tenant/cause.js +1 -1
  152. package/dist/tenant/commands.d.ts +2 -18
  153. package/dist/tenant/commands.js +35 -172
  154. package/dist/tenant/context.d.ts +14 -24
  155. package/dist/tenant/definition-files.d.ts +24 -0
  156. package/dist/tenant/definition-files.js +103 -0
  157. package/dist/tenant/effects.d.ts +18 -20
  158. package/dist/tenant/effects.js +56 -119
  159. package/dist/tenant/ephemeral.d.ts +7 -6
  160. package/dist/tenant/ephemeral.js +3 -11
  161. package/dist/tenant/host-token.js +1 -1
  162. package/dist/tenant/jwt.js +1 -1
  163. package/dist/tenant/module.d.ts +1 -4
  164. package/dist/tenant/module.js +3 -12
  165. package/dist/tenant/operator-keys.d.ts +34 -8
  166. package/dist/tenant/operator-keys.js +50 -18
  167. package/dist/tenant/outbound.d.ts +10 -1
  168. package/dist/tenant/outbound.js +44 -27
  169. package/dist/tenant/paths.d.ts +1 -1
  170. package/dist/tenant/paths.js +1 -3
  171. package/dist/tenant/principals.d.ts +11 -2
  172. package/dist/tenant/principals.js +27 -8
  173. package/dist/tenant/run-token.js +3 -3
  174. package/dist/tenant/runtime.d.ts +4 -6
  175. package/dist/tenant/runtime.js +19 -18
  176. package/dist/tenant/sandboxes.d.ts +4 -1
  177. package/dist/tenant/sandboxes.js +11 -0
  178. package/dist/tenant/scheduler.d.ts +1 -5
  179. package/dist/tenant/scheduler.js +2 -5
  180. package/dist/tenant/session-streams.d.ts +2 -1
  181. package/dist/tenant/session-streams.js +39 -5
  182. package/dist/tenant/session.d.ts +8 -41
  183. package/dist/tenant/session.js +0 -37
  184. package/dist/tenant/sessions.js +16 -8
  185. package/dist/tenant/signing-keys.d.ts +3 -3
  186. package/dist/tenant/signing-keys.js +5 -5
  187. package/dist/tenant/skill-tool.d.ts +20 -0
  188. package/dist/tenant/skill-tool.js +72 -0
  189. package/dist/tenant/slim.d.ts +1 -1
  190. package/dist/tenant/slim.js +1 -1
  191. package/dist/tenant/status.js +7 -12
  192. package/dist/tenant/store-pg.d.ts +15 -0
  193. package/dist/tenant/store-pg.js +7 -3
  194. package/dist/tenant/streams.d.ts +3 -10
  195. package/dist/tenant/streams.js +1 -24
  196. package/dist/tenant/sweep.js +0 -5
  197. package/dist/tenant/transcript.d.ts +2 -2
  198. package/dist/tenant/transcript.js +2 -2
  199. package/dist/tenant/types.d.ts +15 -22
  200. package/dist/tenant/worker.d.ts +1 -3
  201. package/dist/tenant/worker.js +3 -8
  202. package/dist/vault/sources.d.ts +7 -1
  203. package/dist/vault/sources.js +22 -11
  204. package/dist/version.d.ts +1 -1
  205. package/dist/version.js +1 -1
  206. package/package.json +4 -4
  207. package/dist/admin-openapi.json +0 -904
  208. package/dist/api/http/routes/actions.d.ts +0 -8
  209. package/dist/api/http/routes/actions.js +0 -75
  210. package/dist/api/http/routes/endpoints.d.ts +0 -7
  211. package/dist/api/http/routes/endpoints.js +0 -100
  212. package/dist/host/admin-api.d.ts +0 -30
  213. package/dist/host/admin-api.js +0 -140
  214. package/dist/mcp/stdio.d.ts +0 -17
  215. package/dist/mcp/stdio.js +0 -82
  216. package/dist/tenant/actions.d.ts +0 -14
  217. package/dist/tenant/actions.js +0 -29
  218. package/dist/tenant/delivery-token.d.ts +0 -41
  219. package/dist/tenant/delivery-token.js +0 -104
  220. package/dist/tenant/delivery.d.ts +0 -62
  221. package/dist/tenant/delivery.js +0 -481
  222. package/dist/tenant/endpoints.d.ts +0 -67
  223. package/dist/tenant/endpoints.js +0 -90
@@ -1,31 +1,29 @@
1
1
  /**
2
2
  * The loop's client of the Tool Gate in the gates service (F4.1, `tool-contract.ts`): remote
3
3
  * MCP servers opened and called through the gate, which holds their connections and
4
- * credentials, and Action deliveries POSTed by the gate. Over `node:http`, like the model gate's
5
- * client (`http-client.ts`): a call answers only when it has finished.
4
+ * credentials, and HTTP tools called by the gate (R2 M3).
5
+ * Over `node:http`, like the model gate's client (`http-client.ts`): a call answers only when it
6
+ * has finished.
6
7
  *
7
8
  * Failures keep the meaning they had in the loop's own process:
8
9
  * - An MCP request that fails, at the server or on the hop, throws, so the pool reports a
9
- * diagnostic and `resolveEffect` marks a call `uncertain`, as before.
10
- * - A delivery never throws. A hop that failed before the request was sent is `not_sent`
11
- * (the deliverer sends it again, even a tool); one that failed after is `lost`.
10
+ * diagnostic and `resolveEffect` marks a call `uncertain`, as before. An HTTP tool call
11
+ * throws only for the hop, or a call lost with the gateway: its own failures are outcomes.
12
12
  *
13
13
  * Credentials (F5): a session's MCP requests and keyed cancels carry its run token, read per
14
14
  * request from the advance's grant, and leave the session out of the body: the gate takes it
15
- * from the token. Deliveries, pings, and MCP requests made outside a run (closing a pooled
16
- * connection after the advance ended) carry core's credential, `NYLORUN_GATES_TOKEN`, and name
17
- * the session in the body.
15
+ * from the token. MCP requests made outside a run (closing a pooled connection after the
16
+ * advance ended) carry core's credential, `NYLORUN_GATES_TOKEN`, and name the session in the
17
+ * body.
18
18
  */
19
19
  import { randomUUID } from "node:crypto";
20
20
  import { request as httpRequest } from "node:http";
21
21
  import { request as httpsRequest } from "node:https";
22
22
  import { TENANT_HEADER } from "./contract.js";
23
23
  import { GATE_CLIENT_TIMEOUT_MS } from "./http-client.js";
24
- import { DELIVERIES_PATH, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, TOOL_CALLS_PATH, } from "./tool-contract.js";
24
+ import { HTTP_CALLS_PATH, MCP_CLOSE_PATH, MCP_CONNECT_PATH, MCP_LIST_PATH, TOOL_CALLS_PATH, } from "./tool-contract.js";
25
25
  /** How long a close or a cancel may take; neither changes an outcome. */
26
26
  const SHORT_TIMEOUT_MS = 2_000;
27
- /** Extra silence allowed on a delivery beyond the endpoint's own timeout. */
28
- const DELIVERY_SLACK_MS = 30_000;
29
27
  export function httpToolGate(options) {
30
28
  const where = new URL(options.url).origin;
31
29
  const timeoutMs = options.timeoutMs ?? GATE_CLIENT_TIMEOUT_MS;
@@ -107,8 +105,11 @@ export function httpToolGate(options) {
107
105
  const { sessionId: _, ...unnamed } = server;
108
106
  return { body: body(unnamed), bearer: token };
109
107
  }
110
- /** The result of an MCP request, or a throw the pool and `resolveEffect` read as before. */
111
- async function mcp(path, scope, request) {
108
+ /**
109
+ * The result of an MCP or HTTP tool request, or a throw the pool and `resolveEffect` read as
110
+ * before: the call's fate is unknown, and the effect becomes `uncertain`.
111
+ */
112
+ async function answered(path, scope, request) {
112
113
  const result = await exchange(path, scope.body, {
113
114
  ...request,
114
115
  timeoutMs,
@@ -135,13 +136,13 @@ export function httpToolGate(options) {
135
136
  recovers: true,
136
137
  async openMcp(server) {
137
138
  // The credential is read per request: the connection outlives the advance that opened it.
138
- await mcp(MCP_CONNECT_PATH, scoped(server, (named) => ({ server: named })), {});
139
+ await answered(MCP_CONNECT_PATH, scoped(server, (named) => ({ server: named })), {});
139
140
  const client = {
140
- listTools: (params, request) => mcp(MCP_LIST_PATH, scoped(server, (named) => ({
141
+ listTools: (params, request) => answered(MCP_LIST_PATH, scoped(server, (named) => ({
141
142
  server: named,
142
143
  ...(params?.cursor ? { cursor: params.cursor } : {}),
143
144
  })), request?.signal ? { signal: request.signal } : {}),
144
- callTool: (params, request) => mcp(TOOL_CALLS_PATH, scoped(server, (named) => ({
145
+ callTool: (params, request) => answered(TOOL_CALLS_PATH, scoped(server, (named) => ({
145
146
  server: named,
146
147
  effectId: request?.key ?? randomUUID(),
147
148
  name: params.name,
@@ -156,6 +157,12 @@ export function httpToolGate(options) {
156
157
  close: () => fireAndForget(MCP_CLOSE_PATH, scoped(server, (named) => ({ server: named }))),
157
158
  };
158
159
  },
160
+ async callHttp(call, signal) {
161
+ const token = options.runTokens?.token(call.tool.sessionId);
162
+ const { sessionId: _, ...unnamed } = call.tool;
163
+ const body = { ...call, tool: token ? unnamed : { ...call.tool } };
164
+ return answered(HTTP_CALLS_PATH, { body, ...(token ? { bearer: token } : {}) }, { signal, idempotencyKey: call.effectId });
165
+ },
159
166
  async cancel(request) {
160
167
  const token = options.runTokens?.token(request.sessionId);
161
168
  await fireAndForget(`${TOOL_CALLS_PATH}/${encodeURIComponent(request.effectId)}/cancel`, {
@@ -163,37 +170,6 @@ export function httpToolGate(options) {
163
170
  ...(token ? { bearer: token } : {}),
164
171
  });
165
172
  },
166
- async post(delivery, signal) {
167
- const result = await exchange(DELIVERIES_PATH, {
168
- url: delivery.url,
169
- body: delivery.body,
170
- headers: { ...delivery.headers },
171
- timeoutMs: delivery.timeoutMs,
172
- }, { signal, timeoutMs: delivery.timeoutMs + DELIVERY_SLACK_MS });
173
- if (result.kind === "aborted")
174
- return {
175
- kind: result.sent ? "lost" : "not_sent",
176
- code: "ABORTED",
177
- message: "The delivery was aborted",
178
- };
179
- if (result.kind === "unreachable")
180
- return { kind: "not_sent", code: "gateway.unreachable", message: result.message };
181
- if (result.kind === "lost")
182
- return { kind: "lost", code: "gateway.lost", message: result.message };
183
- const parsed = parse(result.text);
184
- if (result.status !== 200 || !parsed?.result)
185
- // The gate refused the request before sending anything.
186
- return { kind: "not_sent", code: "gateway.refused", message: gateRefusal(result.status, parsed) };
187
- const wire = parsed.result;
188
- if (wire.kind !== "response")
189
- return wire;
190
- return {
191
- kind: "response",
192
- status: wire.status,
193
- headers: wire.headers,
194
- body: Buffer.from(wire.body, "base64"),
195
- };
196
- },
197
173
  };
198
174
  }
199
175
  /** An MCP failure the gate reported, as the loop's own MCP code would have thrown it. */
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * The Tool Gate's wire format (blueprint §12, F4.1): the routes the loop calls on the gates
3
- * service for remote MCP servers and Action deliveries. Internal, like the model call route
3
+ * service for remote MCP servers and HTTP tools. Internal, like the model call route
4
4
  * (`contract.ts`): same optional Tenant header, not in the published OpenAPI documents.
5
5
  *
6
6
  * Credentials (F5). A session's MCP requests carry its run token, and the gate takes the
7
7
  * session from it: `server.sessionId` is then absent (or the token's). Core's credential
8
8
  * (`NYLORUN_GATES_TOKEN`) is accepted too, for requests made outside a run, and then
9
- * `server.sessionId` names the session. Deliveries accept core's credential only.
9
+ * `server.sessionId` names the session.
10
10
  *
11
11
  * Remote MCP. The gate holds the connection and the vault credential; the loop names the
12
12
  * server, never a URL or a credential, and the gate finds it in the session's pinned manifest.
@@ -23,22 +23,23 @@
23
23
  * answer, not a gate error. A keyed call whose earlier attempt was lost with the gateway answers
24
24
  * `{ok: false, error: {uncertain: true}}` and is never run again.
25
25
  *
26
- * Action deliveries. `POST /nylorun/v1/deliveries` `{url, body, headers, timeoutMs}`: the gate
27
- * POSTs the signed delivery under the gateway's own address policy and answers `200 {result}`,
28
- * what `tenant/outbound.ts` `post` returned, with the answer's body in base64.
26
+ * HTTP tools (R2 M3). `POST /nylorun/v1/http-calls` `{tool, effectId, turnId, input}`: one call
27
+ * of an HTTP tool. The loop names the tool (`{sessionId?, agentId?, capabilityId, toolName}`), or a
28
+ * flow's HTTP stage or HTTP verifier by its stage key (`{sessionId?, stage}`); the gate finds its
29
+ * URL, method and credential in the session's pinned manifest
30
+ * (`gates/http-tool.ts`). A run token's turn is the call's; `turnId` counts only under core's
31
+ * credential. Keyed like a tool call, and cancelled by the same route. It answers
32
+ * `200 {ok: true, result}` with the tool outcome (a failed request is a failed outcome the
33
+ * model sees), or `{ok: false, error: {uncertain: true}}` for a call lost with the gateway.
29
34
  */
30
35
  import { z } from "zod";
31
36
  export declare const MCP_CONNECT_PATH = "/nylorun/v1/mcp/connect";
32
37
  export declare const MCP_LIST_PATH = "/nylorun/v1/mcp/list";
33
38
  export declare const MCP_CLOSE_PATH = "/nylorun/v1/mcp/close";
34
39
  export declare const TOOL_CALLS_PATH = "/nylorun/v1/tool-calls";
35
- export declare const DELIVERIES_PATH = "/nylorun/v1/deliveries";
36
- /** Largest tool call or delivery body the gate reads. */
40
+ export declare const HTTP_CALLS_PATH = "/nylorun/v1/http-calls";
41
+ /** Largest tool call body the gate reads. */
37
42
  export declare const MAX_TOOL_BODY_BYTES: number;
38
- /** The longest delivery timeout the gate accepts: an endpoint's maximum `timeoutMs`. */
39
- export declare const MAX_DELIVERY_TIMEOUT_MS: number;
40
- /** The only headers the gate forwards on a delivery, lower-cased. */
41
- export declare const DELIVERY_HEADERS: ReadonlySet<string>;
42
43
  export declare const McpServerRefSchema: z.ZodObject<{
43
44
  sessionId: z.ZodOptional<z.ZodString>;
44
45
  agentId: z.ZodOptional<z.ZodString>;
@@ -74,6 +75,21 @@ export declare const ToolCallBodySchema: z.ZodObject<{
74
75
  arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
75
76
  }, z.core.$strip>;
76
77
  export type ToolCallBody = z.infer<typeof ToolCallBodySchema>;
78
+ export declare const HttpCallBodySchema: z.ZodObject<{
79
+ tool: z.ZodUnion<readonly [z.ZodObject<{
80
+ sessionId: z.ZodOptional<z.ZodString>;
81
+ agentId: z.ZodOptional<z.ZodString>;
82
+ capabilityId: z.ZodString;
83
+ toolName: z.ZodString;
84
+ }, z.core.$strip>, z.ZodObject<{
85
+ sessionId: z.ZodOptional<z.ZodString>;
86
+ stage: z.ZodString;
87
+ }, z.core.$strip>]>;
88
+ effectId: z.ZodString;
89
+ turnId: z.ZodString;
90
+ input: z.ZodUnknown;
91
+ }, z.core.$strip>;
92
+ export type HttpCallBody = z.infer<typeof HttpCallBodySchema>;
77
93
  /** Why an MCP request failed, as the loop's diagnostics read it (`mcp/connect.ts`). */
78
94
  export interface McpGateError {
79
95
  readonly message: string;
@@ -91,31 +107,3 @@ export type McpAnswer<T> = {
91
107
  readonly ok: false;
92
108
  readonly error: McpGateError;
93
109
  };
94
- export declare const DeliveryBodySchema: z.ZodObject<{
95
- url: z.ZodString;
96
- body: z.ZodString;
97
- headers: z.ZodRecord<z.ZodString, z.ZodString>;
98
- timeoutMs: z.ZodNumber;
99
- }, z.core.$strip>;
100
- export type DeliveryBody = z.infer<typeof DeliveryBodySchema>;
101
- /** `OutboundResult` on the wire: the answer's body in base64. */
102
- export type WireOutboundResult = {
103
- readonly kind: "response";
104
- readonly status: number;
105
- readonly headers: Record<string, string | string[] | undefined>;
106
- readonly body: string;
107
- } | {
108
- readonly kind: "too_large";
109
- readonly status: number;
110
- } | {
111
- readonly kind: "not_sent";
112
- readonly code: string;
113
- readonly message: string;
114
- } | {
115
- readonly kind: "lost";
116
- readonly code: string;
117
- readonly message: string;
118
- };
119
- export interface DeliveryAnswer {
120
- readonly result: WireOutboundResult;
121
- }
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * The Tool Gate's wire format (blueprint §12, F4.1): the routes the loop calls on the gates
3
- * service for remote MCP servers and Action deliveries. Internal, like the model call route
3
+ * service for remote MCP servers and HTTP tools. Internal, like the model call route
4
4
  * (`contract.ts`): same optional Tenant header, not in the published OpenAPI documents.
5
5
  *
6
6
  * Credentials (F5). A session's MCP requests carry its run token, and the gate takes the
7
7
  * session from it: `server.sessionId` is then absent (or the token's). Core's credential
8
8
  * (`NYLORUN_GATES_TOKEN`) is accepted too, for requests made outside a run, and then
9
- * `server.sessionId` names the session. Deliveries accept core's credential only.
9
+ * `server.sessionId` names the session.
10
10
  *
11
11
  * Remote MCP. The gate holds the connection and the vault credential; the loop names the
12
12
  * server, never a URL or a credential, and the gate finds it in the session's pinned manifest.
@@ -23,27 +23,23 @@
23
23
  * answer, not a gate error. A keyed call whose earlier attempt was lost with the gateway answers
24
24
  * `{ok: false, error: {uncertain: true}}` and is never run again.
25
25
  *
26
- * Action deliveries. `POST /nylorun/v1/deliveries` `{url, body, headers, timeoutMs}`: the gate
27
- * POSTs the signed delivery under the gateway's own address policy and answers `200 {result}`,
28
- * what `tenant/outbound.ts` `post` returned, with the answer's body in base64.
26
+ * HTTP tools (R2 M3). `POST /nylorun/v1/http-calls` `{tool, effectId, turnId, input}`: one call
27
+ * of an HTTP tool. The loop names the tool (`{sessionId?, agentId?, capabilityId, toolName}`), or a
28
+ * flow's HTTP stage or HTTP verifier by its stage key (`{sessionId?, stage}`); the gate finds its
29
+ * URL, method and credential in the session's pinned manifest
30
+ * (`gates/http-tool.ts`). A run token's turn is the call's; `turnId` counts only under core's
31
+ * credential. Keyed like a tool call, and cancelled by the same route. It answers
32
+ * `200 {ok: true, result}` with the tool outcome (a failed request is a failed outcome the
33
+ * model sees), or `{ok: false, error: {uncertain: true}}` for a call lost with the gateway.
29
34
  */
30
35
  import { z } from "zod";
31
- import { PROTOCOL_HEADER, SIGNATURE_HEADER } from "@nylorun/core/compatibility";
32
36
  export const MCP_CONNECT_PATH = "/nylorun/v1/mcp/connect";
33
37
  export const MCP_LIST_PATH = "/nylorun/v1/mcp/list";
34
38
  export const MCP_CLOSE_PATH = "/nylorun/v1/mcp/close";
35
39
  export const TOOL_CALLS_PATH = "/nylorun/v1/tool-calls";
36
- export const DELIVERIES_PATH = "/nylorun/v1/deliveries";
37
- /** Largest tool call or delivery body the gate reads. */
40
+ export const HTTP_CALLS_PATH = "/nylorun/v1/http-calls";
41
+ /** Largest tool call body the gate reads. */
38
42
  export const MAX_TOOL_BODY_BYTES = 8 * 1024 * 1024;
39
- /** The longest delivery timeout the gate accepts: an endpoint's maximum `timeoutMs`. */
40
- export const MAX_DELIVERY_TIMEOUT_MS = 15 * 60_000;
41
- /** The only headers the gate forwards on a delivery, lower-cased. */
42
- export const DELIVERY_HEADERS = new Set([
43
- SIGNATURE_HEADER.toLowerCase(),
44
- PROTOCOL_HEADER.toLowerCase(),
45
- "idempotency-key",
46
- ]);
47
43
  export const McpServerRefSchema = z.object({
48
44
  /** Required with core's credential; a run token names the session itself. */
49
45
  sessionId: z.string().min(1).optional(),
@@ -62,9 +58,22 @@ export const ToolCallBodySchema = z.object({
62
58
  name: z.string().min(1),
63
59
  arguments: z.record(z.string(), z.unknown()),
64
60
  });
65
- export const DeliveryBodySchema = z.object({
66
- url: z.string().url(),
67
- body: z.string(),
68
- headers: z.record(z.string(), z.string()),
69
- timeoutMs: z.number().int().positive().max(MAX_DELIVERY_TIMEOUT_MS),
61
+ export const HttpCallBodySchema = z.object({
62
+ tool: z.union([
63
+ z.object({
64
+ /** Required with core's credential; a run token names the session itself. */
65
+ sessionId: z.string().min(1).optional(),
66
+ agentId: z.string().min(1).optional(),
67
+ capabilityId: z.string().min(1),
68
+ toolName: z.string().min(1),
69
+ }),
70
+ z.object({
71
+ sessionId: z.string().min(1).optional(),
72
+ /** A flow's HTTP stage or HTTP verifier. */
73
+ stage: z.string().min(1),
74
+ }),
75
+ ]),
76
+ effectId: z.string().min(1),
77
+ turnId: z.string().min(1),
78
+ input: z.unknown(),
70
79
  });
@@ -1,46 +1,47 @@
1
1
  /**
2
2
  * The Tool Gate seam (blueprint §12, F4.1). Every tool call that leaves the loop crosses one
3
- * `ToolGate`: a remote MCP server's connection and calls, and every Action delivery to an
4
- * Action endpoint. The gate owns what those need that the loop must not hold: the MCP
5
- * credential and its OAuth refresh, and the outbound route.
3
+ * `ToolGate`: a remote MCP server's connection and calls, and an HTTP tool's request (R2 M3).
4
+ * The gate owns what those need that the loop must not hold: the MCP and HTTP tool credentials
5
+ * and their OAuth refresh, and the outbound route.
6
6
  *
7
7
  * Two implementations: `inProcessToolGate` (embedding, the ephemeral Runtime, tests), which
8
- * opens remote servers and POSTs deliveries in this process, and the HTTP client of the gates
9
- * service (`tool-client.ts`, the `gateway` container). Stdio MCP servers and the sandbox tools
10
- * never cross it: they run beside the loop until the session sandbox takes them (P4).
8
+ * opens remote servers and calls HTTP tools in this process, and the HTTP client of the gates
9
+ * service (`tool-client.ts`, the `gateway` container). The sandbox tools never cross it.
11
10
  */
12
11
  import type { LiveConnection } from "../mcp/connect.js";
13
12
  import type { McpServerRef } from "../mcp/pool.js";
14
- import { type OutboundPolicy, type OutboundResult } from "../tenant/outbound.js";
15
- /** One Action delivery or endpoint ping, signed by the caller. */
16
- export interface DeliveryRequest {
17
- readonly url: string;
18
- readonly body: string;
19
- /** `Nylorun-Signature`, `Nylorun-Protocol` and `Idempotency-Key`; nothing else. */
20
- readonly headers: Readonly<Record<string, string>>;
21
- /** How long the endpoint may take to answer. */
22
- readonly timeoutMs: number;
23
- }
13
+ import type { OutboundPolicy } from "../tenant/outbound.js";
14
+ import type { Logger } from "../tenant/types.js";
15
+ import { type HttpOutcome, type HttpToolCall, type HttpToolTenant } from "./http-tool.js";
24
16
  export interface ToolGate {
25
17
  /**
26
18
  * Opens a remote (`streamable-http` or `sse`) MCP server of a session. Absent: the loop's
27
19
  * pool opens it itself, with the Tenant vault.
28
20
  */
29
21
  openMcp?(server: McpServerRef): Promise<LiveConnection>;
30
- /** POSTs a delivery. Never throws; `signal` aborts it (see `tenant/outbound.ts`). */
31
- post(request: DeliveryRequest, signal: AbortSignal): Promise<OutboundResult>;
32
22
  /**
33
- * True when a keyed MCP call outlives the caller's process (the gates service, G3): after a
34
- * takeover or a shutdown, re-sending it joins the call or returns its outcome, and a call
35
- * lost with the gateway answers `uncertain` instead of running again.
23
+ * Calls an HTTP tool of a session (R2 M3), keyed by the call's effect id. A failed request is
24
+ * a failed outcome; it throws only when the call's fate is unknown (the gate was lost, or the
25
+ * call was lost with it) or `signal` aborts. Absent: this Runtime cannot run HTTP tools.
26
+ */
27
+ callHttp?(call: HttpToolCall, signal: AbortSignal): Promise<HttpOutcome>;
28
+ /**
29
+ * True when a keyed MCP or HTTP tool call outlives the caller's process (the gates service,
30
+ * G3): after a takeover or a shutdown, re-sending it joins the call or returns its outcome,
31
+ * and a call lost with the gateway answers `uncertain` instead of running again.
36
32
  */
37
33
  readonly recovers?: boolean;
38
- /** Stops a keyed MCP call that outlives its caller (a user cancel). Never rejects. */
34
+ /** Stops a keyed tool call that outlives its caller (a user cancel). Never rejects. */
39
35
  cancel?(request: {
40
36
  tenantId: string;
41
37
  sessionId: string;
42
38
  effectId: string;
43
39
  }): Promise<void>;
44
40
  }
45
- /** The Tool Gate in the caller's process: remote MCP through the pool, deliveries by `post`. */
46
- export declare function inProcessToolGate(policy?: OutboundPolicy): ToolGate;
41
+ /**
42
+ * The Tool Gate in the caller's process: remote MCP through the pool, and HTTP tools with
43
+ * `tenant`'s sessions and vault.
44
+ */
45
+ export declare function inProcessToolGate(policy?: OutboundPolicy, tenant?: HttpToolTenant & {
46
+ readonly logger?: Logger;
47
+ }): ToolGate;
@@ -1,10 +1,14 @@
1
- import { post } from "../tenant/outbound.js";
2
- /** The Tool Gate in the caller's process: remote MCP through the pool, deliveries by `post`. */
3
- export function inProcessToolGate(policy = {}) {
1
+ import { runHttpTool } from "./http-tool.js";
2
+ /**
3
+ * The Tool Gate in the caller's process: remote MCP through the pool, and HTTP tools with
4
+ * `tenant`'s sessions and vault.
5
+ */
6
+ export function inProcessToolGate(policy = {}, tenant) {
4
7
  return {
5
- post: (request, signal) => post(request.url, request.body, { ...request.headers }, {
6
- policy,
7
- signal: AbortSignal.any([signal, AbortSignal.timeout(request.timeoutMs)]),
8
- }),
8
+ ...(tenant
9
+ ? {
10
+ callHttp: (call, signal) => runHttpTool(tenant, call, { policy, signal, ...(tenant.logger ? { logger: tenant.logger } : {}) }),
11
+ }
12
+ : {}),
9
13
  };
10
14
  }
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * The calls a harness executes, as pure helpers over what routes them: the Model Gate (or the
3
- * Tenant's provider), the MCP pool, the SandboxManager. No store, no record: the session's
4
- * routing comes with the run (`TurnStart.routing`).
3
+ * Tenant's provider), the Tool Gate, the MCP pool, the SandboxManager. No store, no record: the
4
+ * session's routing comes with the run (`TurnStart.routing`).
5
5
  */
6
6
  import { type AgentManifest } from "@nylorun/core/define";
7
7
  import type { HostEffect } from "@nylorun/harness/run";
8
8
  import type { AbortReason } from "@nylorun/core/harness-api";
9
9
  import type { ModelProvider } from "../core/provider.js";
10
10
  import type { ModelGate } from "../gates/model-gate.js";
11
+ import type { ToolGate } from "../gates/tool-gate.js";
11
12
  import { type McpPool } from "../mcp/pool.js";
12
13
  import { type McpSnapshot } from "../mcp/snapshot.js";
13
14
  import type { SandboxManager } from "../sandbox/manager.js";
@@ -22,7 +23,6 @@ export interface ModelRoute {
22
23
  /** What a session's tool calls are routed by. */
23
24
  export interface ToolRouting {
24
25
  readonly rootManifest: AgentManifest;
25
- readonly pluginRoots: Readonly<Record<string, string>>;
26
26
  readonly mcpSnapshot?: McpSnapshot;
27
27
  /** The session that owns the tree's sandbox, and the sandbox resource it is attached to. */
28
28
  readonly sandboxOwnerId: string;
@@ -46,7 +46,13 @@ export declare function invokeModel(route: ModelRoute, request: HostEffect, sign
46
46
  export declare function abortOn(signal: AbortSignal, kinds: readonly AbortReason[]): AbortSignal;
47
47
  /** True when `request` calls `save_artifact` of the `nylorun.artifacts` capability `manifest` has. */
48
48
  export declare function isSaveArtifactCall(manifest: AgentManifest | undefined, request: HostEffect): boolean;
49
- /** True when `request` calls a tool of a remote (`streamable-http` or `sse`) MCP server. */
49
+ /** True when `request` calls a tool of a declared MCP server (every one is remote). */
50
50
  export declare function isRemoteMcpCall(routing: Pick<ToolRouting, "rootManifest" | "mcpSnapshot">, request: HostEffect): boolean;
51
51
  export declare function callMcpTool(mcp: McpPool, routing: ToolRouting, request: HostEffect, signal: AbortSignal): Promise<unknown>;
52
+ /**
53
+ * Calls an HTTP tool through the Tool Gate (R2 M3), keyed by the effect id: an agent's (the
54
+ * effect's agent used as a tool, or the root), or a flow's HTTP stage or HTTP verifier. Its
55
+ * outcome is the effect's value; a throw leaves the effect `uncertain`.
56
+ */
57
+ export declare function callHttpTool(gate: Pick<ToolGate, "callHttp">, request: HostEffect, signal: AbortSignal): Promise<unknown>;
52
58
  export declare function callSandboxTool(sandbox: SandboxManager, routing: ToolRouting, request: HostEffect, signal: AbortSignal): Promise<unknown>;
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * The calls a harness executes, as pure helpers over what routes them: the Model Gate (or the
3
- * Tenant's provider), the MCP pool, the SandboxManager. No store, no record: the session's
4
- * routing comes with the run (`TurnStart.routing`).
3
+ * Tenant's provider), the Tool Gate, the MCP pool, the SandboxManager. No store, no record: the
4
+ * session's routing comes with the run (`TurnStart.routing`).
5
5
  */
6
6
  import { ARTIFACTS_CAPABILITY_ID, SAVE_ARTIFACT_TOOL } from "@nylorun/core/define";
7
7
  import { runAbortKind } from "@nylorun/harness/api";
8
+ import { httpToolRefOf } from "../gates/http-tool.js";
8
9
  import { classifyThrown } from "../model/classify.js";
9
10
  import { findServer } from "../mcp/pool.js";
10
11
  import { manifestFor, mcpToolOf } from "../mcp/snapshot.js";
@@ -71,15 +72,14 @@ export function isSaveArtifactCall(manifest, request) {
71
72
  request.toolName === SAVE_ARTIFACT_TOOL &&
72
73
  manifest?.capabilities.some((capability) => capability.id === ARTIFACTS_CAPABILITY_ID) === true);
73
74
  }
74
- /** True when `request` calls a tool of a remote (`streamable-http` or `sse`) MCP server. */
75
+ /** True when `request` calls a tool of a declared MCP server (every one is remote). */
75
76
  export function isRemoteMcpCall(routing, request) {
76
77
  if (request.kind !== "tool")
77
78
  return false;
78
79
  const tool = mcpToolOf(routing.mcpSnapshot, request);
79
80
  if (!tool)
80
81
  return false;
81
- const declared = findServer(routing.rootManifest, tool.agentId, tool.capabilityId, tool.serverName);
82
- return declared !== undefined && declared.server.type !== "stdio";
82
+ return findServer(routing.rootManifest, tool.agentId, tool.capabilityId, tool.serverName) !== undefined;
83
83
  }
84
84
  export async function callMcpTool(mcp, routing, request, signal) {
85
85
  const tool = mcpToolOf(routing.mcpSnapshot, request);
@@ -93,11 +93,20 @@ export async function callMcpTool(mcp, routing, request, signal) {
93
93
  serverToolName: tool.serverToolName,
94
94
  args: request.input,
95
95
  manifest: routing.rootManifest,
96
- pluginRoots: routing.pluginRoots,
97
96
  effectId: request.effectId,
98
97
  signal,
99
98
  });
100
99
  }
100
+ /**
101
+ * Calls an HTTP tool through the Tool Gate (R2 M3), keyed by the effect id: an agent's (the
102
+ * effect's agent used as a tool, or the root), or a flow's HTTP stage or HTTP verifier. Its
103
+ * outcome is the effect's value; a throw leaves the effect `uncertain`.
104
+ */
105
+ export async function callHttpTool(gate, request, signal) {
106
+ if (!gate.callHttp)
107
+ throw new Error("This Runtime has no Tool Gate for HTTP tools");
108
+ return gate.callHttp({ tool: httpToolRefOf(request), effectId: request.effectId, turnId: request.turnId, input: request.input }, signal);
109
+ }
101
110
  export async function callSandboxTool(sandbox, routing, request, signal) {
102
111
  const capability = sandboxCapabilityOf(manifestFor(routing.rootManifest, request.agent), request.capabilityId, request.toolName);
103
112
  if (!capability)
@@ -6,7 +6,7 @@ import { type ModelRoute, type ToolRouting } from "./calls.js";
6
6
  export interface HarnessExecutorsOptions {
7
7
  /** Where model calls go. Read per call: a harness process learns its Tenant at `hello`. */
8
8
  readonly model: ModelRoute;
9
- readonly toolGate: Pick<ToolGate, "recovers" | "cancel">;
9
+ readonly toolGate: Pick<ToolGate, "recovers" | "cancel" | "callHttp">;
10
10
  readonly mcp: McpPool;
11
11
  /** The SandboxManager; a harness process creates it once `hello` names the Tenant. */
12
12
  readonly sandbox: () => SandboxManager;
@@ -1,7 +1,8 @@
1
1
  /**
2
- * A harness's executors (F6.1, F6.2): the model route, the Tool Gate, an MCP pool and a
3
- * SandboxManager, injected. They reach no store: a run's routing comes with its `turn.start`,
4
- * and the session's MCP discovery is recorded through core (`session.mcp`, `prepare`).
2
+ * A harness's executors (F6.1, F6.2): the model route, the Tool Gate (remote MCP and HTTP
3
+ * tools), an MCP pool and a SandboxManager, injected. They reach no store: a run's routing comes
4
+ * with its `turn.start`, and the session's MCP discovery is recorded through core (`session.mcp`,
5
+ * `prepare`).
5
6
  *
6
7
  * The in-process harness gets the Tenant's own pool and SandboxManager; a harness process
7
8
  * (`--service harness`, `main.ts`) its own, whose sandbox events it claims from core.
@@ -10,27 +11,34 @@ import { hashManifest } from "@nylorun/core/define";
10
11
  import { toolFixtureModel } from "../core/provider.js";
11
12
  import { serversOf } from "../mcp/pool.js";
12
13
  import { mcpToolOf } from "../mcp/snapshot.js";
13
- import { abortOn, callMcpTool, callSandboxTool, invokeModel, isRemoteMcpCall, isSaveArtifactCall, } from "./calls.js";
14
+ import { isHttpToolCall } from "../gates/http-tool.js";
15
+ import { abortOn, callHttpTool, callMcpTool, callSandboxTool, invokeModel, isRemoteMcpCall, isSaveArtifactCall, } from "./calls.js";
14
16
  /** The Tenant's model of the fixture-model setting. Stateless. */
15
17
  const fixture = toolFixtureModel();
16
18
  export function harnessExecutors(options) {
17
- const recoversMcp = options.toolGate.recovers === true;
18
- const remote = (effect, run) => recoversMcp && isRemoteMcpCall(routingOf(run), effect);
19
+ const recoversTools = options.toolGate.recovers === true;
20
+ const atGate = (effect, run) => {
21
+ const routing = routingOf(run);
22
+ return isRemoteMcpCall(routing, effect) || isHttpToolCall(routing.rootManifest, effect);
23
+ };
24
+ const recovered = (effect, run) => recoversTools && atGate(effect, run);
19
25
  return {
20
26
  model: (effect, signal, run) => invokeModel(options.model, effect, signal, run.start.options.fixtureModel ? fixture : undefined),
21
27
  tool(effect, signal, run) {
22
28
  const routing = routingOf(run);
29
+ // A call at the Tool Gate outlives a shutdown there; a local one finishes and is recorded.
30
+ const kinds = recovered(effect, run) ? ["cancel", "shutdown"] : ["cancel"];
31
+ if (isHttpToolCall(routing.rootManifest, effect))
32
+ return callHttpTool(options.toolGate, effect, abortOn(signal, kinds));
23
33
  if (!mcpToolOf(routing.mcpSnapshot, effect))
24
34
  return callSandboxTool(options.sandbox(), routing, effect, signal);
25
- // A call at the Tool Gate outlives a shutdown there; a local one finishes and is recorded.
26
- const kinds = remote(effect, run) ? ["cancel", "shutdown"] : ["cancel"];
27
35
  return callMcpTool(options.mcp, routing, effect, abortOn(signal, kinds));
28
36
  },
29
37
  recovers: {
30
38
  get model() {
31
39
  return options.model.useVaultModel && options.model.modelGate.recovers === true;
32
40
  },
33
- remoteMcp: remote,
41
+ tool: recovered,
34
42
  },
35
43
  async cancelAtGate(effect) {
36
44
  await options.toolGate.cancel?.({
@@ -59,7 +67,6 @@ export async function prepareMcp(pool, run, record) {
59
67
  sessionId,
60
68
  manifest,
61
69
  manifestHash: hashManifest(manifest),
62
- pluginRoots: routing.pluginRoots,
63
70
  signal: run.signal,
64
71
  });
65
72
  answer = await record({ snapshot: found.snapshot, diagnostics: found.diagnostics });
@@ -68,7 +75,6 @@ export async function prepareMcp(pool, run, record) {
68
75
  const diagnostics = await pool.reconnect({
69
76
  sessionId,
70
77
  manifest,
71
- pluginRoots: routing.pluginRoots,
72
78
  tools: routing.mcpSnapshot.mcpTools,
73
79
  signal: run.signal,
74
80
  });
@@ -86,7 +92,6 @@ export function routingOf(run) {
86
92
  const { routing } = run.start;
87
93
  return {
88
94
  rootManifest: routing.rootManifest,
89
- pluginRoots: routing.pluginRoots,
90
95
  ...(routing.mcpSnapshot ? { mcpSnapshot: routing.mcpSnapshot } : {}),
91
96
  sandboxOwnerId: routing.sandbox?.ownerId ?? run.grant.sessionId,
92
97
  ...(routing.sandbox?.sandboxId === undefined ? {} : { sandboxId: routing.sandbox.sandboxId }),
@@ -1,6 +1,6 @@
1
1
  import type { StackConfig } from "../host/stack-config.js";
2
2
  /**
3
- * `baseline` is the allowlisted environment of MCP stdio servers (`baselineEnvironment`), read
4
- * by `host/main.ts`: nothing here reads the process environment.
3
+ * `baseline` is the allowlisted environment of a pod's sandbox tools (`baselineEnvironment`),
4
+ * read by `host/main.ts`: nothing here reads the process environment.
5
5
  */
6
6
  export declare function runHarness(stack: StackConfig, baseline: Readonly<Record<string, string>>): Promise<void>;
@@ -6,8 +6,7 @@
6
6
  * database, no Restate, no keys.
7
7
  *
8
8
  * Its files live under `NYLORUN_HARNESS_ROOT` (`/harness`): `sandboxes/` (workspaces and their
9
- * records), `plugin-data/`, and `home/` and `tmp/` for MCP stdio servers. `/health` answers on
10
- * 127.0.0.1 only.
9
+ * records). `/health` answers on 127.0.0.1 only.
11
10
  *
12
11
  * In a pod sandbox (`NYLORUN_SANDBOX_KIND=pod`, F7.2) it is that sandbox's engine: it first waits
13
12
  * until the pod's NetworkPolicy is in force (`awaitNetworkPolicy`), then joins with the
@@ -28,20 +27,14 @@ import { podHost } from "./pod.js";
28
27
  import { harnessRunTokens } from "./run-tokens.js";
29
28
  import { startHarnessService } from "./service.js";
30
29
  /**
31
- * `baseline` is the allowlisted environment of MCP stdio servers (`baselineEnvironment`), read
32
- * by `host/main.ts`: nothing here reads the process environment.
30
+ * `baseline` is the allowlisted environment of a pod's sandbox tools (`baselineEnvironment`),
31
+ * read by `host/main.ts`: nothing here reads the process environment.
33
32
  */
34
33
  export async function runHarness(stack, baseline) {
35
34
  const config = stack.harness;
36
35
  const logger = createHostLogger();
37
- const paths = {
38
- sandboxes: join(config.root, "sandboxes"),
39
- pluginData: join(config.root, "plugin-data"),
40
- home: join(config.root, "home"),
41
- tmp: join(config.root, "tmp"),
42
- };
43
- for (const dir of Object.values(paths))
44
- mkdirSync(dir, { recursive: true });
36
+ const paths = { sandboxes: join(config.root, "sandboxes") };
37
+ mkdirSync(paths.sandboxes, { recursive: true });
45
38
  logger.info("host_stack_config", { services: [...stack.services], harness: config.url, gates: config.gatesUrl });
46
39
  // A pod's engine trusts the network only once its NetworkPolicy blocks what it must.
47
40
  let pod;
@@ -62,7 +55,6 @@ export async function runHarness(stack, baseline) {
62
55
  token,
63
56
  ...(pod ? { sandboxBackends: [localBackend({ env: baseline, proxyEnv: () => pod.proxyEnv() })] } : {}),
64
57
  paths,
65
- childEnv: { ...baseline, HOME: paths.home, TMPDIR: paths.tmp },
66
58
  modelGate: httpModelGate({ url: config.gatesUrl, runTokens }),
67
59
  useVaultModel: true,
68
60
  toolGate: httpToolGate({ url: config.gatesUrl, runTokens }),