@nylorun/runtime 0.22.0-beta → 0.24.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 (273) hide show
  1. package/CHANGELOG.md +161 -0
  2. package/README.md +95 -30
  3. package/dist/adapters/execution/restate.d.ts +15 -3
  4. package/dist/adapters/execution/restate.js +78 -84
  5. package/dist/adapters/replication/pgoutput.d.ts +2 -0
  6. package/dist/adapters/replication/pgoutput.js +6 -3
  7. package/dist/adapters/sandbox/local.d.ts +9 -1
  8. package/dist/adapters/sandbox/local.js +16 -4
  9. package/dist/adapters/sandbox/virtual.js +4 -1
  10. package/dist/adapters/streams/s2.js +1 -13
  11. package/dist/api/a2a/endpoint.js +5 -1
  12. package/dist/api/a2a/routes.d.ts +2 -0
  13. package/dist/api/a2a/routes.js +2 -2
  14. package/dist/api/a2a/tasks.js +2 -1
  15. package/dist/api/ag-ui/endpoint.js +4 -2
  16. package/dist/api/ag-ui/history.js +4 -1
  17. package/dist/api/ag-ui/routes.d.ts +4 -1
  18. package/dist/api/ag-ui/routes.js +11 -10
  19. package/dist/api/ag-ui/translate.js +3 -2
  20. package/dist/api/components.d.ts +4953 -1204
  21. package/dist/api/components.js +25 -16
  22. package/dist/api/gate/keys.js +7 -1
  23. package/dist/api/gate/routes.d.ts +6 -0
  24. package/dist/api/gate/routes.js +39 -3
  25. package/dist/api/http/app.js +4 -4
  26. package/dist/api/http/define.d.ts +6 -0
  27. package/dist/api/http/define.js +13 -1
  28. package/dist/api/http/respond.js +1 -1
  29. package/dist/api/http/routes/artifacts.js +35 -8
  30. package/dist/api/http/routes/coverage.d.ts +9 -0
  31. package/dist/api/http/routes/coverage.js +34 -0
  32. package/dist/api/http/routes/environments.d.ts +11 -0
  33. package/dist/api/http/routes/environments.js +283 -0
  34. package/dist/api/http/routes/mcp.d.ts +1 -1
  35. package/dist/api/http/routes/mcp.js +2 -2
  36. package/dist/api/http/routes/me.js +1 -1
  37. package/dist/api/http/routes/reads.d.ts +45 -9
  38. package/dist/api/http/routes/reads.js +54 -5
  39. package/dist/api/http/routes/sessions.js +11 -6
  40. package/dist/api/http/routes/tenant.js +32 -10
  41. package/dist/api/openapi.js +31 -26
  42. package/dist/artifacts/disk.d.ts +59 -0
  43. package/dist/artifacts/disk.js +563 -0
  44. package/dist/artifacts/export.d.ts +1 -1
  45. package/dist/artifacts/export.js +2 -3
  46. package/dist/artifacts/folders.d.ts +6 -3
  47. package/dist/artifacts/folders.js +17 -12
  48. package/dist/artifacts/service.d.ts +2 -1
  49. package/dist/artifacts/service.js +6 -1
  50. package/dist/artifacts/workspace.d.ts +1 -1
  51. package/dist/artifacts/workspace.js +1 -1
  52. package/dist/core/flow-host.d.ts +3 -22
  53. package/dist/core/flow-host.js +11 -37
  54. package/dist/core/provider.d.ts +3 -2
  55. package/dist/core/provider.js +5 -37
  56. package/dist/core/sandbox-routes.d.ts +2 -21
  57. package/dist/core/sandbox-routes.js +10 -43
  58. package/dist/execution/types.d.ts +11 -9
  59. package/dist/execution/types.js +5 -7
  60. package/dist/gates/contract.d.ts +3 -24
  61. package/dist/gates/contract.js +1 -36
  62. package/dist/gates/egress-credentials.d.ts +9 -0
  63. package/dist/gates/egress-credentials.js +11 -4
  64. package/dist/gates/egress.d.ts +28 -1
  65. package/dist/gates/egress.js +115 -10
  66. package/dist/gates/fixture-model.d.ts +28 -0
  67. package/dist/gates/fixture-model.js +92 -0
  68. package/dist/gates/handler.js +4 -4
  69. package/dist/gates/http-tool.d.ts +6 -2
  70. package/dist/gates/http-tool.js +3 -5
  71. package/dist/gates/in-process.d.ts +5 -0
  72. package/dist/gates/in-process.js +12 -1
  73. package/dist/gates/journal.d.ts +30 -0
  74. package/dist/gates/journal.js +52 -0
  75. package/dist/gates/mcp-handler.d.ts +4 -0
  76. package/dist/gates/mcp-handler.js +5 -1
  77. package/dist/gates/meter.d.ts +10 -2
  78. package/dist/gates/meter.js +20 -5
  79. package/dist/gates/policy.d.ts +49 -0
  80. package/dist/gates/policy.js +134 -0
  81. package/dist/gates/tenant-vaults.d.ts +7 -7
  82. package/dist/gates/tenant-vaults.js +5 -5
  83. package/dist/gates/tool-calls.d.ts +10 -5
  84. package/dist/gates/tool-calls.js +28 -10
  85. package/dist/gates/tool-client.d.ts +8 -0
  86. package/dist/gates/tool-client.js +27 -11
  87. package/dist/gates/tool-contract.d.ts +10 -68
  88. package/dist/gates/tool-contract.js +1 -85
  89. package/dist/gates/tool-gate.d.ts +1 -1
  90. package/dist/harness/calls.d.ts +12 -5
  91. package/dist/harness/calls.js +21 -12
  92. package/dist/harness/executors.js +12 -9
  93. package/dist/harness/main.js +18 -5
  94. package/dist/harness/pod.d.ts +34 -0
  95. package/dist/harness/pod.js +41 -0
  96. package/dist/harness/service.d.ts +0 -1
  97. package/dist/harness/service.js +13 -5
  98. package/dist/harness/setup.d.ts +27 -0
  99. package/dist/harness/setup.js +150 -0
  100. package/dist/harness/ws-client.js +3 -2
  101. package/dist/harness/ws-port.d.ts +1 -5
  102. package/dist/harness/ws-port.js +1 -5
  103. package/dist/harness-api/in-process.js +3 -3
  104. package/dist/harness-api/record.d.ts +15 -1
  105. package/dist/harness-api/record.js +174 -44
  106. package/dist/harness-api/redact.d.ts +3 -0
  107. package/dist/harness-api/redact.js +45 -0
  108. package/dist/harness-api/server.d.ts +8 -0
  109. package/dist/harness-api/server.js +93 -13
  110. package/dist/harness-api/start.d.ts +10 -3
  111. package/dist/harness-api/start.js +40 -10
  112. package/dist/harness-api/tool-journal.d.ts +96 -0
  113. package/dist/harness-api/tool-journal.js +102 -0
  114. package/dist/harness-api/tool-status.d.ts +13 -0
  115. package/dist/harness-api/tool-status.js +26 -0
  116. package/dist/harness-api/workspace.d.ts +6 -3
  117. package/dist/harness-api/workspace.js +27 -11
  118. package/dist/harness-api/ws-server.d.ts +11 -3
  119. package/dist/harness-api/ws-server.js +94 -15
  120. package/dist/host/execution.d.ts +8 -6
  121. package/dist/host/gates.d.ts +2 -1
  122. package/dist/host/gates.js +10 -2
  123. package/dist/host/main.js +64 -21
  124. package/dist/host/operate.js +67 -5
  125. package/dist/host/stack-config.d.ts +70 -0
  126. package/dist/host/stack-config.js +67 -1
  127. package/dist/infra/execution.d.ts +18 -1
  128. package/dist/infra/execution.js +28 -4
  129. package/dist/infra/index.d.ts +1 -1
  130. package/dist/keys/client.js +4 -1
  131. package/dist/keys/keys.d.ts +5 -5
  132. package/dist/keys/keys.js +5 -7
  133. package/dist/management-openapi.json +999 -2211
  134. package/dist/mcp/connect.d.ts +25 -20
  135. package/dist/mcp/connect.js +29 -30
  136. package/dist/mcp/pool.d.ts +2 -2
  137. package/dist/mcp/pool.js +1 -1
  138. package/dist/mcp/preview.d.ts +3 -3
  139. package/dist/mcp/preview.js +10 -20
  140. package/dist/mcp/snapshot.d.ts +5 -11
  141. package/dist/mcp/snapshot.js +6 -7
  142. package/dist/model/pi-model.js +8 -0
  143. package/dist/openapi.json +6955 -2526
  144. package/dist/reads/types.d.ts +16 -3
  145. package/dist/record/append.d.ts +3 -1
  146. package/dist/record/append.js +1 -0
  147. package/dist/record/envelope.d.ts +5 -1
  148. package/dist/record/envelope.js +7 -3
  149. package/dist/record/environment.d.ts +25 -0
  150. package/dist/record/environment.js +44 -0
  151. package/dist/record/index.d.ts +1 -1
  152. package/dist/record/index.js +1 -1
  153. package/dist/retry.d.ts +21 -0
  154. package/dist/retry.js +34 -0
  155. package/dist/sandbox/disk-fs.d.ts +95 -0
  156. package/dist/sandbox/disk-fs.js +206 -0
  157. package/dist/sandbox/join.d.ts +17 -18
  158. package/dist/sandbox/join.js +46 -20
  159. package/dist/sandbox/manager.d.ts +16 -8
  160. package/dist/sandbox/manager.js +33 -17
  161. package/dist/sandbox/placement.d.ts +13 -12
  162. package/dist/sandbox/placement.js +29 -12
  163. package/dist/sandbox/pods/client.d.ts +6 -1
  164. package/dist/sandbox/pods/lifecycle.d.ts +28 -27
  165. package/dist/sandbox/pods/lifecycle.js +14 -26
  166. package/dist/sandbox/pods/reconcile.js +21 -15
  167. package/dist/sandbox/pods/spec.d.ts +15 -13
  168. package/dist/sandbox/pods/spec.js +16 -20
  169. package/dist/sandbox/records.d.ts +2 -2
  170. package/dist/sandbox/records.js +3 -3
  171. package/dist/sandbox/resolve.d.ts +35 -27
  172. package/dist/sandbox/resolve.js +66 -41
  173. package/dist/sandbox/session-sandbox.js +1 -1
  174. package/dist/sandbox/setup.d.ts +61 -0
  175. package/dist/sandbox/setup.js +123 -0
  176. package/dist/sandbox/share.d.ts +11 -21
  177. package/dist/sandbox/share.js +12 -41
  178. package/dist/sandbox/tenant-config.d.ts +12 -14
  179. package/dist/sandbox/tenant-config.js +12 -17
  180. package/dist/sandbox/types.d.ts +6 -0
  181. package/dist/store/postgres/control.js +8 -1
  182. package/dist/store/postgres/drizzle/0018_wake_outbox_retries.sql +3 -0
  183. package/dist/store/postgres/drizzle/0019_sandbox_signal_outbox.sql +18 -0
  184. package/dist/store/postgres/drizzle/0020_environments.sql +63 -0
  185. package/dist/store/postgres/drizzle/0021_disk_versions.sql +7 -0
  186. package/dist/store/postgres/drizzle/0022_model_usage_timing.sql +5 -0
  187. package/dist/store/postgres/drizzle/0023_artifact_pages.sql +1 -0
  188. package/dist/store/postgres/drizzle/meta/_journal.json +42 -0
  189. package/dist/store/postgres/reads.js +117 -17
  190. package/dist/store/postgres/record-writer.d.ts +4 -4
  191. package/dist/store/postgres/record-writer.js +9 -9
  192. package/dist/store/postgres/record.d.ts +7 -0
  193. package/dist/store/postgres/record.js +23 -2
  194. package/dist/store/postgres/schema.d.ts +1213 -779
  195. package/dist/store/postgres/schema.js +136 -76
  196. package/dist/store/postgres/store.js +283 -117
  197. package/dist/store/types.d.ts +206 -88
  198. package/dist/streams/relay/core.js +1 -13
  199. package/dist/tenant/advance.d.ts +7 -6
  200. package/dist/tenant/advance.js +121 -49
  201. package/dist/tenant/artifact-tool.js +3 -4
  202. package/dist/tenant/commands.d.ts +15 -2
  203. package/dist/tenant/commands.js +94 -14
  204. package/dist/tenant/context.d.ts +67 -33
  205. package/dist/tenant/context.js +4 -15
  206. package/dist/tenant/control.d.ts +8 -1
  207. package/dist/tenant/control.js +2 -0
  208. package/dist/tenant/effects.d.ts +1 -1
  209. package/dist/tenant/effects.js +37 -20
  210. package/dist/tenant/environments.d.ts +167 -0
  211. package/dist/tenant/environments.js +823 -0
  212. package/dist/tenant/harness-tokens.d.ts +21 -0
  213. package/dist/tenant/harness-tokens.js +61 -0
  214. package/dist/tenant/host-token.d.ts +1 -1
  215. package/dist/tenant/host-token.js +2 -4
  216. package/dist/tenant/identity-file.d.ts +4 -4
  217. package/dist/tenant/identity-file.js +17 -8
  218. package/dist/tenant/issuers.js +3 -3
  219. package/dist/tenant/principals.js +1 -1
  220. package/dist/tenant/reset.js +3 -3
  221. package/dist/tenant/runtime.d.ts +6 -1
  222. package/dist/tenant/runtime.js +30 -4
  223. package/dist/tenant/scheduler.d.ts +7 -0
  224. package/dist/tenant/scheduler.js +38 -7
  225. package/dist/tenant/session-streams.d.ts +0 -1
  226. package/dist/tenant/session-streams.js +1 -13
  227. package/dist/tenant/session.d.ts +3 -3
  228. package/dist/tenant/session.js +0 -14
  229. package/dist/tenant/sessions.d.ts +13 -13
  230. package/dist/tenant/sessions.js +61 -138
  231. package/dist/tenant/signing-keys.d.ts +5 -1
  232. package/dist/tenant/status.js +3 -3
  233. package/dist/tenant/streams.js +14 -29
  234. package/dist/tenant/sweep.d.ts +39 -12
  235. package/dist/tenant/sweep.js +168 -63
  236. package/dist/tenant/transcript.d.ts +210 -20
  237. package/dist/tenant/transcript.js +62 -11
  238. package/dist/tenant/turn-timing.d.ts +43 -0
  239. package/dist/tenant/turn-timing.js +39 -0
  240. package/dist/tenant/types.d.ts +2 -0
  241. package/dist/traces/ids.d.ts +42 -0
  242. package/dist/traces/ids.js +85 -0
  243. package/dist/traces/key.d.ts +6 -0
  244. package/dist/traces/key.js +37 -0
  245. package/dist/traces/map.d.ts +113 -0
  246. package/dist/traces/map.js +317 -0
  247. package/dist/traces/options.d.ts +7 -0
  248. package/dist/traces/options.js +1 -0
  249. package/dist/traces/otlp.d.ts +42 -0
  250. package/dist/traces/otlp.js +84 -0
  251. package/dist/traces/projector.d.ts +58 -0
  252. package/dist/traces/projector.js +200 -0
  253. package/dist/traces/read.d.ts +23 -0
  254. package/dist/traces/read.js +16 -0
  255. package/dist/vault/coverage.d.ts +26 -0
  256. package/dist/vault/coverage.js +64 -0
  257. package/dist/vault/error.d.ts +11 -1
  258. package/dist/vault/error.js +5 -1
  259. package/dist/vault/service.d.ts +47 -48
  260. package/dist/vault/service.js +321 -382
  261. package/dist/vault/sources.d.ts +5 -16
  262. package/dist/vault/sources.js +6 -8
  263. package/dist/version.d.ts +1 -1
  264. package/dist/version.js +2 -2
  265. package/package.json +14 -13
  266. package/dist/api/http/routes/sandboxes.d.ts +0 -9
  267. package/dist/api/http/routes/sandboxes.js +0 -153
  268. package/dist/api/http/routes/vaults.d.ts +0 -10
  269. package/dist/api/http/routes/vaults.js +0 -139
  270. package/dist/record/sandbox.d.ts +0 -25
  271. package/dist/record/sandbox.js +0 -43
  272. package/dist/tenant/sandboxes.d.ts +0 -122
  273. package/dist/tenant/sandboxes.js +0 -562
@@ -0,0 +1,27 @@
1
+ import type { ExecRequest, ExecResult } from "../sandbox/types.js";
2
+ import type { PodHost } from "./pod.js";
3
+ /** How often a failed setup asks whether to run again. */
4
+ export declare const SETUP_RETRY_POLL_MS = 5000;
5
+ export interface DiskSetupOptions {
6
+ readonly host: Pick<PodHost, "setup" | "setupState" | "reportSetup" | "setupFile"> & {
7
+ /** The volume starts from a disk version (R2d step 3): it holds what setup made. */
8
+ readonly seeded?: boolean;
9
+ };
10
+ /** Runs one command as the sandbox tools do (`localExec`). */
11
+ readonly exec: (request: ExecRequest, signal: AbortSignal) => Promise<ExecResult>;
12
+ /** The volume's id file (`/harness/volume-id`). */
13
+ readonly volumeFile: string;
14
+ /** The marker (`/harness/setup.json`). */
15
+ readonly markerFile: string;
16
+ readonly logger: {
17
+ info(message: string, fields?: Record<string, unknown>): void;
18
+ warn(message: string, fields?: Record<string, unknown>): void;
19
+ };
20
+ readonly pollMs?: number;
21
+ readonly signal?: AbortSignal;
22
+ }
23
+ /**
24
+ * Runs the disk's setup when this volume has not had it, reports how it ended, and after a
25
+ * failure waits for core to ask for it again. Resolves once the setup is done (or there is none).
26
+ */
27
+ export declare function prepareDisk(options: DiskSetupOptions): Promise<void>;
@@ -0,0 +1,150 @@
1
+ /**
2
+ * The disk's setup in a pod Environment's engine (R2d step 2): after it joins and before it takes
3
+ * any turn, the engine copies the recipe's input files and runs its setup commands, once per
4
+ * volume. A marker on the volume (`/harness/setup.json`, `{ volumeId, recipeVersion, status }`)
5
+ * says it was done: a resume finds it and skips, a reset (a new volume, a new volume id) runs it
6
+ * again. Commands run as the sandbox tools' do (`localExec`): `/bin/sh -c` in `cwd`, with the
7
+ * Environment's variables and secrets (as the sentinel) and egress through egress-gate.
8
+ *
9
+ * A failure is reported to core, which fails the pod and the turn waiting for it; the engine then
10
+ * polls until a turn start asks the pod to run again, and runs the setup again from the start.
11
+ */
12
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
13
+ import { randomUUID } from "node:crypto";
14
+ import { dirname, posix } from "node:path";
15
+ /** How often a failed setup asks whether to run again. */
16
+ export const SETUP_RETRY_POLL_MS = 5_000;
17
+ /** The end of a failed command's output kept in its report. */
18
+ const REPORT_TAIL = 4 * 1024;
19
+ async function readText(path) {
20
+ try {
21
+ return (await readFile(path, "utf8")).trim();
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ /** Writes `bytes` at `path`, by way of a temporary name, creating its directory. */
28
+ async function writeAtomic(path, bytes) {
29
+ await mkdir(dirname(path), { recursive: true });
30
+ const next = `${path}.${randomUUID()}.tmp`;
31
+ await writeFile(next, bytes);
32
+ await rename(next, path);
33
+ }
34
+ /** A folder entry's path joined under `base`, refused when it would leave it. */
35
+ function under(base, relative) {
36
+ const joined = posix.normalize(posix.join(base, relative));
37
+ if (joined !== base && !joined.startsWith(`${base.replace(/\/$/, "")}/`))
38
+ throw new Error(`${relative} would leave ${base}`);
39
+ return joined;
40
+ }
41
+ /** Copies input file `file` into place: a file artifact at its path, a folder under it. */
42
+ async function copyFile(host, file) {
43
+ const first = await host.setupFile(file.index);
44
+ if (!first.ok)
45
+ throw new Error(`input file ${file.index + 1} answered ${first.status}`);
46
+ if (first.headers.get("x-nylorun-artifact-kind") !== "folder") {
47
+ await writeAtomic(file.path, new Uint8Array(await first.arrayBuffer()));
48
+ return;
49
+ }
50
+ const { entries } = (await first.json());
51
+ for (const entry of entries) {
52
+ const answer = await host.setupFile(file.index, entry.path);
53
+ if (!answer.ok)
54
+ throw new Error(`input file ${file.index + 1}, ${entry.path}, answered ${answer.status}`);
55
+ await writeAtomic(under(file.path, entry.path), new Uint8Array(await answer.arrayBuffer()));
56
+ }
57
+ }
58
+ /** Runs `setup` once: files first, then commands in order; the report of how it ended. */
59
+ async function runOnce(options, setup) {
60
+ for (const file of setup.files) {
61
+ try {
62
+ await copyFile(options.host, file);
63
+ }
64
+ catch (error) {
65
+ return { status: "failed", output: error instanceof Error ? error.message : String(error) };
66
+ }
67
+ }
68
+ for (const [index, command] of setup.commands.entries()) {
69
+ options.logger.info("environment_setup_command", { index, cwd: command.cwd });
70
+ await mkdir(command.cwd, { recursive: true }).catch(() => undefined);
71
+ let result;
72
+ try {
73
+ result = await options.exec({ command: command.command, cwd: command.cwd, timeoutMs: command.timeoutMs, env: setup.environment }, options.signal ?? new AbortController().signal);
74
+ }
75
+ catch (error) {
76
+ return { status: "failed", index, output: error instanceof Error ? error.message : String(error) };
77
+ }
78
+ if (result.exitCode !== 0) {
79
+ const output = `${result.stdout}${result.stderr ? `\n${result.stderr}` : ""}${result.timedOut ? "\n[timed out]" : ""}`;
80
+ return { status: "failed", index, exitCode: result.exitCode, output: output.slice(-REPORT_TAIL) };
81
+ }
82
+ }
83
+ return { status: "ok" };
84
+ }
85
+ /**
86
+ * Runs the disk's setup when this volume has not had it, reports how it ended, and after a
87
+ * failure waits for core to ask for it again. Resolves once the setup is done (or there is none).
88
+ */
89
+ export async function prepareDisk(options) {
90
+ let setup = options.host.setup;
91
+ const volumeId = await readText(options.volumeFile);
92
+ if (options.host.seeded) {
93
+ // A volume seeded from a disk version: the version holds what setup made, so mark it done.
94
+ if (volumeId) {
95
+ const done = { volumeId, recipeVersion: setup?.recipeVersion ?? 0, status: "ok" };
96
+ await writeAtomic(options.markerFile, new TextEncoder().encode(`${JSON.stringify(done)}\n`));
97
+ }
98
+ options.logger.info("environment_setup_skipped", { reason: "seeded" });
99
+ return;
100
+ }
101
+ if (!setup)
102
+ return;
103
+ const marker = await readText(options.markerFile);
104
+ if (marker && volumeId) {
105
+ try {
106
+ const done = JSON.parse(marker);
107
+ if (done.volumeId === volumeId && done.status === "ok")
108
+ return;
109
+ }
110
+ catch {
111
+ /* a broken marker: run the setup again */
112
+ }
113
+ }
114
+ for (;;) {
115
+ if (options.signal?.aborted)
116
+ return;
117
+ options.logger.info("environment_setup_started", { recipeVersion: setup.recipeVersion });
118
+ const report = await runOnce(options, setup);
119
+ if (report.status === "ok") {
120
+ if (volumeId) {
121
+ const done = { volumeId, recipeVersion: setup.recipeVersion, status: "ok" };
122
+ await writeAtomic(options.markerFile, new TextEncoder().encode(`${JSON.stringify(done)}\n`));
123
+ }
124
+ await options.host.reportSetup(report).catch((error) => options.logger.warn("environment_setup_report_failed", {
125
+ message: error instanceof Error ? error.message : String(error),
126
+ }));
127
+ options.logger.info("environment_setup_done", { recipeVersion: setup.recipeVersion });
128
+ return;
129
+ }
130
+ options.logger.warn("environment_setup_failed", { index: report.index, exitCode: report.exitCode });
131
+ let reported = false;
132
+ // Report it, then wait until a turn start asks the pod to run again, and run it again.
133
+ for (;;) {
134
+ if (!reported)
135
+ reported = await options.host.reportSetup(report).then(() => true, () => false);
136
+ await new Promise((resolve) => setTimeout(resolve, options.pollMs ?? SETUP_RETRY_POLL_MS));
137
+ if (options.signal?.aborted)
138
+ return;
139
+ if (!reported)
140
+ continue;
141
+ const state = await options.host.setupState().catch(() => undefined);
142
+ if (!state?.retry)
143
+ continue;
144
+ if (!state.setup)
145
+ return;
146
+ setup = state.setup;
147
+ break;
148
+ }
149
+ }
150
+ }
@@ -9,7 +9,8 @@
9
9
  import { createChannel } from "@nylorun/core/harness-api";
10
10
  import { createHarness } from "@nylorun/harness/api";
11
11
  import { WebSocket } from "ws";
12
- import { HARNESS_API_HEADER, HARNESS_MAX_PAYLOAD, wsPort } from "./ws-port.js";
12
+ import { HARNESS_API_HEADER, HARNESS_API_TRANSPORT, HARNESS_MAX_PAYLOAD } from "@nylorun/core/harness-api";
13
+ import { wsPort } from "./ws-port.js";
13
14
  export function connectHarness(options) {
14
15
  const { logger } = options;
15
16
  const backoff = options.backoff ?? { minMs: 500, maxMs: 10_000 };
@@ -23,7 +24,7 @@ export function connectHarness(options) {
23
24
  const token = typeof options.token === "string" ? options.token : await options.token();
24
25
  return new Promise((resolve, reject) => {
25
26
  const socket = new WebSocket(options.url, {
26
- headers: { authorization: `Bearer ${token}`, [HARNESS_API_HEADER]: "1" },
27
+ headers: { authorization: `Bearer ${token}`, [HARNESS_API_HEADER]: HARNESS_API_TRANSPORT },
27
28
  maxPayload: HARNESS_MAX_PAYLOAD,
28
29
  handshakeTimeout: 10_000,
29
30
  });
@@ -6,11 +6,7 @@
6
6
  */
7
7
  import type { Port } from "@nylorun/core/harness-api";
8
8
  import { WebSocket } from "ws";
9
- /** The URL path of the Harness API, and the header naming its version. */
10
- export declare const HARNESS_API_PATH = "/nylorun/harness/v1";
11
- export declare const HARNESS_API_HEADER = "nylorun-harness-api";
12
- /** Largest frame either end accepts. */
13
- export declare const HARNESS_MAX_PAYLOAD: number;
9
+ export { HARNESS_API_HEADER, HARNESS_API_PATH, HARNESS_API_TRANSPORT, HARNESS_MAX_PAYLOAD, } from "@nylorun/core/harness-api";
14
10
  export declare const DEFAULT_PING_MS = 30000;
15
11
  export declare const DEFAULT_SILENCE_MS = 90000;
16
12
  export interface WsPortOptions {
@@ -1,9 +1,5 @@
1
1
  import { WebSocket } from "ws";
2
- /** The URL path of the Harness API, and the header naming its version. */
3
- export const HARNESS_API_PATH = "/nylorun/harness/v1";
4
- export const HARNESS_API_HEADER = "nylorun-harness-api";
5
- /** Largest frame either end accepts. */
6
- export const HARNESS_MAX_PAYLOAD = 64 * 1024 * 1024;
2
+ export { HARNESS_API_HEADER, HARNESS_API_PATH, HARNESS_API_TRANSPORT, HARNESS_MAX_PAYLOAD, } from "@nylorun/core/harness-api";
7
3
  export const DEFAULT_PING_MS = 30_000;
8
4
  export const DEFAULT_SILENCE_MS = 90_000;
9
5
  export function wsPort(socket, options = {}) {
@@ -9,7 +9,7 @@
9
9
  * SandboxManager and no store, as `--service harness` runs one.
10
10
  */
11
11
  import { randomBytes } from "node:crypto";
12
- import { memoryChannels } from "@nylorun/core/harness-api";
12
+ import { DEFAULT_HARNESS, memoryChannels } from "@nylorun/core/harness-api";
13
13
  import { createHarness } from "@nylorun/harness/api";
14
14
  import { harnessExecutors } from "../harness/executors.js";
15
15
  import { startHarnessService } from "../harness/service.js";
@@ -36,7 +36,8 @@ export async function startInProcessHarness(ctx, tools, options = {}) {
36
36
  sandbox: () => tools.sandbox,
37
37
  }),
38
38
  logger: ctx.config.logger,
39
- name: "in-process",
39
+ // Our harness: its hello names our harness id (R4.1).
40
+ name: DEFAULT_HARNESS,
40
41
  });
41
42
  await harness.start();
42
43
  return {
@@ -77,7 +78,6 @@ export async function startLoopbackHarness(ctx, options = {}) {
77
78
  ...(ctx.config.delivery ? { delivery: ctx.config.delivery } : {}),
78
79
  ...(options.sandboxBackends ? { sandboxBackends: options.sandboxBackends } : {}),
79
80
  logger: quietLogger(ctx),
80
- name: "loopback",
81
81
  ephemeral: ctx.config.mode === "ephemeral",
82
82
  backoff: { minMs: 50, maxMs: 500 },
83
83
  });
@@ -11,8 +11,15 @@
11
11
  *
12
12
  * Rows store the request's hash (`requestHash`) and, for a model call, the request without its
13
13
  * prompt: drift is a hash compare. Rows written before carry their full request, hashed on read.
14
+ *
15
+ * Every row a run journals keeps when it was journaled (`startedAt`, R7.1), and a rejoin keeps
16
+ * it: an outcome's `durationMs` is the journal's window, from the intent to the outcome. A model
17
+ * call's outcome event also carries what the meter recorded for it (`modelOutcomeFacts`). A tool
18
+ * row keeps its span's context (`traceparent`, R7.4), which the `execute` answer carries to the
19
+ * harness and the Tool Gate reads with the row.
14
20
  */
15
21
  import { type EffectIntent, type IntentAnswer, type OutcomeAnswer, type RecordedOutcome } from "@nylorun/core/harness-api";
22
+ import type { EventWriter } from "@nylorun/core/contracts";
16
23
  import { type Lease, type Session, type TenantContext } from "../tenant/context.js";
17
24
  import type { Tx } from "../store/types.js";
18
25
  /** What a run's journal writes are scoped by: the advance's lease and its signal. */
@@ -20,6 +27,13 @@ export interface RecordScope {
20
27
  readonly ctx: TenantContext;
21
28
  readonly lease: Lease;
22
29
  readonly signal: AbortSignal;
30
+ /** The tools the run's harness declared it runs itself (`hello` `capabilities.tools`, R4.2). */
31
+ readonly nativeTools?: ReadonlySet<string>;
32
+ /**
33
+ * Who reported what this scope records (R4.9): the run's harness, so the events derived from
34
+ * its intents and outcomes are its claim. Absent, core recorded what it saw itself.
35
+ */
36
+ readonly writer?: EventWriter;
23
37
  }
24
38
  /** The hash a journal row's request was recorded with. */
25
39
  export declare function hashOf(row: {
@@ -41,7 +55,7 @@ export declare function recordIntent(scope: RecordScope, effect: EffectIntent, r
41
55
  * `error` that left it uncertain. Only a cancel discards an outcome in hand (§10.7): after any
42
56
  * other abort (shutdown, deadline) it is recorded, so the next advance replays it.
43
57
  */
44
- export declare function recordOutcome(scope: RecordScope, effectId: string, result: {
58
+ export declare function recordOutcome(scope: RecordScope, effectId: string, reported: {
45
59
  value: unknown;
46
60
  } | {
47
61
  error: string;