@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,358 @@
1
+ /**
2
+ * Interactive escalation sessions for the agent-facing run/debug endpoints.
3
+ *
4
+ * The supervisor design (docs/workflow-supervisor-design.md) puts an LLM agent
5
+ * on a run's failure path. This module puts the *calling* agent there instead:
6
+ * `InteractiveEscalationHandle` is a `SupervisorHandle` whose `decide()` parks
7
+ * the escalation until a verdict arrives over HTTP, so the tool that started
8
+ * the run gets the problem back as its result and answers with one of the
9
+ * same verdicts the supervisor vocabulary defines. The kernel's guarantees are
10
+ * untouched — the handle is wrapped in `BoundedHandle` (decision/retry caps,
11
+ * timeout, sticky verdicts) and the actor still enforces `allowedActions`.
12
+ *
13
+ * A session is one run: the parked escalations, the run's completion promise,
14
+ * and the final report. Sessions are owned by the user who started the run and
15
+ * are swept a few minutes after the run settles.
16
+ *
17
+ * Long-running work that is not a workflow run uses the same registry for its
18
+ * polling and cancel — `POST /api/applications/build` fronts a build this way,
19
+ * with a null `workflowId` and a handle nothing ever escalates to.
20
+ */
21
+ import { randomUUID } from "node:crypto";
22
+ import { createLogger } from "@nodetool-ai/config";
23
+ import { validateSubstituteOutputs } from "@nodetool-ai/kernel";
24
+ const log = createLogger("nodetool.execution.debug-sessions");
25
+ /** How long an agent gets to answer one escalation before it fails closed. */
26
+ export const INTERACTIVE_DECISION_TIMEOUT_MS = 10 * 60_000;
27
+ /** How long a settled session's report stays fetchable. */
28
+ const SESSION_DONE_TTL_MS = 10 * 60_000;
29
+ /**
30
+ * Hard ceiling on a session's life. The TTL sweep only arms once a run
31
+ * settles, so a run whose `done` never resolves — a wedged bridge, a promise
32
+ * nobody rejects — used to hold its session (and the run behind it) forever.
33
+ */
34
+ export const SESSION_MAX_LIFETIME_MS = 60 * 60_000;
35
+ /** How long `cancel()` waits for the run to settle before answering anyway. */
36
+ export const CANCEL_SETTLE_TIMEOUT_MS = 30_000;
37
+ /** Live (unsettled) sessions one user may hold at once. */
38
+ export const MAX_LIVE_SESSIONS_PER_USER = 8;
39
+ const FAIL_CLOSED = {
40
+ verdict: { action: "fail" },
41
+ decidedBy: "default"
42
+ };
43
+ /**
44
+ * A `SupervisorHandle` that answers nothing itself: each `decide()` parks the
45
+ * escalation until `submit()` delivers a verdict (or the decision signal
46
+ * aborts, which fails closed). `BoundedHandle` serializes decisions, so at
47
+ * most one escalation is pending at a time.
48
+ */
49
+ export class InteractiveEscalationHandle {
50
+ _pending = null;
51
+ _waiters = [];
52
+ _counter = 0;
53
+ _closed = false;
54
+ decide(e, signal) {
55
+ if (this._closed || signal.aborted)
56
+ return Promise.resolve(FAIL_CLOSED);
57
+ return new Promise((resolve) => {
58
+ let settled = false;
59
+ const entry = {
60
+ id: `esc-${++this._counter}`,
61
+ escalation: e,
62
+ settle: (outcome) => {
63
+ if (settled)
64
+ return;
65
+ settled = true;
66
+ if (this._pending === entry)
67
+ this._pending = null;
68
+ signal.removeEventListener("abort", onAbort);
69
+ resolve(outcome);
70
+ }
71
+ };
72
+ const onAbort = () => entry.settle(FAIL_CLOSED);
73
+ signal.addEventListener("abort", onAbort, { once: true });
74
+ this._pending = entry;
75
+ const waiters = this._waiters;
76
+ this._waiters = [];
77
+ for (const waiter of waiters)
78
+ waiter(entry);
79
+ });
80
+ }
81
+ /** The escalation currently awaiting a verdict, if any. */
82
+ current() {
83
+ if (!this._pending)
84
+ return null;
85
+ return { id: this._pending.id, escalation: this._pending.escalation };
86
+ }
87
+ /**
88
+ * Subscribe to the next parked escalation. Returns an unsubscribe so a
89
+ * caller racing this against run completion can withdraw when the run wins
90
+ * — otherwise every verdict round trip would strand one waiter until the
91
+ * session is swept.
92
+ */
93
+ subscribe(waiter) {
94
+ this._waiters.push(waiter);
95
+ return () => {
96
+ const index = this._waiters.indexOf(waiter);
97
+ if (index !== -1)
98
+ this._waiters.splice(index, 1);
99
+ };
100
+ }
101
+ /**
102
+ * Deliver the agent's verdict for the parked escalation. Returns an error
103
+ * string instead of throwing so the HTTP layer can 400 with it; the verdict
104
+ * is checked against the escalation's `allowedActions` here so the agent can
105
+ * correct itself, and enforced again by the kernel regardless.
106
+ *
107
+ * A `substitute` payload is validated here too, against the same rules the
108
+ * actor applies. Accepting it and letting the kernel reject it fails the
109
+ * node with its *original* error and burns the decision — the agent never
110
+ * learns its repair was malformed. Rejecting here keeps the escalation
111
+ * parked, so it can answer again.
112
+ */
113
+ async submit(escalationId, verdict) {
114
+ const pending = this._pending;
115
+ if (!pending) {
116
+ return {
117
+ error: "No escalation is awaiting a verdict — the run may have moved on " +
118
+ "(a timed-out decision fails closed) or finished."
119
+ };
120
+ }
121
+ if (pending.id !== escalationId) {
122
+ return {
123
+ error: `Escalation ${escalationId} is not pending (current: ${pending.id}).`
124
+ };
125
+ }
126
+ if (!pending.escalation.allowedActions.includes(verdict.action)) {
127
+ return {
128
+ error: `Verdict "${verdict.action}" is not allowed for this escalation. ` +
129
+ `Allowed: ${pending.escalation.allowedActions.join(", ")}.`
130
+ };
131
+ }
132
+ if (verdict.action === "substitute") {
133
+ const result = await validateSubstituteOutputs(verdict.outputs, {
134
+ declaredOutputs: pending.escalation.declaredOutputs
135
+ });
136
+ if (!result.ok) {
137
+ return {
138
+ error: "Substituted outputs are invalid, so the escalation is still " +
139
+ `awaiting a verdict: ${result.issues.join("; ")}`
140
+ };
141
+ }
142
+ // Validation is async; the escalation may have failed closed meanwhile.
143
+ if (this._pending !== pending) {
144
+ return {
145
+ error: "The escalation stopped awaiting a verdict while the substituted " +
146
+ "outputs were being validated."
147
+ };
148
+ }
149
+ }
150
+ pending.settle({ verdict, decidedBy: "agent" });
151
+ return null;
152
+ }
153
+ close() {
154
+ this._closed = true;
155
+ this._pending?.settle(FAIL_CLOSED);
156
+ }
157
+ }
158
+ export class DebugSession {
159
+ id;
160
+ userId;
161
+ workflowId;
162
+ jobId;
163
+ _handle;
164
+ /** The run's own completion, raced with a forced settle. Never rejects. */
165
+ _done;
166
+ _cancel;
167
+ _cancelWaitMs;
168
+ _force = () => { };
169
+ _report = null;
170
+ constructor(options, onSettled) {
171
+ this.id = randomUUID();
172
+ this.userId = options.userId;
173
+ this.workflowId = options.workflowId;
174
+ this.jobId = options.jobId;
175
+ this._handle = options.handle;
176
+ this._cancel = options.cancel;
177
+ this._cancelWaitMs = options.cancelWaitMs ?? CANCEL_SETTLE_TIMEOUT_MS;
178
+ // A run that never settles must not hold the session — or its waiters —
179
+ // open forever, so every wait goes through this race rather than through
180
+ // the run's own promise.
181
+ const forced = new Promise((resolve) => {
182
+ this._force = resolve;
183
+ });
184
+ this._done = Promise.race([options.done, forced]);
185
+ void this._done.then((report) => {
186
+ this._report = report;
187
+ onSettled();
188
+ });
189
+ }
190
+ /** True until the run (or a forced settle) has produced a final report. */
191
+ isLive() {
192
+ return this._report === null;
193
+ }
194
+ /**
195
+ * Settle the session without the run: cancel what can be cancelled, fail the
196
+ * parked escalation closed, and hand every waiter a failed report. Used by
197
+ * the lifetime ceiling and by a cancel the run does not answer.
198
+ */
199
+ forceSettle(reason) {
200
+ try {
201
+ this._cancel();
202
+ }
203
+ catch (error) {
204
+ log.warn("cancel threw while force-settling a debug session", {
205
+ sessionId: this.id,
206
+ error: String(error)
207
+ });
208
+ }
209
+ this._handle.close();
210
+ this._force({
211
+ status: "failed",
212
+ error: reason,
213
+ job_id: this.jobId,
214
+ workflow_id: this.workflowId,
215
+ outputs: {}
216
+ });
217
+ }
218
+ /**
219
+ * Wait until the run either parks an escalation or settles. There is no
220
+ * wait cap of its own: the non-interactive endpoint awaits the whole run
221
+ * too, a parked decision fails closed on its own timeout, and the session's
222
+ * lifetime ceiling settles anything that outlives both.
223
+ */
224
+ async waitForEvent() {
225
+ const pending = this._handle.current();
226
+ if (pending) {
227
+ return {
228
+ kind: "escalated",
229
+ escalationId: pending.id,
230
+ escalation: pending.escalation
231
+ };
232
+ }
233
+ let unsubscribe = () => { };
234
+ try {
235
+ return await Promise.race([
236
+ this._done.then((report) => ({ kind: "done", report })),
237
+ new Promise((resolve) => {
238
+ unsubscribe = this._handle.subscribe((entry) => resolve({
239
+ kind: "escalated",
240
+ escalationId: entry.id,
241
+ escalation: entry.escalation
242
+ }));
243
+ })
244
+ ]);
245
+ }
246
+ finally {
247
+ unsubscribe();
248
+ }
249
+ }
250
+ /** Current state without waiting. */
251
+ peek() {
252
+ if (this._report)
253
+ return { kind: "done", report: this._report };
254
+ const pending = this._handle.current();
255
+ if (pending) {
256
+ return {
257
+ kind: "escalated",
258
+ escalationId: pending.id,
259
+ escalation: pending.escalation
260
+ };
261
+ }
262
+ return { kind: "running" };
263
+ }
264
+ async submitVerdict(escalationId, verdict) {
265
+ if (this._report) {
266
+ return { error: "The run has already finished." };
267
+ }
268
+ return this._handle.submit(escalationId, verdict);
269
+ }
270
+ /**
271
+ * Cancel the run and return its final report. The wait is bounded: a run
272
+ * that ignores cancellation used to hang the cancel request itself, so past
273
+ * the deadline the session settles on its own and answers with that.
274
+ */
275
+ async cancel() {
276
+ try {
277
+ this._cancel();
278
+ }
279
+ catch (error) {
280
+ log.warn("cancel threw for a debug session", {
281
+ sessionId: this.id,
282
+ error: String(error)
283
+ });
284
+ }
285
+ let timer;
286
+ const deadline = new Promise((resolve) => {
287
+ timer = setTimeout(() => resolve("timeout"), this._cancelWaitMs);
288
+ timer.unref?.();
289
+ });
290
+ try {
291
+ const outcome = await Promise.race([this._done, deadline]);
292
+ if (outcome !== "timeout")
293
+ return outcome;
294
+ }
295
+ finally {
296
+ if (timer)
297
+ clearTimeout(timer);
298
+ }
299
+ this.forceSettle(`Cancel requested, but the run did not settle within ${this._cancelWaitMs}ms.`);
300
+ return this._done;
301
+ }
302
+ }
303
+ /** Thrown by `create()` when a user already holds the maximum live sessions. */
304
+ export class TooManyDebugSessionsError extends Error {
305
+ constructor(limit) {
306
+ super(`Too many active debug sessions (limit ${limit}). Cancel or finish one ` +
307
+ "with POST /api/debug/sessions/:id/cancel before starting another.");
308
+ this.name = "TooManyDebugSessionsError";
309
+ }
310
+ }
311
+ class DebugSessionRegistry {
312
+ _sessions = new Map();
313
+ /** Live sessions this user holds. */
314
+ liveCount(userId) {
315
+ let count = 0;
316
+ for (const session of this._sessions.values()) {
317
+ if (session.userId === userId && session.isLive())
318
+ count += 1;
319
+ }
320
+ return count;
321
+ }
322
+ create(options) {
323
+ if (this.liveCount(options.userId) >= MAX_LIVE_SESSIONS_PER_USER) {
324
+ throw new TooManyDebugSessionsError(MAX_LIVE_SESSIONS_PER_USER);
325
+ }
326
+ const session = new DebugSession(options, () => {
327
+ clearTimeout(lifetime);
328
+ const timer = setTimeout(() => {
329
+ this._sessions.delete(session.id);
330
+ }, SESSION_DONE_TTL_MS);
331
+ timer.unref?.();
332
+ });
333
+ const lifetime = setTimeout(() => {
334
+ log.warn("debug session hit its lifetime ceiling", {
335
+ sessionId: session.id,
336
+ jobId: options.jobId
337
+ });
338
+ session.forceSettle("The run exceeded the maximum session lifetime and was force-settled.");
339
+ }, options.maxLifetimeMs ?? SESSION_MAX_LIFETIME_MS);
340
+ lifetime.unref?.();
341
+ this._sessions.set(session.id, session);
342
+ log.info("interactive debug session opened", {
343
+ sessionId: session.id,
344
+ jobId: options.jobId,
345
+ workflowId: options.workflowId
346
+ });
347
+ return session;
348
+ }
349
+ /** Ownership is part of the lookup: a foreign session id is a miss. */
350
+ get(sessionId, userId) {
351
+ const session = this._sessions.get(sessionId);
352
+ if (!session || session.userId !== userId)
353
+ return null;
354
+ return session;
355
+ }
356
+ }
357
+ export const debugSessions = new DebugSessionRegistry();
358
+ //# sourceMappingURL=debug-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-sessions.js","sourceRoot":"","sources":["../../src/service/debug-sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@nodetool-ai/execution/service` — workflow execution as a service.
3
+ *
4
+ * Everything the HTTP surface does *except* parse a Request and write a
5
+ * Response: running a saved workflow (plain, debug, or interactive), the
6
+ * in-memory escalation-session registry those interactive runs park in, the
7
+ * kernel runner every app simulation shares, and the app-debug engine.
8
+ *
9
+ * The websocket package keeps the Fastify routes and calls this. So do the
10
+ * agent tools — an agent runs a workflow in-process, never over HTTP.
11
+ */
12
+ export { debugSessions, DebugSession, InteractiveEscalationHandle, TooManyDebugSessionsError, INTERACTIVE_DECISION_TIMEOUT_MS, SESSION_MAX_LIFETIME_MS, CANCEL_SETTLE_TIMEOUT_MS, MAX_LIVE_SESSIONS_PER_USER } from "./debug-sessions.js";
13
+ export type { CreateDebugSessionOptions, DebugSessionEvent, ParkedEscalation } from "./debug-sessions.js";
14
+ export { resolveWorkflowWorkspace, resolveWorkflowWorkspaceDir, workspaceFromRow, setWorkspaceCloudStorage, setWorkspaceChangeNotifier, usesCloudWorkspaces, buildWorkspaceExecutionContext } from "./workflow-workspace.js";
15
+ export type { WorkspaceFileChange } from "./workflow-workspace.js";
16
+ export { createAppServerRunner } from "./app-run-server.js";
17
+ export type { AppServerRunnerOptions } from "./app-run-server.js";
18
+ export { runWorkflow, peekDebugSession, submitEscalationVerdict, cancelDebugSession, buildWorkflowRunPayload, debugSessionEventPayload, boundedRunOption, persistableOutputs, withoutInlineAssetBytes, modelSelectionErrors, MAX_INTERACTIVE_DECISIONS, MAX_INTERACTIVE_RETRIES_PER_NODE, MAX_INTERACTIVE_DECISION_TIMEOUT_MS } from "./workflow-run.js";
19
+ export type { RunModelCatalogs, RunWorkflowOptions, RunWorkflowOutcome, WorkflowRunEnvironment } from "./workflow-run.js";
20
+ export { runApplicationDebug, AppServiceError } from "./app-debug-service.js";
21
+ export type { AppDebugDeps, AppDebugRequest } from "./app-debug-service.js";
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/service/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,2BAA2B,EAC3B,yBAAyB,EACzB,+BAA+B,EAC/B,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,8BAA8B,EAC/B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAElE,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,yBAAyB,EACzB,gCAAgC,EAChC,mCAAmC,EACpC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,eAAe,EAChB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `@nodetool-ai/execution/service` — workflow execution as a service.
3
+ *
4
+ * Everything the HTTP surface does *except* parse a Request and write a
5
+ * Response: running a saved workflow (plain, debug, or interactive), the
6
+ * in-memory escalation-session registry those interactive runs park in, the
7
+ * kernel runner every app simulation shares, and the app-debug engine.
8
+ *
9
+ * The websocket package keeps the Fastify routes and calls this. So do the
10
+ * agent tools — an agent runs a workflow in-process, never over HTTP.
11
+ */
12
+ export { debugSessions, DebugSession, InteractiveEscalationHandle, TooManyDebugSessionsError, INTERACTIVE_DECISION_TIMEOUT_MS, SESSION_MAX_LIFETIME_MS, CANCEL_SETTLE_TIMEOUT_MS, MAX_LIVE_SESSIONS_PER_USER } from "./debug-sessions.js";
13
+ export { resolveWorkflowWorkspace, resolveWorkflowWorkspaceDir, workspaceFromRow, setWorkspaceCloudStorage, setWorkspaceChangeNotifier, usesCloudWorkspaces, buildWorkspaceExecutionContext } from "./workflow-workspace.js";
14
+ export { createAppServerRunner } from "./app-run-server.js";
15
+ export { runWorkflow, peekDebugSession, submitEscalationVerdict, cancelDebugSession, buildWorkflowRunPayload, debugSessionEventPayload, boundedRunOption, persistableOutputs, withoutInlineAssetBytes, modelSelectionErrors, MAX_INTERACTIVE_DECISIONS, MAX_INTERACTIVE_RETRIES_PER_NODE, MAX_INTERACTIVE_DECISION_TIMEOUT_MS } from "./workflow-run.js";
16
+ export { runApplicationDebug, AppServiceError } from "./app-debug-service.js";
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/service/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,2BAA2B,EAC3B,yBAAyB,EACzB,+BAA+B,EAC/B,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,8BAA8B,EAC/B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,yBAAyB,EACzB,gCAAgC,EAChC,mCAAmC,EACpC,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,EACL,mBAAmB,EACnB,eAAe,EAChB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { ProcessingMessage } from "@nodetool-ai/protocol";
2
+ /**
3
+ * Job progress on the job row.
4
+ *
5
+ * A node posts `node_progress` while it works — a render posts one per frame —
6
+ * and until now that message reached only the debug collector, which exists
7
+ * for a finished run. So `get_job` on a background render in its third minute
8
+ * answered "running" and nothing else, which is exactly the moment the caller
9
+ * needs a number. This folds the latest message onto the row.
10
+ *
11
+ * Throttled, because a 25fps two-minute render posts three thousand of them
12
+ * and each write is a database round trip: at most one write every
13
+ * `minIntervalMs`, with a jump of `minPercentStep` or the final frame going
14
+ * through immediately.
15
+ */
16
+ /** The shape read off a `node_progress` message. */
17
+ export interface JobProgress {
18
+ node_id: string;
19
+ progress: number;
20
+ total: number;
21
+ updated_at: string;
22
+ }
23
+ export interface JobProgressRecorderOptions {
24
+ /** Persist one progress value. Rejections are swallowed, not thrown. */
25
+ write: (progress: JobProgress) => Promise<void>;
26
+ /** Injected so the throttle is tested against a clock rather than a wait. */
27
+ now?: () => number;
28
+ minIntervalMs?: number;
29
+ /** Percent of `total` that goes through regardless of the interval. */
30
+ minPercentStep?: number;
31
+ }
32
+ /**
33
+ * A message listener that keeps the job row's progress current.
34
+ *
35
+ * Synchronous on purpose: it is called from the message bus, so it starts the
36
+ * write and returns. A write that fails is dropped — progress is a courtesy,
37
+ * and a database blip must not fail the run it is reporting on.
38
+ */
39
+ export declare function createJobProgressRecorder(options: JobProgressRecorderOptions): (message: ProcessingMessage) => void;
40
+ //# sourceMappingURL=job-progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-progress.d.ts","sourceRoot":"","sources":["../../src/service/job-progress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D;;;;;;;;;;;;;GAaG;AAEH,oDAAoD;AACpD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,KAAK,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AASD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CA0CtC"}
@@ -0,0 +1,53 @@
1
+ const DEFAULT_MIN_INTERVAL_MS = 2000;
2
+ const DEFAULT_MIN_PERCENT_STEP = 5;
3
+ function num(value) {
4
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
5
+ }
6
+ /**
7
+ * A message listener that keeps the job row's progress current.
8
+ *
9
+ * Synchronous on purpose: it is called from the message bus, so it starts the
10
+ * write and returns. A write that fails is dropped — progress is a courtesy,
11
+ * and a database blip must not fail the run it is reporting on.
12
+ */
13
+ export function createJobProgressRecorder(options) {
14
+ const now = options.now ?? Date.now;
15
+ const minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;
16
+ const minPercentStep = options.minPercentStep ?? DEFAULT_MIN_PERCENT_STEP;
17
+ let lastWriteAt = Number.NEGATIVE_INFINITY;
18
+ let lastProgress = null;
19
+ return (message) => {
20
+ if (message.type !== "node_progress")
21
+ return;
22
+ const nodeId = message.node_id;
23
+ const progress = num(message.progress);
24
+ const total = num(message.total);
25
+ if (typeof nodeId !== "string" || progress === null || total === null) {
26
+ return;
27
+ }
28
+ const at = now();
29
+ const stepPercent = total > 0 && lastProgress !== null
30
+ ? ((progress - lastProgress) / total) * 100
31
+ : Number.POSITIVE_INFINITY;
32
+ const finished = total > 0 && progress >= total;
33
+ const due = lastProgress === null ||
34
+ finished ||
35
+ at - lastWriteAt >= minIntervalMs ||
36
+ stepPercent >= minPercentStep;
37
+ if (!due)
38
+ return;
39
+ lastWriteAt = at;
40
+ lastProgress = progress;
41
+ void options
42
+ .write({
43
+ node_id: nodeId,
44
+ progress,
45
+ total,
46
+ updated_at: new Date(at).toISOString()
47
+ })
48
+ .catch(() => {
49
+ // Progress is a courtesy: a failed write must not fail the run.
50
+ });
51
+ };
52
+ }
53
+ //# sourceMappingURL=job-progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-progress.js","sourceRoot":"","sources":["../../src/service/job-progress.ts"],"names":[],"mappings":"AAmCA,MAAM,uBAAuB,GAAG,IAAI,CAAC;AACrC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAEnC,SAAS,GAAG,CAAC,KAAc;IACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAmC;IAEnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;IACvE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,wBAAwB,CAAC;IAC1E,IAAI,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAC3C,IAAI,YAAY,GAAkB,IAAI,CAAC;IAEvC,OAAO,CAAC,OAA0B,EAAQ,EAAE;QAC1C,IAAI,OAAO,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACtE,OAAO;QACT,CAAC;QAED,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;QACjB,MAAM,WAAW,GACf,KAAK,GAAG,CAAC,IAAI,YAAY,KAAK,IAAI;YAChC,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,YAAY,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG;YAC3C,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAC/B,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,IAAI,QAAQ,IAAI,KAAK,CAAC;QAChD,MAAM,GAAG,GACP,YAAY,KAAK,IAAI;YACrB,QAAQ;YACR,EAAE,GAAG,WAAW,IAAI,aAAa;YACjC,WAAW,IAAI,cAAc,CAAC;QAChC,IAAI,CAAC,GAAG;YAAE,OAAO;QAEjB,WAAW,GAAG,EAAE,CAAC;QACjB,YAAY,GAAG,QAAQ,CAAC;QACxB,KAAK,OAAO;aACT,KAAK,CAAC;YACL,OAAO,EAAE,MAAM;YACf,QAAQ;YACR,KAAK;YACL,UAAU,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE;SACvC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,gEAAgE;QAClE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;AACJ,CAAC"}