@nodetool-ai/execution 0.8.1

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 (231) hide show
  1. package/README.md +129 -0
  2. package/dist/.nodetool-build-stamp +1 -0
  3. package/dist/app-debug/app-spec.d.ts +94 -0
  4. package/dist/app-debug/app-spec.d.ts.map +1 -0
  5. package/dist/app-debug/app-spec.js +710 -0
  6. package/dist/app-debug/app-spec.js.map +1 -0
  7. package/dist/app-debug/application-target.d.ts +53 -0
  8. package/dist/app-debug/application-target.d.ts.map +1 -0
  9. package/dist/app-debug/application-target.js +126 -0
  10. package/dist/app-debug/application-target.js.map +1 -0
  11. package/dist/app-debug/bundle-target.d.ts +21 -0
  12. package/dist/app-debug/bundle-target.d.ts.map +1 -0
  13. package/dist/app-debug/bundle-target.js +51 -0
  14. package/dist/app-debug/bundle-target.js.map +1 -0
  15. package/dist/app-debug/graph-shape.d.ts +14 -0
  16. package/dist/app-debug/graph-shape.d.ts.map +1 -0
  17. package/dist/app-debug/graph-shape.js +23 -0
  18. package/dist/app-debug/graph-shape.js.map +1 -0
  19. package/dist/app-debug/index.d.ts +26 -0
  20. package/dist/app-debug/index.d.ts.map +1 -0
  21. package/dist/app-debug/index.js +19 -0
  22. package/dist/app-debug/index.js.map +1 -0
  23. package/dist/app-debug/markdown.d.ts +6 -0
  24. package/dist/app-debug/markdown.d.ts.map +1 -0
  25. package/dist/app-debug/markdown.js +133 -0
  26. package/dist/app-debug/markdown.js.map +1 -0
  27. package/dist/app-debug/runtime.d.ts +267 -0
  28. package/dist/app-debug/runtime.d.ts.map +1 -0
  29. package/dist/app-debug/runtime.js +633 -0
  30. package/dist/app-debug/runtime.js.map +1 -0
  31. package/dist/app-debug/script-operation.d.ts +58 -0
  32. package/dist/app-debug/script-operation.d.ts.map +1 -0
  33. package/dist/app-debug/script-operation.js +44 -0
  34. package/dist/app-debug/script-operation.js.map +1 -0
  35. package/dist/app-debug/simulate.d.ts +85 -0
  36. package/dist/app-debug/simulate.d.ts.map +1 -0
  37. package/dist/app-debug/simulate.js +991 -0
  38. package/dist/app-debug/simulate.js.map +1 -0
  39. package/dist/app-debug/summarize.d.ts +64 -0
  40. package/dist/app-debug/summarize.d.ts.map +1 -0
  41. package/dist/app-debug/summarize.js +65 -0
  42. package/dist/app-debug/summarize.js.map +1 -0
  43. package/dist/app-debug/types.d.ts +343 -0
  44. package/dist/app-debug/types.d.ts.map +1 -0
  45. package/dist/app-debug/types.js +2 -0
  46. package/dist/app-debug/types.js.map +1 -0
  47. package/dist/cost-ledger.d.ts +147 -0
  48. package/dist/cost-ledger.d.ts.map +1 -0
  49. package/dist/cost-ledger.js +288 -0
  50. package/dist/cost-ledger.js.map +1 -0
  51. package/dist/debug/collector.d.ts +28 -0
  52. package/dist/debug/collector.d.ts.map +1 -0
  53. package/dist/debug/collector.js +284 -0
  54. package/dist/debug/collector.js.map +1 -0
  55. package/dist/debug/index.d.ts +15 -0
  56. package/dist/debug/index.d.ts.map +1 -0
  57. package/dist/debug/index.js +16 -0
  58. package/dist/debug/index.js.map +1 -0
  59. package/dist/debug/types.d.ts +179 -0
  60. package/dist/debug/types.d.ts.map +1 -0
  61. package/dist/debug/types.js +11 -0
  62. package/dist/debug/types.js.map +1 -0
  63. package/dist/debug/verdict.d.ts +27 -0
  64. package/dist/debug/verdict.d.ts.map +1 -0
  65. package/dist/debug/verdict.js +51 -0
  66. package/dist/debug/verdict.js.map +1 -0
  67. package/dist/executor-resolver.d.ts +13 -0
  68. package/dist/executor-resolver.d.ts.map +1 -0
  69. package/dist/executor-resolver.js +13 -0
  70. package/dist/executor-resolver.js.map +1 -0
  71. package/dist/fal-output-decoder.d.ts +36 -0
  72. package/dist/fal-output-decoder.d.ts.map +1 -0
  73. package/dist/fal-output-decoder.js +129 -0
  74. package/dist/fal-output-decoder.js.map +1 -0
  75. package/dist/generation-lifecycle.d.ts +54 -0
  76. package/dist/generation-lifecycle.d.ts.map +1 -0
  77. package/dist/generation-lifecycle.js +431 -0
  78. package/dist/generation-lifecycle.js.map +1 -0
  79. package/dist/generation-recovery-worker.d.ts +100 -0
  80. package/dist/generation-recovery-worker.d.ts.map +1 -0
  81. package/dist/generation-recovery-worker.js +995 -0
  82. package/dist/generation-recovery-worker.js.map +1 -0
  83. package/dist/generation-tracker.d.ts +83 -0
  84. package/dist/generation-tracker.d.ts.map +1 -0
  85. package/dist/generation-tracker.js +436 -0
  86. package/dist/generation-tracker.js.map +1 -0
  87. package/dist/index.d.ts +28 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +21 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/js-script-debug/index.d.ts +13 -0
  92. package/dist/js-script-debug/index.d.ts.map +1 -0
  93. package/dist/js-script-debug/index.js +12 -0
  94. package/dist/js-script-debug/index.js.map +1 -0
  95. package/dist/js-script-debug/markdown.d.ts +6 -0
  96. package/dist/js-script-debug/markdown.d.ts.map +1 -0
  97. package/dist/js-script-debug/markdown.js +62 -0
  98. package/dist/js-script-debug/markdown.js.map +1 -0
  99. package/dist/js-script-debug/outputs.d.ts +20 -0
  100. package/dist/js-script-debug/outputs.d.ts.map +1 -0
  101. package/dist/js-script-debug/outputs.js +30 -0
  102. package/dist/js-script-debug/outputs.js.map +1 -0
  103. package/dist/js-script-debug/report.d.ts +15 -0
  104. package/dist/js-script-debug/report.d.ts.map +1 -0
  105. package/dist/js-script-debug/report.js +90 -0
  106. package/dist/js-script-debug/report.js.map +1 -0
  107. package/dist/js-script-debug/types.d.ts +63 -0
  108. package/dist/js-script-debug/types.d.ts.map +1 -0
  109. package/dist/js-script-debug/types.js +10 -0
  110. package/dist/js-script-debug/types.js.map +1 -0
  111. package/dist/js-script-debug/validate.d.ts +38 -0
  112. package/dist/js-script-debug/validate.d.ts.map +1 -0
  113. package/dist/js-script-debug/validate.js +137 -0
  114. package/dist/js-script-debug/validate.js.map +1 -0
  115. package/dist/message-stream.d.ts +33 -0
  116. package/dist/message-stream.d.ts.map +1 -0
  117. package/dist/message-stream.js +58 -0
  118. package/dist/message-stream.js.map +1 -0
  119. package/dist/normalize-graph.d.ts +13 -0
  120. package/dist/normalize-graph.d.ts.map +1 -0
  121. package/dist/normalize-graph.js +63 -0
  122. package/dist/normalize-graph.js.map +1 -0
  123. package/dist/output-names.d.ts +13 -0
  124. package/dist/output-names.d.ts.map +1 -0
  125. package/dist/output-names.js +13 -0
  126. package/dist/output-names.js.map +1 -0
  127. package/dist/predicates.d.ts +6 -0
  128. package/dist/predicates.d.ts.map +1 -0
  129. package/dist/predicates.js +6 -0
  130. package/dist/predicates.js.map +1 -0
  131. package/dist/preflight.d.ts +87 -0
  132. package/dist/preflight.d.ts.map +1 -0
  133. package/dist/preflight.js +139 -0
  134. package/dist/preflight.js.map +1 -0
  135. package/dist/provider-secret-key.d.ts +3 -0
  136. package/dist/provider-secret-key.d.ts.map +1 -0
  137. package/dist/provider-secret-key.js +7 -0
  138. package/dist/provider-secret-key.js.map +1 -0
  139. package/dist/service/app-debug-service.d.ts +78 -0
  140. package/dist/service/app-debug-service.d.ts.map +1 -0
  141. package/dist/service/app-debug-service.js +201 -0
  142. package/dist/service/app-debug-service.js.map +1 -0
  143. package/dist/service/app-run-server.d.ts +28 -0
  144. package/dist/service/app-run-server.d.ts.map +1 -0
  145. package/dist/service/app-run-server.js +104 -0
  146. package/dist/service/app-run-server.js.map +1 -0
  147. package/dist/service/debug-sessions.d.ts +158 -0
  148. package/dist/service/debug-sessions.d.ts.map +1 -0
  149. package/dist/service/debug-sessions.js +358 -0
  150. package/dist/service/debug-sessions.js.map +1 -0
  151. package/dist/service/index.d.ts +22 -0
  152. package/dist/service/index.d.ts.map +1 -0
  153. package/dist/service/index.js +17 -0
  154. package/dist/service/index.js.map +1 -0
  155. package/dist/service/job-progress.d.ts +40 -0
  156. package/dist/service/job-progress.d.ts.map +1 -0
  157. package/dist/service/job-progress.js +53 -0
  158. package/dist/service/job-progress.js.map +1 -0
  159. package/dist/service/workflow-run.d.ts +279 -0
  160. package/dist/service/workflow-run.d.ts.map +1 -0
  161. package/dist/service/workflow-run.js +598 -0
  162. package/dist/service/workflow-run.js.map +1 -0
  163. package/dist/service/workflow-workspace.d.ts +89 -0
  164. package/dist/service/workflow-workspace.d.ts.map +1 -0
  165. package/dist/service/workflow-workspace.js +160 -0
  166. package/dist/service/workflow-workspace.js.map +1 -0
  167. package/dist/session.d.ts +62 -0
  168. package/dist/session.d.ts.map +1 -0
  169. package/dist/session.js +353 -0
  170. package/dist/session.js.map +1 -0
  171. package/dist/sketch-debug/index.d.ts +11 -0
  172. package/dist/sketch-debug/index.d.ts.map +1 -0
  173. package/dist/sketch-debug/index.js +10 -0
  174. package/dist/sketch-debug/index.js.map +1 -0
  175. package/dist/sketch-debug/markdown.d.ts +6 -0
  176. package/dist/sketch-debug/markdown.d.ts.map +1 -0
  177. package/dist/sketch-debug/markdown.js +93 -0
  178. package/dist/sketch-debug/markdown.js.map +1 -0
  179. package/dist/sketch-debug/report.d.ts +15 -0
  180. package/dist/sketch-debug/report.d.ts.map +1 -0
  181. package/dist/sketch-debug/report.js +98 -0
  182. package/dist/sketch-debug/report.js.map +1 -0
  183. package/dist/sketch-debug/types.d.ts +62 -0
  184. package/dist/sketch-debug/types.d.ts.map +1 -0
  185. package/dist/sketch-debug/types.js +10 -0
  186. package/dist/sketch-debug/types.js.map +1 -0
  187. package/dist/sketch-debug/validate.d.ts +14 -0
  188. package/dist/sketch-debug/validate.d.ts.map +1 -0
  189. package/dist/sketch-debug/validate.js +478 -0
  190. package/dist/sketch-debug/validate.js.map +1 -0
  191. package/dist/supervisor.d.ts +45 -0
  192. package/dist/supervisor.d.ts.map +1 -0
  193. package/dist/supervisor.js +97 -0
  194. package/dist/supervisor.js.map +1 -0
  195. package/dist/timeline-debug/index.d.ts +11 -0
  196. package/dist/timeline-debug/index.d.ts.map +1 -0
  197. package/dist/timeline-debug/index.js +10 -0
  198. package/dist/timeline-debug/index.js.map +1 -0
  199. package/dist/timeline-debug/legibility.d.ts +23 -0
  200. package/dist/timeline-debug/legibility.d.ts.map +1 -0
  201. package/dist/timeline-debug/legibility.js +240 -0
  202. package/dist/timeline-debug/legibility.js.map +1 -0
  203. package/dist/timeline-debug/markdown.d.ts +6 -0
  204. package/dist/timeline-debug/markdown.d.ts.map +1 -0
  205. package/dist/timeline-debug/markdown.js +103 -0
  206. package/dist/timeline-debug/markdown.js.map +1 -0
  207. package/dist/timeline-debug/motion.d.ts +20 -0
  208. package/dist/timeline-debug/motion.d.ts.map +1 -0
  209. package/dist/timeline-debug/motion.js +362 -0
  210. package/dist/timeline-debug/motion.js.map +1 -0
  211. package/dist/timeline-debug/report.d.ts +16 -0
  212. package/dist/timeline-debug/report.d.ts.map +1 -0
  213. package/dist/timeline-debug/report.js +100 -0
  214. package/dist/timeline-debug/report.js.map +1 -0
  215. package/dist/timeline-debug/showcase.d.ts +7 -0
  216. package/dist/timeline-debug/showcase.d.ts.map +1 -0
  217. package/dist/timeline-debug/showcase.js +347 -0
  218. package/dist/timeline-debug/showcase.js.map +1 -0
  219. package/dist/timeline-debug/types.d.ts +64 -0
  220. package/dist/timeline-debug/types.d.ts.map +1 -0
  221. package/dist/timeline-debug/types.js +10 -0
  222. package/dist/timeline-debug/types.js.map +1 -0
  223. package/dist/timeline-debug/validate.d.ts +24 -0
  224. package/dist/timeline-debug/validate.d.ts.map +1 -0
  225. package/dist/timeline-debug/validate.js +1432 -0
  226. package/dist/timeline-debug/validate.js.map +1 -0
  227. package/dist/types.d.ts +211 -0
  228. package/dist/types.d.ts.map +1 -0
  229. package/dist/types.js +2 -0
  230. package/dist/types.js.map +1 -0
  231. package/package.json +103 -0
@@ -0,0 +1,353 @@
1
+ /**
2
+ * `ExecutionSession` — the one place that constructs `WorkflowRunner`.
3
+ *
4
+ * See the package README for the wiring-inventory table this facade is
5
+ * derived from (Track A / task A1 of docs/RELIABILITY_TASKS.md) and
6
+ * docs/RELIABILITY_ARCHITECTURE.md §7 for the target API shape.
7
+ */
8
+ import { randomUUID } from "node:crypto";
9
+ import { createLogger } from "@nodetool-ai/config";
10
+ import { hydrateGraphNodeFlags } from "@nodetool-ai/node-sdk";
11
+ import { Graph, WorkflowRunner, withExplicitNodeFlags } from "@nodetool-ai/kernel";
12
+ import { PERMISSION_GATE_CONTEXT_KEY, connectPythonBridgeForGraph, headlessGate } from "@nodetool-ai/runtime";
13
+ import { createExecutorResolver } from "./executor-resolver.js";
14
+ import { WORKFLOW_RUN_HOST, buildWorkspaceExecutionContext } from "./service/workflow-workspace.js";
15
+ import { normalizeGraph } from "./normalize-graph.js";
16
+ import { assertPreflight } from "./preflight.js";
17
+ import { rewriteOutputNames } from "./output-names.js";
18
+ import { MessageStream } from "./message-stream.js";
19
+ import { attachRunCostLedger, nodeTypeLookup } from "./cost-ledger.js";
20
+ const log = createLogger("nodetool.execution.session");
21
+ export class ExecutionSession {
22
+ jobId;
23
+ workflowId;
24
+ graph;
25
+ runner;
26
+ /** Null unless the caller opted into `captureMessages` (see options). */
27
+ stream;
28
+ persistence;
29
+ bridge;
30
+ resultPromise;
31
+ runTimeoutHandle = null;
32
+ _cancelReason = null;
33
+ constructor(init) {
34
+ this.jobId = init.jobId;
35
+ this.workflowId = init.workflowId;
36
+ this.graph = init.graph;
37
+ this.runner = init.runner;
38
+ this.persistence = init.persistence;
39
+ this.bridge = init.bridge;
40
+ this.stream = init.captureMessages
41
+ ? new MessageStream(init.context, init.messageBufferLimit)
42
+ : null;
43
+ // Every generation this run pays for lands in the ledger `nodetool costs`
44
+ // reads. Attached here, at the one seam all surfaces share, so image and
45
+ // video spend is recorded whether the run came from the CLI, the debug
46
+ // harness, an app, or the websocket server.
47
+ // No `projectId`/`documentId`: a session is constructed from a graph and a
48
+ // job id, and no host passes project attribution down to it. The rows carry
49
+ // a null rather than being attributed to the loose bucket.
50
+ const detachLedger = init.recordCosts
51
+ ? attachRunCostLedger(init.context, {
52
+ userId: init.userId,
53
+ workflowId: init.workflowId,
54
+ projectId: init.projectId ?? null,
55
+ documentId: init.documentId ?? null,
56
+ nodeType: nodeTypeLookup(init.graph.nodes),
57
+ resolveSecret: (key) => init.context.getSecret(key)
58
+ })
59
+ : null;
60
+ if (init.runTimeoutMs && init.runTimeoutMs > 0) {
61
+ this.runTimeoutHandle = setTimeout(() => {
62
+ this.cancel("timeout");
63
+ }, init.runTimeoutMs);
64
+ }
65
+ // Open the run boundary on the Python worker before the kernel starts, so
66
+ // an execute frame can never arrive ahead of the job it belongs to. Fire
67
+ // and forget: `jobStart` is a no-op on a pre-v4 worker and swallows its own
68
+ // failures, and blocking the kernel on worker bookkeeping would make an
69
+ // unreachable worker a run failure.
70
+ const boundary = {
71
+ jobId: init.jobId,
72
+ workflowId: init.workflowId,
73
+ userId: init.userId
74
+ };
75
+ void init.lifecycle?.jobStart(boundary);
76
+ const runRequest = {
77
+ job_id: init.jobId,
78
+ workflow_id: init.workflowId ?? undefined,
79
+ params: init.params
80
+ };
81
+ if (init.triggerEvent) {
82
+ runRequest.trigger_event = init.triggerEvent;
83
+ }
84
+ this.resultPromise = init.runner
85
+ .run(runRequest, init.graph)
86
+ .then((result) => {
87
+ void init.lifecycle?.jobEnd({
88
+ ...boundary,
89
+ reason: this.endReason(result.status)
90
+ });
91
+ return result;
92
+ }, (err) => {
93
+ // `run()` documents that it never rejects, but the boundary must
94
+ // close even if that ever stops being true — an abandoned run is
95
+ // exactly the leak `job.end` exists to prevent.
96
+ void init.lifecycle?.jobEnd({ ...boundary, reason: "abandoned" });
97
+ throw err;
98
+ })
99
+ .finally(async () => {
100
+ if (this.runTimeoutHandle) {
101
+ clearTimeout(this.runTimeoutHandle);
102
+ this.runTimeoutHandle = null;
103
+ }
104
+ init.closeBridge();
105
+ // The terminal message was emitted synchronously before run()
106
+ // resolved (ProcessingContext.emit() calls listeners inline), so the
107
+ // stream can close now without dropping it. The same holds for the
108
+ // ledger: every prediction/node_update it prices was already delivered.
109
+ detachLedger?.();
110
+ this.stream?.close();
111
+ try {
112
+ await init.context.workspace?.cleanupScratch?.();
113
+ }
114
+ catch (err) {
115
+ log.warn("Workspace scratch cleanup failed", {
116
+ jobId: this.jobId,
117
+ error: err instanceof Error ? err.message : String(err)
118
+ });
119
+ }
120
+ });
121
+ this.resultPromise
122
+ .then((result) => this.persistence?.onTerminal?.(result))
123
+ .catch((err) => {
124
+ log.warn("persistence.onTerminal threw", {
125
+ jobId: this.jobId,
126
+ error: err instanceof Error ? err.message : String(err)
127
+ });
128
+ });
129
+ }
130
+ /** Map a kernel run status onto the `job.end` reason. */
131
+ endReason(status) {
132
+ if (status === "failed")
133
+ return "failed";
134
+ if (status === "cancelled")
135
+ return "cancelled";
136
+ return "completed";
137
+ }
138
+ static async create(options) {
139
+ if (options.limits?.nodeTimeoutMs) {
140
+ throw new Error("ExecutionSession: nodeTimeoutMs is not yet supported — the kernel " +
141
+ "has no per-node timeout hook (only run-level cancel()). Omit it " +
142
+ "or use limits.runTimeoutMs.");
143
+ }
144
+ if (!options.registry && !options.resolveExecutor) {
145
+ throw new Error("ExecutionSession: either registry or resolveExecutor must be provided " +
146
+ "(registry builds the default registry+bridge resolver; resolveExecutor " +
147
+ "bypasses it for a host with its own resolution, e.g. the WS runner).");
148
+ }
149
+ const jobId = options.jobId ?? randomUUID();
150
+ const workflowId = options.workflowId ?? null;
151
+ const registry = options.registry;
152
+ const normalized = normalizeGraph(options.graph);
153
+ // A caller that brings no context still gets one that can reach the
154
+ // secret store. The bare `new ProcessingContext(...)` this replaced
155
+ // resolved no secret at all, so a graph with a provider node failed on
156
+ // credentials the install had — the same defect the service-layer run
157
+ // path shipped with. Selected here, ahead of the bridge, because the
158
+ // preflight below resolves credentials through it.
159
+ const context = options.context ??
160
+ buildWorkspaceExecutionContext({
161
+ jobId,
162
+ workflowId,
163
+ userId: "1",
164
+ workspace: null,
165
+ durableFalGenerations: true
166
+ });
167
+ // This facade is the workflow host for every caller that builds its own
168
+ // context (`nodetool run`, the WebSocket job runner, the app simulator):
169
+ // a run is consent, so a context that arrived with no gate gets the
170
+ // headless one here. A caller that already has a user to ask — a chat
171
+ // turn's `run_node` — set its gate before handing the context in, and
172
+ // keeps it.
173
+ if (context.get(PERMISSION_GATE_CONTEXT_KEY) === undefined) {
174
+ context.set(PERMISSION_GATE_CONTEXT_KEY, headlessGate(WORKFLOW_RUN_HOST));
175
+ }
176
+ // Refuse a graph this runtime cannot honour before anything is paid for:
177
+ // ahead of the Python bridge (a worker spawn), ahead of
178
+ // `persistence.onAccepted` (a job row), and ahead of the kernel. Without
179
+ // this, a bad model id or a missing key failed at the node that needed it
180
+ // — after the upstream half of the graph had already run and billed.
181
+ // A context serving providers from its own resolver (a fake, a cassette,
182
+ // the e2e server's scripted provider) never reaches the registry and never
183
+ // reads a credential, so the registry's "is this key set" question does not
184
+ // apply to it — asking anyway refuses the run for a secret it would not
185
+ // have used. An explicit checker still wins: a host that knows its own
186
+ // registry says so itself.
187
+ const providerConfiguration = options.providerConfiguration ??
188
+ (context.hasProviderResolver ? () => [] : undefined);
189
+ await assertPreflight(normalized, {
190
+ catalogs: options.catalogs,
191
+ providerConfiguration,
192
+ resolveSecret: (key) => context.getSecret(key)
193
+ });
194
+ // A caller injecting its own `resolveExecutor` (see the option doc)
195
+ // typically also owns its own Python bridge — never connect a second one
196
+ // behind its back. `bridgeFactory` remains available for that caller to
197
+ // opt back in explicitly (e.g. handing this facade an already-connected
198
+ // bridge instance to close on its behalf).
199
+ const bridgeFactory = options.bridgeFactory ??
200
+ (options.resolveExecutor
201
+ ? async () => null
202
+ : connectPythonBridgeForGraph);
203
+ const bridge = await bridgeFactory(normalized.nodes, (t) => registry ? registry.has(t) : false);
204
+ let bridgeClosed = false;
205
+ const closeBridge = () => {
206
+ if (bridgeClosed)
207
+ return;
208
+ bridgeClosed = true;
209
+ bridge?.close();
210
+ };
211
+ let hydrated;
212
+ try {
213
+ if (options.resolveNodeType) {
214
+ // Richer path: resolves `propertyTypes`/`outputs` from registry
215
+ // metadata too (async — the resolver may lazy-load a namespace),
216
+ // matching `websocket-client-session.ts`'s `Graph.loadFromDict`
217
+ // hydration. Without this, multi-edge fan-in into a non-list
218
+ // property is misclassified as list aggregation (the kernel only
219
+ // gates on a populated `propertyTypes` map).
220
+ const loaded = await Graph.loadFromDict(normalized, {
221
+ resolver: options.resolveNodeType
222
+ });
223
+ hydrated = { nodes: [...loaded.nodes], edges: [...loaded.edges] };
224
+ }
225
+ else if (registry) {
226
+ hydrated = hydrateGraphNodeFlags(normalized, registry);
227
+ }
228
+ else {
229
+ // No registry and no resolveNodeType: the caller hydrates its own
230
+ // graph before handing it to this facade (see the `registry` option
231
+ // doc) — default absent flags to `false` rather than guessing.
232
+ // `...node` on every field `withExplicitNodeFlags` doesn't touch
233
+ // means an already-resolved `propertyTypes`/`outputs` passes through
234
+ // unchanged.
235
+ hydrated = withExplicitNodeFlags(normalized);
236
+ }
237
+ }
238
+ catch (err) {
239
+ closeBridge();
240
+ throw err;
241
+ }
242
+ if (options.requireTerminalResult) {
243
+ rewriteOutputNames(hydrated);
244
+ }
245
+ const resolveExecutor = options.resolveExecutor ?? createExecutorResolver(registry, bridge);
246
+ const runnerOptions = {
247
+ resolveExecutor,
248
+ executionContext: context,
249
+ validateNode: options.validateNode,
250
+ bufferLimit: options.limits?.bufferLimit ?? null,
251
+ strict: options.strict
252
+ };
253
+ if (options.supervisor) {
254
+ runnerOptions.supervisor = options.supervisor;
255
+ }
256
+ const runner = new WorkflowRunner(jobId, runnerOptions);
257
+ try {
258
+ await options.persistence?.onAccepted?.(jobId);
259
+ }
260
+ catch (err) {
261
+ log.warn("persistence.onAccepted threw", {
262
+ jobId,
263
+ error: err instanceof Error ? err.message : String(err)
264
+ });
265
+ }
266
+ return new ExecutionSession({
267
+ jobId,
268
+ workflowId,
269
+ graph: hydrated,
270
+ runner,
271
+ context,
272
+ persistence: options.persistence ?? null,
273
+ params: options.params ?? {},
274
+ triggerEvent: options.triggerEvent ?? null,
275
+ bridge,
276
+ lifecycle: options.jobLifecycleBridge ?? bridge,
277
+ userId: context.userId,
278
+ closeBridge,
279
+ runTimeoutMs: options.limits?.runTimeoutMs,
280
+ captureMessages: options.captureMessages === true,
281
+ messageBufferLimit: options.limits?.messageBufferLimit,
282
+ recordCosts: options.recordCosts !== false,
283
+ projectId: options.projectId,
284
+ documentId: options.documentId
285
+ });
286
+ }
287
+ /**
288
+ * Live message stream — closes once the run reaches a terminal state.
289
+ * Requires `captureMessages: true` at `create()`; without it nothing is
290
+ * queued (see that option) and reading this throws rather than handing back
291
+ * a stream that would silently yield nothing.
292
+ */
293
+ get messages() {
294
+ if (!this.stream) {
295
+ throw new Error("ExecutionSession: `messages` requires `captureMessages: true` at " +
296
+ "create() — message capture is opt-in so a host that only awaits " +
297
+ "`result` never queues a run's messages unread.");
298
+ }
299
+ return this.stream;
300
+ }
301
+ /** The run's terminal result. Never rejects — kernel failures resolve as `status: "failed"`. */
302
+ get result() {
303
+ return this.resultPromise;
304
+ }
305
+ /**
306
+ * Live resource counts, for leak accounting: after a terminal result every
307
+ * one of these must be back to zero. Measured, not inferred — the
308
+ * reliability harness's `cleanup-leaks` invariant asserts against these
309
+ * numbers and reports a violation when a driver can't produce them.
310
+ */
311
+ resourceCounters() {
312
+ return {
313
+ liveActors: this.runner.liveActorCount,
314
+ pendingControlResponses: this.runner.pendingControlResponseCount,
315
+ // The session's own run-timeout timer is the only timer it owns; it is
316
+ // cleared when the run settles.
317
+ pendingTimers: this.runTimeoutHandle === null ? 0 : 1,
318
+ pythonBridgePendingRequests: this.bridge?.pendingRequestCount ?? 0
319
+ };
320
+ }
321
+ /** The reason passed to the most recent `cancel()` call, if any. */
322
+ get cancelReason() {
323
+ return this._cancelReason;
324
+ }
325
+ /** Stream one more value into a live input node (mirrors the WS `stream_input` command). */
326
+ pushInput(inputName, value, sourceHandle) {
327
+ return this.runner.pushInputValue(inputName, value, sourceHandle);
328
+ }
329
+ /** Signal end-of-stream for a live input node (mirrors `end_input_stream`). */
330
+ finishInputStream(inputName, sourceHandle) {
331
+ this.runner.finishInputStream(inputName, sourceHandle);
332
+ }
333
+ /**
334
+ * Push property updates into a running node's executor instance (live
335
+ * parameter changes, e.g. a synth knob while a patch plays — mirrors the
336
+ * WS runner's `update_node_properties` command). Returns `true` when the
337
+ * node's executor exists and supports live updates; `false` is not an
338
+ * error — the caller's own state already holds the new value for the next
339
+ * run.
340
+ */
341
+ updateNodeProperties(nodeId, properties) {
342
+ return this.runner.updateNodeProperties(nodeId, properties);
343
+ }
344
+ /**
345
+ * The only cancel path. `runTimeoutMs` is implemented as
346
+ * `cancel("timeout")` — there is no separate timeout code path.
347
+ */
348
+ cancel(reason) {
349
+ this._cancelReason = reason ?? this._cancelReason ?? "cancelled";
350
+ this.runner.cancel();
351
+ }
352
+ }
353
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `@nodetool-ai/execution/sketch-debug` — sketch validation + debug report.
3
+ *
4
+ * Pure, dependency-injected core: no DB, no canvas, no browser. Hosts (the CLI
5
+ * `sketch` command today) resolve the target and write the bundle.
6
+ */
7
+ export type { SketchDebugIssue, SketchValidation, SketchInteractionRecord, SketchDebugTarget, SketchDocumentMeta, SketchDebugReport } from "./types.js";
8
+ export { validateSketchDocument, type SketchValidationMeta } from "./validate.js";
9
+ export { buildSketchDebugReport, type SketchDebugReportInput } from "./report.js";
10
+ export { renderSketchReportMarkdown } from "./markdown.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sketch-debug/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,sBAAsB,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EACL,sBAAsB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `@nodetool-ai/execution/sketch-debug` — sketch validation + debug report.
3
+ *
4
+ * Pure, dependency-injected core: no DB, no canvas, no browser. Hosts (the CLI
5
+ * `sketch` command today) resolve the target and write the bundle.
6
+ */
7
+ export { validateSketchDocument } from "./validate.js";
8
+ export { buildSketchDebugReport } from "./report.js";
9
+ export { renderSketchReportMarkdown } from "./markdown.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sketch-debug/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAAE,sBAAsB,EAA6B,MAAM,eAAe,CAAC;AAClF,OAAO,EACL,sBAAsB,EAEvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Renders a `SketchDebugReport` as human-readable Markdown for the bundle.
3
+ */
4
+ import type { SketchDebugReport } from "./types.js";
5
+ export declare function renderSketchReportMarkdown(report: SketchDebugReport): string;
6
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/sketch-debug/markdown.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA+EtE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAyD5E"}
@@ -0,0 +1,93 @@
1
+ import { isObjectLike, isString } from "../predicates.js";
2
+ const short = (value, max = 120) => {
3
+ if (value === undefined)
4
+ return "—";
5
+ let s;
6
+ try {
7
+ s = isString(value) ? value : JSON.stringify(value);
8
+ }
9
+ catch {
10
+ s = String(value);
11
+ }
12
+ s = (s ?? "null").replace(/\s+/g, " ");
13
+ return s.length > max ? `${s.slice(0, max)}…` : s;
14
+ };
15
+ const where = (issue) => {
16
+ const parts = [
17
+ issue.layerId ? `layer \`${issue.layerId}\`` : null,
18
+ issue.path ? `\`${issue.path}\`` : null
19
+ ].filter((part) => part !== null);
20
+ return parts.length > 0 ? parts.join(" · ") : "—";
21
+ };
22
+ function issueTable(title, issues, lines) {
23
+ if (issues.length === 0)
24
+ return;
25
+ lines.push("", `## ${title}`, "");
26
+ lines.push("| Severity | Code | Where | Message |");
27
+ lines.push("| --- | --- | --- | --- |");
28
+ for (const issue of issues) {
29
+ lines.push(`| ${issue.severity} | \`${issue.code}\` | ${where(issue)} | ${short(issue.message, 300)} |`);
30
+ }
31
+ }
32
+ const asRecord = (value) => isObjectLike(value) ? value : null;
33
+ /**
34
+ * The snapshot carries the whole layer stack; the markdown wants one line per
35
+ * layer, top of the stack first, rather than a JSON dump.
36
+ */
37
+ function finalStateLines(state) {
38
+ const record = asRecord(state);
39
+ const layers = Array.isArray(record?.layers)
40
+ ? record.layers
41
+ : null;
42
+ if (!layers)
43
+ return [`- ${short(state, 600)}`];
44
+ const lines = [];
45
+ const canvas = `${String(record?.width ?? "?")}×${String(record?.height ?? "?")}`;
46
+ lines.push(`- canvas ${canvas}, active layer \`${String(record?.activeLayerId ?? "none")}\``);
47
+ for (const layer of [...layers].reverse()) {
48
+ lines.push(`- \`${layer.id ?? "?"}\`${layer.name ? ` "${layer.name}"` : ""} ` +
49
+ `${layer.type ?? "?"} · opacity ${layer.opacity ?? 1} · ${layer.blendMode ?? "normal"}` +
50
+ `${layer.visible === false ? " · hidden" : ""}${layer.hasBinding ? " · bound" : ""}`);
51
+ }
52
+ return lines;
53
+ }
54
+ export function renderSketchReportMarkdown(report) {
55
+ const lines = [];
56
+ const title = report.target.name ?? report.target.ref;
57
+ lines.push(`# Sketch debug: ${title}`);
58
+ lines.push("");
59
+ lines.push(`${report.verdict.ok ? "✅" : "❌"} ${report.verdict.headline}`);
60
+ lines.push("");
61
+ lines.push(`Target: \`${report.target.ref}\` (${report.target.kind})`);
62
+ lines.push(`Document: ${report.meta.width}×${report.meta.height} on ${report.meta.backgroundColor} · ` +
63
+ `${report.meta.layerCount} layer(s), ${report.meta.bindingCount} binding(s)`);
64
+ if (report.verdict.issues.length > 0) {
65
+ lines.push("", "## Issues", "");
66
+ for (const issue of report.verdict.issues)
67
+ lines.push(`- ${issue}`);
68
+ }
69
+ issueTable("Validation", [...report.validation.errors, ...report.validation.warnings], lines);
70
+ if (report.interactions.length > 0) {
71
+ lines.push("", "## Interactions", "");
72
+ lines.push("| Tool | OK | Input | Error |");
73
+ lines.push("| --- | --- | --- | --- |");
74
+ for (const step of report.interactions) {
75
+ lines.push(`| \`${step.tool}\` | ${step.ok ? "✅" : "❌"} | ${short(step.input)} | ${step.error ? short(step.error, 200) : "—"} |`);
76
+ }
77
+ }
78
+ if (report.finalValidation) {
79
+ issueTable("Validation after edits", [...report.finalValidation.errors, ...report.finalValidation.warnings], lines);
80
+ }
81
+ if (report.finalState !== undefined) {
82
+ lines.push("", "## Final state", "");
83
+ lines.push(...finalStateLines(report.finalState));
84
+ }
85
+ if (report.notSimulated.length > 0) {
86
+ lines.push("", "## Not simulated", "");
87
+ for (const entry of report.notSimulated)
88
+ lines.push(`- ${entry}`);
89
+ }
90
+ lines.push("");
91
+ return lines.join("\n");
92
+ }
93
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/sketch-debug/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { SketchDebugReport, SketchDebugTarget, SketchInteractionRecord } from "./types.js";
2
+ import { type SketchValidationMeta } from "./validate.js";
3
+ export interface SketchDebugReportInput {
4
+ target: SketchDebugTarget;
5
+ /** The document as loaded — untrusted, validated here. */
6
+ document: unknown;
7
+ meta?: SketchValidationMeta;
8
+ interactions?: SketchInteractionRecord[];
9
+ /** Bridge snapshot after the scripted session (`SketchBridgeFinalState`). */
10
+ finalState?: unknown;
11
+ /** Document reconstructed from the final state, validated as a second pass. */
12
+ finalDocument?: unknown;
13
+ }
14
+ export declare function buildSketchDebugReport(input: SketchDebugReportInput): SketchDebugReport;
15
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/sketch-debug/report.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,iBAAiB,EACjB,iBAAiB,EAEjB,uBAAuB,EAExB,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAyGvB,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,YAAY,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACzC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,sBAAsB,GAC5B,iBAAiB,CAiCnB"}
@@ -0,0 +1,98 @@
1
+ import { validateSketchDocument } from "./validate.js";
2
+ import { isPositiveFiniteNumber, isString } from "../predicates.js";
3
+ const DEFAULTS = {
4
+ width: 1024,
5
+ height: 1024,
6
+ backgroundColor: "#ffffff"
7
+ };
8
+ /**
9
+ * What a headless sketch run cannot answer. Fixed, because the boundary is a
10
+ * property of the harness, not of the document it was pointed at.
11
+ */
12
+ const NOT_SIMULATED = [
13
+ "Pixels — layer bitmaps are never decoded, composited, or diffed.",
14
+ "Rendering and flattening — no canvas exists, so blend modes and effects produce nothing to look at.",
15
+ "Painting tools — brush, eraser, fill, gradient and transform strokes leave no marks headlessly.",
16
+ "Generation providers — no imagery is produced; bindings are checked structurally only.",
17
+ "Asset I/O — asset ids are never resolved, fetched, or uploaded.",
18
+ "Generation bindings after edits — the headless bridge tracks a layer's prompt/provider/model but not the persisted binding record, so a post-edit document is validated with no bindings."
19
+ ];
20
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21
+ const count = (value) => Array.isArray(value) ? value.length : 0;
22
+ function describeDocument(document, meta) {
23
+ const record = isRecord(document) ? document : {};
24
+ const sketch = isRecord(record.sketch) ? record.sketch : {};
25
+ const canvas = isRecord(sketch.canvas) ? sketch.canvas : {};
26
+ const pick = (value, fallback) => isPositiveFiniteNumber(value) ? value : fallback;
27
+ const background = isString(canvas.backgroundColor)
28
+ ? canvas.backgroundColor
29
+ : (meta?.backgroundColor ?? DEFAULTS.backgroundColor);
30
+ return {
31
+ width: pick(canvas.width, pick(meta?.width, DEFAULTS.width)),
32
+ height: pick(canvas.height, pick(meta?.height, DEFAULTS.height)),
33
+ backgroundColor: background,
34
+ layerCount: count(sketch.layers),
35
+ bindingCount: count(record.layerBindings)
36
+ };
37
+ }
38
+ const describe = (issue) => {
39
+ const where = issue.layerId ?? issue.path;
40
+ return where
41
+ ? `[${issue.code}] ${where}: ${issue.message}`
42
+ : `[${issue.code}] ${issue.message}`;
43
+ };
44
+ function buildSketchVerdict(validation, interactions, finalValidation) {
45
+ const failedSteps = interactions.filter((step) => !step.ok);
46
+ const issues = [
47
+ ...validation.errors.map(describe),
48
+ ...failedSteps.map((step) => `Interaction \`${step.tool}\` failed${step.error ? `: ${step.error}` : ""}`),
49
+ ...(finalValidation?.errors ?? []).map((issue) => `After edits — ${describe(issue)}`)
50
+ ];
51
+ const warnings = [
52
+ ...validation.warnings.map(describe),
53
+ ...(finalValidation?.warnings ?? []).map((issue) => `After edits — ${describe(issue)}`)
54
+ ];
55
+ const ok = issues.length === 0;
56
+ const warningCount = warnings.length;
57
+ const headline = ok
58
+ ? `Sketch is sound — ${interactions.length} interaction(s) ran clean` +
59
+ (warningCount > 0 ? `, ${warningCount} warning(s)` : "") +
60
+ "."
61
+ : `Sketch has ${issues.length} problem(s)` +
62
+ (failedSteps.length > 0
63
+ ? `, ${failedSteps.length} failed interaction(s)`
64
+ : "") +
65
+ (warningCount > 0 ? `, ${warningCount} warning(s)` : "") +
66
+ ` — ${issues[0]}`;
67
+ return warningCount > 0
68
+ ? { ok, headline, issues, warnings }
69
+ : { ok, headline, issues };
70
+ }
71
+ export function buildSketchDebugReport(input) {
72
+ const validation = validateSketchDocument(input.document, input.meta);
73
+ // The post-edit pass runs without `meta`: a session may have resized the
74
+ // canvas, and the stored row's size is then the stale number, not the bug.
75
+ const finalValidation = input.finalDocument === undefined
76
+ ? undefined
77
+ : validateSketchDocument(input.finalDocument);
78
+ const interactions = input.interactions ?? [];
79
+ // The final document is what the session left behind, so it — not the input
80
+ // — describes the sketch the report is about.
81
+ const meta = describeDocument(input.finalDocument ?? input.document, input.meta);
82
+ const report = {
83
+ target: input.target,
84
+ meta,
85
+ validation,
86
+ interactions,
87
+ notSimulated: [...NOT_SIMULATED],
88
+ verdict: buildSketchVerdict(validation, interactions, finalValidation)
89
+ };
90
+ if (input.finalState !== undefined) {
91
+ report.finalState = input.finalState;
92
+ }
93
+ if (finalValidation) {
94
+ report.finalValidation = finalValidation;
95
+ }
96
+ return report;
97
+ }
98
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/sketch-debug/report.ts"],"names":[],"mappings":"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"}