@nodetool-ai/websocket 0.8.1 → 0.8.3

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 (471) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/chat-turn-registry.d.ts +2 -1
  3. package/dist/chat-turn-registry.d.ts.map +1 -1
  4. package/dist/chat-turn-registry.js +8 -1
  5. package/dist/chat-turn-registry.js.map +1 -1
  6. package/dist/collection-api.d.ts.map +1 -1
  7. package/dist/collection-api.js +41 -6
  8. package/dist/collection-api.js.map +1 -1
  9. package/dist/custom-providers.d.ts.map +1 -1
  10. package/dist/custom-providers.js +6 -1
  11. package/dist/custom-providers.js.map +1 -1
  12. package/dist/error-traces.d.ts +56 -0
  13. package/dist/error-traces.d.ts.map +1 -0
  14. package/dist/error-traces.js +179 -0
  15. package/dist/error-traces.js.map +1 -0
  16. package/dist/example-workflows.d.ts.map +1 -1
  17. package/dist/example-workflows.js +6 -0
  18. package/dist/example-workflows.js.map +1 -1
  19. package/dist/fake-runtime.d.ts +41 -6
  20. package/dist/fake-runtime.d.ts.map +1 -1
  21. package/dist/fake-runtime.js +247 -16
  22. package/dist/fake-runtime.js.map +1 -1
  23. package/dist/file-api.d.ts.map +1 -1
  24. package/dist/file-api.js +6 -8
  25. package/dist/file-api.js.map +1 -1
  26. package/dist/generation-recovery.d.ts.map +1 -1
  27. package/dist/generation-recovery.js +32 -7
  28. package/dist/generation-recovery.js.map +1 -1
  29. package/dist/headless-job-runner.d.ts.map +1 -1
  30. package/dist/headless-job-runner.js +5 -1
  31. package/dist/headless-job-runner.js.map +1 -1
  32. package/dist/http-api.d.ts +3 -1
  33. package/dist/http-api.d.ts.map +1 -1
  34. package/dist/http-api.js +66 -9
  35. package/dist/http-api.js.map +1 -1
  36. package/dist/http-body-schemas.d.ts +2 -0
  37. package/dist/http-body-schemas.d.ts.map +1 -1
  38. package/dist/http-body-schemas.js +8 -1
  39. package/dist/http-body-schemas.js.map +1 -1
  40. package/dist/index.d.ts +0 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +0 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/interrupted-jobs.d.ts +14 -0
  45. package/dist/interrupted-jobs.d.ts.map +1 -0
  46. package/dist/interrupted-jobs.js +28 -0
  47. package/dist/interrupted-jobs.js.map +1 -0
  48. package/dist/lib/admin.d.ts +7 -0
  49. package/dist/lib/admin.d.ts.map +1 -0
  50. package/dist/lib/admin.js +20 -0
  51. package/dist/lib/admin.js.map +1 -0
  52. package/dist/lib/app-debug-service.js +1 -1
  53. package/dist/lib/app-debug-service.js.map +1 -1
  54. package/dist/lib/app-instances-service.d.ts +1319 -0
  55. package/dist/lib/app-instances-service.d.ts.map +1 -0
  56. package/dist/lib/app-instances-service.js +377 -0
  57. package/dist/lib/app-instances-service.js.map +1 -0
  58. package/dist/lib/app-project-export.d.ts +12 -0
  59. package/dist/lib/app-project-export.d.ts.map +1 -0
  60. package/dist/lib/app-project-export.js +42 -0
  61. package/dist/lib/app-project-export.js.map +1 -0
  62. package/dist/lib/app-run-cancellation.d.ts +4 -0
  63. package/dist/lib/app-run-cancellation.d.ts.map +1 -0
  64. package/dist/lib/app-run-cancellation.js +28 -0
  65. package/dist/lib/app-run-cancellation.js.map +1 -0
  66. package/dist/lib/applications-service.d.ts +182 -1
  67. package/dist/lib/applications-service.d.ts.map +1 -1
  68. package/dist/lib/applications-service.js +27 -6
  69. package/dist/lib/applications-service.js.map +1 -1
  70. package/dist/lib/asset-export.d.ts +6 -2
  71. package/dist/lib/asset-export.d.ts.map +1 -1
  72. package/dist/lib/asset-export.js +15 -7
  73. package/dist/lib/asset-export.js.map +1 -1
  74. package/dist/lib/asset-paths.d.ts +7 -11
  75. package/dist/lib/asset-paths.d.ts.map +1 -1
  76. package/dist/lib/asset-paths.js +8 -56
  77. package/dist/lib/asset-paths.js.map +1 -1
  78. package/dist/lib/asset-response.d.ts.map +1 -1
  79. package/dist/lib/asset-response.js +3 -1
  80. package/dist/lib/asset-response.js.map +1 -1
  81. package/dist/lib/audio-peaks.d.ts.map +1 -1
  82. package/dist/lib/audio-peaks.js +5 -1
  83. package/dist/lib/audio-peaks.js.map +1 -1
  84. package/dist/lib/bridge.d.ts.map +1 -1
  85. package/dist/lib/bridge.js.map +1 -1
  86. package/dist/lib/cloud-profile.d.ts +10 -0
  87. package/dist/lib/cloud-profile.d.ts.map +1 -0
  88. package/dist/lib/cloud-profile.js +13 -0
  89. package/dist/lib/cloud-profile.js.map +1 -0
  90. package/dist/lib/document-model-interfaces.d.ts.map +1 -1
  91. package/dist/lib/document-model-interfaces.js +9 -8
  92. package/dist/lib/document-model-interfaces.js.map +1 -1
  93. package/dist/lib/example-apps.d.ts +9 -0
  94. package/dist/lib/example-apps.d.ts.map +1 -1
  95. package/dist/lib/example-apps.js +61 -14
  96. package/dist/lib/example-apps.js.map +1 -1
  97. package/dist/lib/http-tracing.d.ts +12 -0
  98. package/dist/lib/http-tracing.d.ts.map +1 -0
  99. package/dist/lib/http-tracing.js +81 -0
  100. package/dist/lib/http-tracing.js.map +1 -0
  101. package/dist/lib/http-user-id.d.ts +2 -0
  102. package/dist/lib/http-user-id.d.ts.map +1 -0
  103. package/dist/lib/http-user-id.js +4 -0
  104. package/dist/lib/http-user-id.js.map +1 -0
  105. package/dist/lib/json-body.d.ts +11 -0
  106. package/dist/lib/json-body.d.ts.map +1 -0
  107. package/dist/lib/json-body.js +13 -0
  108. package/dist/lib/json-body.js.map +1 -0
  109. package/dist/lib/media.d.ts +1 -6
  110. package/dist/lib/media.d.ts.map +1 -1
  111. package/dist/lib/media.js +8 -44
  112. package/dist/lib/media.js.map +1 -1
  113. package/dist/lib/public-routes.d.ts +22 -0
  114. package/dist/lib/public-routes.d.ts.map +1 -1
  115. package/dist/lib/public-routes.js +41 -0
  116. package/dist/lib/public-routes.js.map +1 -1
  117. package/dist/lib/public-workflow-share.d.ts +31 -0
  118. package/dist/lib/public-workflow-share.d.ts.map +1 -0
  119. package/dist/lib/public-workflow-share.js +88 -0
  120. package/dist/lib/public-workflow-share.js.map +1 -0
  121. package/dist/lib/python-metadata-roots.d.ts +27 -0
  122. package/dist/lib/python-metadata-roots.d.ts.map +1 -0
  123. package/dist/lib/python-metadata-roots.js +92 -0
  124. package/dist/lib/python-metadata-roots.js.map +1 -0
  125. package/dist/lib/run-trace-live-delivery.d.ts +25 -0
  126. package/dist/lib/run-trace-live-delivery.d.ts.map +1 -0
  127. package/dist/lib/run-trace-live-delivery.js +91 -0
  128. package/dist/lib/run-trace-live-delivery.js.map +1 -0
  129. package/dist/lib/runtime-detection.d.ts +1 -1
  130. package/dist/lib/runtime-detection.d.ts.map +1 -1
  131. package/dist/lib/runtime-detection.js +2 -1
  132. package/dist/lib/runtime-detection.js.map +1 -1
  133. package/dist/lib/server-auth-token.d.ts +18 -0
  134. package/dist/lib/server-auth-token.d.ts.map +1 -0
  135. package/dist/lib/server-auth-token.js +28 -0
  136. package/dist/lib/server-auth-token.js.map +1 -0
  137. package/dist/lib/test-ui-run-routes.d.ts +8 -0
  138. package/dist/lib/test-ui-run-routes.d.ts.map +1 -0
  139. package/dist/lib/test-ui-run-routes.js +42 -0
  140. package/dist/lib/test-ui-run-routes.js.map +1 -0
  141. package/dist/lib/thumbnail.d.ts.map +1 -1
  142. package/dist/lib/thumbnail.js +12 -9
  143. package/dist/lib/thumbnail.js.map +1 -1
  144. package/dist/lib/timeline-bundle.d.ts +159 -16
  145. package/dist/lib/timeline-bundle.d.ts.map +1 -1
  146. package/dist/lib/timeline-bundle.js +34 -6
  147. package/dist/lib/timeline-bundle.js.map +1 -1
  148. package/dist/lib/timeline-media-export.d.ts +18 -0
  149. package/dist/lib/timeline-media-export.d.ts.map +1 -0
  150. package/dist/lib/timeline-media-export.js +66 -0
  151. package/dist/lib/timeline-media-export.js.map +1 -0
  152. package/dist/lib/timeline-premiere-import.d.ts +24 -0
  153. package/dist/lib/timeline-premiere-import.d.ts.map +1 -0
  154. package/dist/lib/timeline-premiere-import.js +102 -0
  155. package/dist/lib/timeline-premiere-import.js.map +1 -0
  156. package/dist/lib/timeline-premiere.d.ts +38 -0
  157. package/dist/lib/timeline-premiere.d.ts.map +1 -0
  158. package/dist/lib/timeline-premiere.js +87 -0
  159. package/dist/lib/timeline-premiere.js.map +1 -0
  160. package/dist/lib/video-proxy.d.ts.map +1 -1
  161. package/dist/lib/video-proxy.js +3 -2
  162. package/dist/lib/video-proxy.js.map +1 -1
  163. package/dist/lib/workflow-service.d.ts.map +1 -1
  164. package/dist/lib/workflow-service.js +4 -1
  165. package/dist/lib/workflow-service.js.map +1 -1
  166. package/dist/mcp-agent-tools.d.ts.map +1 -1
  167. package/dist/mcp-agent-tools.js +95 -162
  168. package/dist/mcp-agent-tools.js.map +1 -1
  169. package/dist/mcp-client-config.d.ts +64 -0
  170. package/dist/mcp-client-config.d.ts.map +1 -0
  171. package/dist/mcp-client-config.js +353 -0
  172. package/dist/mcp-client-config.js.map +1 -0
  173. package/dist/mcp-server.d.ts +7 -0
  174. package/dist/mcp-server.d.ts.map +1 -1
  175. package/dist/mcp-server.js +163 -16
  176. package/dist/mcp-server.js.map +1 -1
  177. package/dist/mcp-skill-prompts.d.ts +23 -0
  178. package/dist/mcp-skill-prompts.d.ts.map +1 -0
  179. package/dist/mcp-skill-prompts.js +91 -0
  180. package/dist/mcp-skill-prompts.js.map +1 -0
  181. package/dist/mcp-tool-deps.d.ts.map +1 -1
  182. package/dist/mcp-tool-deps.js +8 -1
  183. package/dist/mcp-tool-deps.js.map +1 -1
  184. package/dist/models-api.d.ts +10 -0
  185. package/dist/models-api.d.ts.map +1 -1
  186. package/dist/models-api.js +29 -2
  187. package/dist/models-api.js.map +1 -1
  188. package/dist/node-registry-setup.d.ts +1 -1
  189. package/dist/node-registry-setup.d.ts.map +1 -1
  190. package/dist/node-registry-setup.js +21 -114
  191. package/dist/node-registry-setup.js.map +1 -1
  192. package/dist/oauth-api.d.ts.map +1 -1
  193. package/dist/oauth-api.js +45 -23
  194. package/dist/oauth-api.js.map +1 -1
  195. package/dist/openai-api.d.ts.map +1 -1
  196. package/dist/openai-api.js +10 -2
  197. package/dist/openai-api.js.map +1 -1
  198. package/dist/plugins/websocket.d.ts.map +1 -1
  199. package/dist/plugins/websocket.js +27 -59
  200. package/dist/plugins/websocket.js.map +1 -1
  201. package/dist/python-bridge-gate.d.ts +28 -0
  202. package/dist/python-bridge-gate.d.ts.map +1 -0
  203. package/dist/python-bridge-gate.js +36 -0
  204. package/dist/python-bridge-gate.js.map +1 -0
  205. package/dist/routes/app-runs.d.ts +4 -0
  206. package/dist/routes/app-runs.d.ts.map +1 -0
  207. package/dist/routes/app-runs.js +173 -0
  208. package/dist/routes/app-runs.js.map +1 -0
  209. package/dist/routes/applications.d.ts +1 -0
  210. package/dist/routes/applications.d.ts.map +1 -1
  211. package/dist/routes/applications.js +24 -0
  212. package/dist/routes/applications.js.map +1 -1
  213. package/dist/routes/assets.d.ts.map +1 -1
  214. package/dist/routes/assets.js +31 -41
  215. package/dist/routes/assets.js.map +1 -1
  216. package/dist/routes/config.d.ts.map +1 -1
  217. package/dist/routes/config.js +6 -0
  218. package/dist/routes/config.js.map +1 -1
  219. package/dist/routes/documents.d.ts.map +1 -1
  220. package/dist/routes/documents.js +24 -0
  221. package/dist/routes/documents.js.map +1 -1
  222. package/dist/routes/fal-pricing-estimate.d.ts.map +1 -1
  223. package/dist/routes/fal-pricing-estimate.js +2 -0
  224. package/dist/routes/fal-pricing-estimate.js.map +1 -1
  225. package/dist/routes/files.d.ts.map +1 -1
  226. package/dist/routes/files.js +2 -0
  227. package/dist/routes/files.js.map +1 -1
  228. package/dist/routes/games.d.ts +38 -0
  229. package/dist/routes/games.d.ts.map +1 -0
  230. package/dist/routes/games.js +158 -0
  231. package/dist/routes/games.js.map +1 -0
  232. package/dist/routes/integrations.d.ts.map +1 -1
  233. package/dist/routes/integrations.js +22 -26
  234. package/dist/routes/integrations.js.map +1 -1
  235. package/dist/routes/js-scripts.d.ts +10 -4
  236. package/dist/routes/js-scripts.d.ts.map +1 -1
  237. package/dist/routes/js-scripts.js +451 -69
  238. package/dist/routes/js-scripts.js.map +1 -1
  239. package/dist/routes/nodes.d.ts.map +1 -1
  240. package/dist/routes/nodes.js +34 -1
  241. package/dist/routes/nodes.js.map +1 -1
  242. package/dist/routes/public-shared-workflows.d.ts +16 -0
  243. package/dist/routes/public-shared-workflows.d.ts.map +1 -0
  244. package/dist/routes/public-shared-workflows.js +55 -0
  245. package/dist/routes/public-shared-workflows.js.map +1 -0
  246. package/dist/routes/run-spans.d.ts +4 -0
  247. package/dist/routes/run-spans.d.ts.map +1 -0
  248. package/dist/routes/run-spans.js +53 -0
  249. package/dist/routes/run-spans.js.map +1 -0
  250. package/dist/routes/storage.d.ts.map +1 -1
  251. package/dist/routes/storage.js +2 -0
  252. package/dist/routes/storage.js.map +1 -1
  253. package/dist/routes/storyboards.d.ts.map +1 -1
  254. package/dist/routes/storyboards.js +6 -3
  255. package/dist/routes/storyboards.js.map +1 -1
  256. package/dist/routes/timeline-fonts.d.ts +22 -0
  257. package/dist/routes/timeline-fonts.d.ts.map +1 -1
  258. package/dist/routes/timeline-fonts.js +138 -7
  259. package/dist/routes/timeline-fonts.js.map +1 -1
  260. package/dist/routes/timelines.d.ts +8 -4
  261. package/dist/routes/timelines.d.ts.map +1 -1
  262. package/dist/routes/timelines.js +209 -16
  263. package/dist/routes/timelines.js.map +1 -1
  264. package/dist/screenshot-docs-seed.d.ts +24 -0
  265. package/dist/screenshot-docs-seed.d.ts.map +1 -0
  266. package/dist/screenshot-docs-seed.js +414 -0
  267. package/dist/screenshot-docs-seed.js.map +1 -0
  268. package/dist/screenshot-projects.d.ts.map +1 -1
  269. package/dist/screenshot-projects.js +9 -9
  270. package/dist/screenshot-projects.js.map +1 -1
  271. package/dist/screenshot-server.js +114 -20
  272. package/dist/screenshot-server.js.map +1 -1
  273. package/dist/sdk/sdk-model-download-service.d.ts.map +1 -1
  274. package/dist/sdk/sdk-model-download-service.js +5 -2
  275. package/dist/sdk/sdk-model-download-service.js.map +1 -1
  276. package/dist/server.js +173 -109
  277. package/dist/server.js.map +1 -1
  278. package/dist/session/app-run-fold.d.ts +7 -0
  279. package/dist/session/app-run-fold.d.ts.map +1 -0
  280. package/dist/session/app-run-fold.js +45 -0
  281. package/dist/session/app-run-fold.js.map +1 -0
  282. package/dist/session/chat-prompt.d.ts.map +1 -1
  283. package/dist/session/chat-prompt.js +37 -15
  284. package/dist/session/chat-prompt.js.map +1 -1
  285. package/dist/session/chat-turn.d.ts +11 -0
  286. package/dist/session/chat-turn.d.ts.map +1 -1
  287. package/dist/session/chat-turn.js +270 -116
  288. package/dist/session/chat-turn.js.map +1 -1
  289. package/dist/session/commands.d.ts +14 -0
  290. package/dist/session/commands.d.ts.map +1 -1
  291. package/dist/session/commands.js +119 -14
  292. package/dist/session/commands.js.map +1 -1
  293. package/dist/session/inference.d.ts +30 -2
  294. package/dist/session/inference.d.ts.map +1 -1
  295. package/dist/session/inference.js +165 -16
  296. package/dist/session/inference.js.map +1 -1
  297. package/dist/session/job-execution.d.ts +7 -1
  298. package/dist/session/job-execution.d.ts.map +1 -1
  299. package/dist/session/job-execution.js +329 -42
  300. package/dist/session/job-execution.js.map +1 -1
  301. package/dist/session/model-interfaces.d.ts +2 -1
  302. package/dist/session/model-interfaces.d.ts.map +1 -1
  303. package/dist/session/model-interfaces.js +1 -0
  304. package/dist/session/model-interfaces.js.map +1 -1
  305. package/dist/storage-api.d.ts +0 -4
  306. package/dist/storage-api.d.ts.map +1 -1
  307. package/dist/storage-api.js +3 -26
  308. package/dist/storage-api.js.map +1 -1
  309. package/dist/storage-retention.d.ts +5 -0
  310. package/dist/storage-retention.d.ts.map +1 -1
  311. package/dist/storage-retention.js +22 -1
  312. package/dist/storage-retention.js.map +1 -1
  313. package/dist/test-ui-server.d.ts +11 -0
  314. package/dist/test-ui-server.d.ts.map +1 -1
  315. package/dist/test-ui-server.js +84 -6
  316. package/dist/test-ui-server.js.map +1 -1
  317. package/dist/timeline-generation-recovery.d.ts +4 -0
  318. package/dist/timeline-generation-recovery.d.ts.map +1 -0
  319. package/dist/timeline-generation-recovery.js +72 -0
  320. package/dist/timeline-generation-recovery.js.map +1 -0
  321. package/dist/triggers/dispatcher.d.ts.map +1 -1
  322. package/dist/triggers/dispatcher.js +26 -6
  323. package/dist/triggers/dispatcher.js.map +1 -1
  324. package/dist/triggers/file-watch.d.ts.map +1 -1
  325. package/dist/triggers/file-watch.js +35 -19
  326. package/dist/triggers/file-watch.js.map +1 -1
  327. package/dist/triggers/scheduler.d.ts.map +1 -1
  328. package/dist/triggers/scheduler.js +7 -5
  329. package/dist/triggers/scheduler.js.map +1 -1
  330. package/dist/triggers/stores.js +8 -8
  331. package/dist/triggers/stores.js.map +1 -1
  332. package/dist/triggers/webhook-route.js +2 -2
  333. package/dist/triggers/webhook-route.js.map +1 -1
  334. package/dist/trpc/error-formatter.d.ts.map +1 -1
  335. package/dist/trpc/error-formatter.js +2 -1
  336. package/dist/trpc/error-formatter.js.map +1 -1
  337. package/dist/trpc/error-logging.d.ts +10 -0
  338. package/dist/trpc/error-logging.d.ts.map +1 -1
  339. package/dist/trpc/error-logging.js +21 -0
  340. package/dist/trpc/error-logging.js.map +1 -1
  341. package/dist/trpc/router.d.ts +100 -31028
  342. package/dist/trpc/router.d.ts.map +1 -1
  343. package/dist/trpc/router.js +12 -3
  344. package/dist/trpc/router.js.map +1 -1
  345. package/dist/trpc/routers/app-instances.d.ts +2332 -0
  346. package/dist/trpc/routers/app-instances.d.ts.map +1 -0
  347. package/dist/trpc/routers/app-instances.js +52 -0
  348. package/dist/trpc/routers/app-instances.js.map +1 -0
  349. package/dist/trpc/routers/app-runs.d.ts +1120 -0
  350. package/dist/trpc/routers/app-runs.d.ts.map +1 -0
  351. package/dist/trpc/routers/app-runs.js +28 -0
  352. package/dist/trpc/routers/app-runs.js.map +1 -0
  353. package/dist/trpc/routers/applications.d.ts +1102 -0
  354. package/dist/trpc/routers/applications.d.ts.map +1 -1
  355. package/dist/trpc/routers/applications.js +5 -2
  356. package/dist/trpc/routers/applications.js.map +1 -1
  357. package/dist/trpc/routers/assets.d.ts +18 -0
  358. package/dist/trpc/routers/assets.d.ts.map +1 -1
  359. package/dist/trpc/routers/assets.js +20 -5
  360. package/dist/trpc/routers/assets.js.map +1 -1
  361. package/dist/trpc/routers/bug-reports.d.ts +33 -0
  362. package/dist/trpc/routers/bug-reports.d.ts.map +1 -0
  363. package/dist/trpc/routers/bug-reports.js +69 -0
  364. package/dist/trpc/routers/bug-reports.js.map +1 -0
  365. package/dist/trpc/routers/collections.d.ts.map +1 -1
  366. package/dist/trpc/routers/collections.js +16 -10
  367. package/dist/trpc/routers/collections.js.map +1 -1
  368. package/dist/trpc/routers/credits.d.ts.map +1 -1
  369. package/dist/trpc/routers/credits.js +11 -1
  370. package/dist/trpc/routers/credits.js.map +1 -1
  371. package/dist/trpc/routers/documents.d.ts.map +1 -1
  372. package/dist/trpc/routers/documents.js +8 -2
  373. package/dist/trpc/routers/documents.js.map +1 -1
  374. package/dist/trpc/routers/error-traces.d.ts +132 -0
  375. package/dist/trpc/routers/error-traces.d.ts.map +1 -0
  376. package/dist/trpc/routers/error-traces.js +118 -0
  377. package/dist/trpc/routers/error-traces.js.map +1 -0
  378. package/dist/trpc/routers/extension.d.ts +3 -3
  379. package/dist/trpc/routers/extension.d.ts.map +1 -1
  380. package/dist/trpc/routers/extension.js +13 -9
  381. package/dist/trpc/routers/extension.js.map +1 -1
  382. package/dist/trpc/routers/gameDraftHistory.d.ts +7 -0
  383. package/dist/trpc/routers/gameDraftHistory.d.ts.map +1 -0
  384. package/dist/trpc/routers/gameDraftHistory.js +40 -0
  385. package/dist/trpc/routers/gameDraftHistory.js.map +1 -0
  386. package/dist/trpc/routers/games.d.ts +59974 -5414
  387. package/dist/trpc/routers/games.d.ts.map +1 -1
  388. package/dist/trpc/routers/games.js +531 -136
  389. package/dist/trpc/routers/games.js.map +1 -1
  390. package/dist/trpc/routers/jobs.d.ts +42 -0
  391. package/dist/trpc/routers/jobs.d.ts.map +1 -1
  392. package/dist/trpc/routers/jobs.js +89 -4
  393. package/dist/trpc/routers/jobs.js.map +1 -1
  394. package/dist/trpc/routers/js-scripts.d.ts.map +1 -1
  395. package/dist/trpc/routers/js-scripts.js +18 -2
  396. package/dist/trpc/routers/js-scripts.js.map +1 -1
  397. package/dist/trpc/routers/mcp-config.d.ts +3 -1
  398. package/dist/trpc/routers/mcp-config.d.ts.map +1 -1
  399. package/dist/trpc/routers/mcp-config.js +46 -208
  400. package/dist/trpc/routers/mcp-config.js.map +1 -1
  401. package/dist/trpc/routers/messages.d.ts +10 -0
  402. package/dist/trpc/routers/messages.d.ts.map +1 -1
  403. package/dist/trpc/routers/messages.js +16 -2
  404. package/dist/trpc/routers/messages.js.map +1 -1
  405. package/dist/trpc/routers/models.d.ts +130 -0
  406. package/dist/trpc/routers/models.d.ts.map +1 -1
  407. package/dist/trpc/routers/models.js +119 -61
  408. package/dist/trpc/routers/models.js.map +1 -1
  409. package/dist/trpc/routers/packs.d.ts.map +1 -1
  410. package/dist/trpc/routers/packs.js +18 -4
  411. package/dist/trpc/routers/packs.js.map +1 -1
  412. package/dist/trpc/routers/projects.d.ts +66 -2
  413. package/dist/trpc/routers/projects.d.ts.map +1 -1
  414. package/dist/trpc/routers/projects.js +19 -2
  415. package/dist/trpc/routers/projects.js.map +1 -1
  416. package/dist/trpc/routers/runs.d.ts +472 -0
  417. package/dist/trpc/routers/runs.d.ts.map +1 -0
  418. package/dist/trpc/routers/runs.js +40 -0
  419. package/dist/trpc/routers/runs.js.map +1 -0
  420. package/dist/trpc/routers/settings.d.ts +3 -0
  421. package/dist/trpc/routers/settings.d.ts.map +1 -1
  422. package/dist/trpc/routers/settings.js +32 -5
  423. package/dist/trpc/routers/settings.js.map +1 -1
  424. package/dist/trpc/routers/sketch.d.ts +44 -0
  425. package/dist/trpc/routers/sketch.d.ts.map +1 -1
  426. package/dist/trpc/routers/sketch.js +2 -2
  427. package/dist/trpc/routers/sketch.js.map +1 -1
  428. package/dist/trpc/routers/storyboards.d.ts +903 -1
  429. package/dist/trpc/routers/storyboards.d.ts.map +1 -1
  430. package/dist/trpc/routers/storyboards.js +8 -5
  431. package/dist/trpc/routers/storyboards.js.map +1 -1
  432. package/dist/trpc/routers/threads.d.ts.map +1 -1
  433. package/dist/trpc/routers/threads.js +8 -2
  434. package/dist/trpc/routers/threads.js.map +1 -1
  435. package/dist/trpc/routers/timeline.d.ts +647 -63
  436. package/dist/trpc/routers/timeline.d.ts.map +1 -1
  437. package/dist/trpc/routers/timeline.js +193 -4
  438. package/dist/trpc/routers/timeline.js.map +1 -1
  439. package/dist/trpc/routers/triggers.d.ts.map +1 -1
  440. package/dist/trpc/routers/triggers.js +18 -3
  441. package/dist/trpc/routers/triggers.js.map +1 -1
  442. package/dist/trpc/routers/users.d.ts +3 -2
  443. package/dist/trpc/routers/users.d.ts.map +1 -1
  444. package/dist/trpc/routers/users.js +25 -27
  445. package/dist/trpc/routers/users.js.map +1 -1
  446. package/dist/trpc/routers/worker.d.ts +10 -9
  447. package/dist/trpc/routers/worker.d.ts.map +1 -1
  448. package/dist/trpc/routers/worker.js +40 -16
  449. package/dist/trpc/routers/worker.js.map +1 -1
  450. package/dist/trpc/routers/workflows.d.ts +202 -3
  451. package/dist/trpc/routers/workflows.d.ts.map +1 -1
  452. package/dist/trpc/routers/workflows.js +72 -12
  453. package/dist/trpc/routers/workflows.js.map +1 -1
  454. package/dist/trpc/sandbox-coverage.d.ts.map +1 -1
  455. package/dist/trpc/sandbox-coverage.js +119 -0
  456. package/dist/trpc/sandbox-coverage.js.map +1 -1
  457. package/dist/websocket-client-session.d.ts +4 -2
  458. package/dist/websocket-client-session.d.ts.map +1 -1
  459. package/dist/websocket-client-session.js +23 -3
  460. package/dist/websocket-client-session.js.map +1 -1
  461. package/dist/worker-settings-env.d.ts +23 -0
  462. package/dist/worker-settings-env.d.ts.map +1 -0
  463. package/dist/worker-settings-env.js +47 -0
  464. package/dist/worker-settings-env.js.map +1 -0
  465. package/dist/workflow-interface-service.d.ts +7 -0
  466. package/dist/workflow-interface-service.d.ts.map +1 -1
  467. package/package.json +58 -41
  468. package/dist/extension-cdp-bridge.d.ts +0 -85
  469. package/dist/extension-cdp-bridge.d.ts.map +0 -1
  470. package/dist/extension-cdp-bridge.js +0 -163
  471. package/dist/extension-cdp-bridge.js.map +0 -1
@@ -1,3 +1,6 @@
1
+ import { ROOT_CONTEXT, propagation, trace, isSpanContextValid } from "@opentelemetry/api";
2
+ import { getRegisteredRunTrace } from "@nodetool-ai/models";
3
+ import { ensureRunTraceTelemetry, openAppRunTrace, registerWorkflowRunTrace } from "@nodetool-ai/execution";
1
4
  /**
2
5
  * Everything between "run_job arrived" and "terminal status persisted": the
3
6
  * admission gates, the concurrency queue, run start-up, the message stream,
@@ -9,7 +12,9 @@
9
12
  * {@link JobExecutionDeps}.
10
13
  */
11
14
  import { randomUUID } from "node:crypto";
15
+ import { operationTarget, parseInputStateKey } from "@nodetool-ai/app-runtime";
12
16
  import { ApiErrorCode } from "../error-codes.js";
17
+ import { captureError } from "../error-traces.js";
13
18
  import { admitSpend, releaseSpend, reserveSpend } from "../credit-gate.js";
14
19
  import { JobConcurrencyQueue } from "../job-queue.js";
15
20
  import { isBoolean, isFiniteNumber, isFunctionValue, isNonEmptyString, isNumber, isObjectLike, isRecord, isString } from "../lib/wire-values.js";
@@ -18,17 +23,19 @@ import { ExecutionSession, isExecutionPreflightError, isUnitBilledCapability, pr
18
23
  import { persistableOutputs, withoutInlineAssetBytes } from "@nodetool-ai/execution/service";
19
24
  import { createRunSupervisor } from "../run-supervisor.js";
20
25
  import { jobRunRegistry } from "../job-run-registry.js";
21
- import { Application, Asset, Job, listApplicationVersions, invocationIdInUse, releasedApplicationRelease, releasedApplicationVersion, reserveInvocation, settleInvocation, Workflow } from "@nodetool-ai/models";
26
+ import { Application, AppRunError, claimAppRun, ensureDefaultAppInstance, findAppRunByInvocation, getAppInstance, getAppRun, Asset, Job, listApplicationVersions, invocationIdInUse, releasedApplicationRelease, releasedApplicationVersion, reconcileAppRunCost, reserveInvocation, reserveAppRun, setAppRunInputs, settleAppRun, updateAppRunEstimate, settleInvocation, Workflow } from "@nodetool-ai/models";
22
27
  import { getInstanceId } from "../lib/instance-id.js";
23
28
  import { requestRemoteJobCancel } from "../job-control.js";
24
29
  import { estimateWorkflowCost, nodeExpectedQuantity } from "@nodetool-ai/node-sdk/cost-estimate";
25
30
  import { extractPricingParams } from "@nodetool-ai/node-sdk/pricing-params";
26
31
  import { getModelUnitPrice } from "@nodetool-ai/model-pricing";
27
32
  import { applicationReleaseResponse } from "@nodetool-ai/protocol/api-schemas/applications.js";
33
+ import { appRunSnapshot } from "@nodetool-ai/protocol/api-schemas/app-runs.js";
28
34
  import { confineRunRequest, isRunRefusal } from "../lib/app-session-scope.js";
29
35
  import { releaseBlockedReason } from "../lib/app-deployment-service.js";
30
36
  import { autoSaveAssets, primaryTextOutputName } from "./asset-autosave.js";
31
37
  import { createRuntimeContext } from "./model-interfaces.js";
38
+ import { createAppRunFold } from "./app-run-fold.js";
32
39
  import { formatSanitizedError, sanitizeLargeText } from "./sanitize.js";
33
40
  import { createLogger } from "@nodetool-ai/config";
34
41
  const log = createLogger("nodetool.websocket.runner");
@@ -50,9 +57,6 @@ export function resolveRunJobExecutionOptions(value, sdkDefaults = false) {
50
57
  : "auto"
51
58
  };
52
59
  }
53
- export function resolveRunJobUserId(requestUserId, connectionUserId) {
54
- return requestUserId?.trim() || connectionUserId;
55
- }
56
60
  export function createRelayActivityWaiter(context, executionSettled, abortSignal) {
57
61
  let pending = context.hasMessages();
58
62
  let resolveWaiter = null;
@@ -374,7 +378,19 @@ export class JobExecutionManager {
374
378
  */
375
379
  async emitBeforeRunFailure(jobId, workflowId, err, persistJob) {
376
380
  const errorMessage = err instanceof Error ? err.message : String(err);
381
+ const appRun = await findAppRunByInvocation(this.session.requireUserId(), jobId);
382
+ if (appRun) {
383
+ await settleAppRun(this.session.requireUserId(), appRun.id, {
384
+ status: "failed",
385
+ error: errorMessage
386
+ });
387
+ }
377
388
  this.session.logError("beforeRunJob failed", err);
389
+ captureError(err, {
390
+ source: "job",
391
+ userId: this.session.userId,
392
+ context: { job_id: jobId, workflow_id: workflowId ?? "" }
393
+ });
378
394
  await this.session.send({
379
395
  type: "job_update",
380
396
  status: "failed",
@@ -589,6 +605,9 @@ export class JobExecutionManager {
589
605
  * telemetry, which is the same ledger.
590
606
  */
591
607
  async admitApplicationRun(req) {
608
+ if (req.app_run_id || this.session.appSession) {
609
+ return this.admitDurableAppRun(req);
610
+ }
592
611
  const applicationId = req.application_id;
593
612
  if (!applicationId)
594
613
  return true;
@@ -712,6 +731,144 @@ export class JobExecutionManager {
712
731
  }
713
732
  return true;
714
733
  }
734
+ async admitDurableAppRun(req) {
735
+ const userId = this.session.requireUserId();
736
+ const jobId = req.job_id ?? randomUUID();
737
+ req.job_id = jobId;
738
+ let claimedRunId = null;
739
+ try {
740
+ if (this.session.appSession && req.application_id) {
741
+ const release = await releasedApplicationRelease(req.application_id, userId);
742
+ if (!release) {
743
+ throw new Error("Application release not found");
744
+ }
745
+ const instance = await ensureDefaultAppInstance({
746
+ userId,
747
+ applicationId: req.application_id,
748
+ sourceId: `public:${req.application_id}:${release.version}`,
749
+ version: release.version,
750
+ name: "Visitor runs",
751
+ snapshot: appRunSnapshot.parse({
752
+ document: release.document,
753
+ workflow_graphs: Object.fromEntries(release.workflows.flatMap((item) => item.graph ? [[item.workflowId, item.graph]] : [])),
754
+ script_documents: {}
755
+ })
756
+ });
757
+ const decision = await reserveAppRun({
758
+ userId,
759
+ instanceId: instance.id,
760
+ invocationId: jobId,
761
+ operationId: req.operation_id ?? "",
762
+ origin: "public",
763
+ estimatedUsd: this.estimateRunCost(req),
764
+ requireFiniteBudget: true
765
+ });
766
+ if (!decision.allowed) {
767
+ return this.refuseRun(req, jobId, ApiErrorCode.BUDGET_EXCEEDED, decision.reason);
768
+ }
769
+ req.app_run_id = decision.run.id;
770
+ req.instance_id = instance.id;
771
+ }
772
+ const run = req.app_run_id
773
+ ? await getAppRun(userId, req.app_run_id)
774
+ : null;
775
+ const instance = req.instance_id
776
+ ? await getAppInstance(userId, req.instance_id)
777
+ : null;
778
+ if (!run ||
779
+ !instance ||
780
+ run.instance_id !== instance.id ||
781
+ run.invocation_id !== jobId) {
782
+ return this.refuseRun(req, jobId, ApiErrorCode.NOT_FOUND, "App run not found");
783
+ }
784
+ if (run.status !== "running") {
785
+ return this.refuseRun(req, jobId, ApiErrorCode.ALREADY_EXISTS, "App run has already finished");
786
+ }
787
+ const operation = instance.snapshot.document.operations.find((item) => item.id === run.operation_id);
788
+ if (!operation ||
789
+ operationTarget(operation).kind !== "workflow" ||
790
+ (req.operation_id && req.operation_id !== run.operation_id)) {
791
+ return this.refuseRun(req, jobId, ApiErrorCode.INVALID_INPUT, "Operation does not match this run");
792
+ }
793
+ const target = operationTarget(operation);
794
+ if (target.kind !== "workflow" ||
795
+ !target.workflowId ||
796
+ (req.workflow_id && req.workflow_id !== target.workflowId)) {
797
+ return this.refuseRun(req, jobId, ApiErrorCode.INVALID_INPUT, "Workflow does not match this run");
798
+ }
799
+ if (run.origin !== "public") {
800
+ const frozen = run.snapshot?.workflow_graphs[target.workflowId];
801
+ if (!frozen) {
802
+ return this.refuseRun(req, jobId, ApiErrorCode.INVALID_INPUT, "Run has no frozen workflow");
803
+ }
804
+ const overlays = new Map();
805
+ const inputs = instance.variables["__app_inputs"];
806
+ for (const [key, value] of Object.entries(isRecord(inputs) ? inputs : {})) {
807
+ const binding = parseInputStateKey(key);
808
+ if (!binding?.property || binding.operationId !== run.operation_id) {
809
+ continue;
810
+ }
811
+ const properties = overlays.get(binding.nodeId) ?? {};
812
+ properties[binding.property] = value;
813
+ overlays.set(binding.nodeId, properties);
814
+ }
815
+ req.graph = {
816
+ ...frozen,
817
+ nodes: frozen.nodes.map((node) => {
818
+ const overlay = overlays.get(node.id);
819
+ if (!overlay) {
820
+ return node;
821
+ }
822
+ const properties = isRecord(node.properties)
823
+ ? node.properties
824
+ : isRecord(node.data)
825
+ ? node.data
826
+ : {};
827
+ return { ...node, properties: { ...properties, ...overlay } };
828
+ })
829
+ };
830
+ await updateAppRunEstimate(userId, run.id, this.estimateRunCost(req));
831
+ }
832
+ if (!(await claimAppRun(userId, run.id, getInstanceId()))) {
833
+ return this.refuseRun(req, jobId, ApiErrorCode.ALREADY_EXISTS, "App run execution already started");
834
+ }
835
+ claimedRunId = run.id;
836
+ await setAppRunInputs(userId, run.id, req.params ?? {});
837
+ req.app_run_id = run.id;
838
+ req.instance_id = instance.id;
839
+ req.user_id = userId;
840
+ req.workflow_id = target.workflowId;
841
+ req.application_id = run.application_id;
842
+ req.application_version = run.version;
843
+ req.operation_id = run.operation_id;
844
+ return true;
845
+ }
846
+ catch (error) {
847
+ if (claimedRunId) {
848
+ try {
849
+ await settleAppRun(userId, claimedRunId, {
850
+ status: "failed",
851
+ actualUsd: 0,
852
+ knownLlmUsd: 0,
853
+ error: error instanceof Error
854
+ ? error.message
855
+ : "App run admission failed"
856
+ });
857
+ }
858
+ catch (settlementError) {
859
+ if (!(settlementError instanceof AppRunError) ||
860
+ settlementError.code !== "not_found") {
861
+ this.session.logError("app run admission settlement failed", settlementError);
862
+ }
863
+ }
864
+ }
865
+ this.session.logError("app run admission failed", error);
866
+ const code = error instanceof AppRunError && error.code === "budget_exceeded"
867
+ ? ApiErrorCode.BUDGET_EXCEEDED
868
+ : ApiErrorCode.INVALID_INPUT;
869
+ return this.refuseRun(req, jobId, code, error instanceof Error ? error.message : "App run admission failed");
870
+ }
871
+ }
715
872
  /**
716
873
  * Gate a run on the user's credit balance — but only the part of the run
717
874
  * that spends through NodeTool's managed provider. A graph with no
@@ -808,8 +965,15 @@ export class JobExecutionManager {
808
965
  req._accepted_at_ms ??= performance.now();
809
966
  if (!(await this.admitApplicationRun(req)))
810
967
  return;
811
- if (!(await this.admitCreditRun(req)))
968
+ if (!(await this.admitCreditRun(req))) {
969
+ if (req.app_run_id) {
970
+ await settleAppRun(this.session.requireUserId(), req.app_run_id, {
971
+ status: "failed",
972
+ error: "Run refused by spending limit"
973
+ });
974
+ }
812
975
  return;
976
+ }
813
977
  const max = await this.deps.getMaxConcurrentJobs();
814
978
  const perWorkflowMax = await this.perWorkflowLimitFor(req);
815
979
  // Queue the run when over the global cap, or when this workflow already has
@@ -841,7 +1005,7 @@ export class JobExecutionManager {
841
1005
  await Job.create({
842
1006
  id: jobId,
843
1007
  workflow_id: req.workflow_id ?? "",
844
- user_id: resolveRunJobUserId(req.user_id, this.session.requireUserId()),
1008
+ user_id: this.session.requireUserId(),
845
1009
  status: "queued",
846
1010
  name: req.job_name ?? "",
847
1011
  params: req.params ?? {},
@@ -949,6 +1113,13 @@ export class JobExecutionManager {
949
1113
  try {
950
1114
  await this.startJobInner(req, releaseSlot);
951
1115
  }
1116
+ catch (error) {
1117
+ if (req.app_run_id) {
1118
+ await this.emitBeforeRunFailure(req.job_id ?? "", req.workflow_id ?? null, error, true);
1119
+ return;
1120
+ }
1121
+ throw error;
1122
+ }
952
1123
  finally {
953
1124
  // Safety net: if startJobInner returned/threw without registering, the
954
1125
  // slot is freed so it doesn't leak and permanently shrink the cap.
@@ -956,7 +1127,10 @@ export class JobExecutionManager {
956
1127
  }
957
1128
  }
958
1129
  async startJobInner(req, releaseSlot) {
959
- const userId = resolveRunJobUserId(req.user_id, this.session.requireUserId());
1130
+ // The connection's authenticated user. The request's `user_id` is
1131
+ // client-written, so it cannot choose whose secrets, workflows, and
1132
+ // assets the run uses.
1133
+ const userId = this.session.requireUserId();
960
1134
  const workflowId = req.workflow_id ?? null;
961
1135
  const jobId = req.job_id ?? randomUUID();
962
1136
  let projectId = req.project_id ?? null;
@@ -1011,11 +1185,23 @@ export class JobExecutionManager {
1011
1185
  const workspace = this.session.workspaceResolver
1012
1186
  ? await this.session.workspaceResolver(workflowId ?? null, userId)
1013
1187
  : null;
1188
+ const appRun = req.app_run_id
1189
+ ? await getAppRun(userId, req.app_run_id)
1190
+ : null;
1014
1191
  const context = createRuntimeContext({
1015
1192
  jobId,
1016
1193
  workflowId,
1017
1194
  projectId,
1018
1195
  userId,
1196
+ ...(appRun && {
1197
+ appRunContext: {
1198
+ userId,
1199
+ appRunId: appRun.id,
1200
+ instanceId: appRun.instance_id,
1201
+ traceId: appRun.trace_id,
1202
+ origin: appRun.origin
1203
+ }
1204
+ }),
1019
1205
  workspace,
1020
1206
  assetOutputMode: this.session.mode === "text" ? "data_uri" : "temp_url",
1021
1207
  persistOutputAssets: executionOptions.assetPersistence === "auto"
@@ -1042,8 +1228,26 @@ export class JobExecutionManager {
1042
1228
  if (executionOptions.persistence === "job") {
1043
1229
  try {
1044
1230
  const existing = await Job.get(jobId);
1231
+ if (existing && existing.user_id !== userId) {
1232
+ // The client chose this job_id. Another user's row under it must
1233
+ // not be flipped to running or written with this run's results.
1234
+ releaseSlot();
1235
+ this.drainQueue();
1236
+ this.session.sendDetached({
1237
+ type: "job_update",
1238
+ status: "failed",
1239
+ job_id: jobId,
1240
+ workflow_id: workflowId,
1241
+ error: "Job id already in use",
1242
+ error_code: ApiErrorCode.ALREADY_EXISTS
1243
+ });
1244
+ return;
1245
+ }
1045
1246
  if (existing) {
1046
1247
  if (existing.status === "cancelled") {
1248
+ if (appRun) {
1249
+ await settleAppRun(userId, appRun.id, { status: "cancelled" });
1250
+ }
1047
1251
  log.info("Skipping start of cancelled job", { jobId });
1048
1252
  // Nothing was registered in activeJobs yet — free the reserved
1049
1253
  // slot and promote any queued run, matching every other slot
@@ -1079,7 +1283,10 @@ export class JobExecutionManager {
1079
1283
  name: req.job_name ?? "",
1080
1284
  started_at: new Date().toISOString(),
1081
1285
  params: req.params ?? {},
1082
- graph,
1286
+ // The graph as submitted, not the hydrated one: hydration drops
1287
+ // editor-only nodes (groups, comments), and "Open as it was when
1288
+ // made" reopens this graph in the editor.
1289
+ graph: rawGraph,
1083
1290
  project_id: projectId ?? "default",
1084
1291
  runner_instance: instanceId
1085
1292
  });
@@ -1134,11 +1341,27 @@ export class JobExecutionManager {
1134
1341
  // uses: a bare throw reaches handleCommand as a generic `invalid_command`
1135
1342
  // the UI never associates with the job, so the run appears to spin
1136
1343
  // forever instead of failing with the reason.
1344
+ let finishAppTrace;
1345
+ try {
1346
+ await ensureRunTraceTelemetry();
1347
+ const incomingParent = req.traceparent ? trace.getSpanContext(propagation.extract(ROOT_CONTEXT, { traceparent: req.traceparent })) : undefined;
1348
+ const acceptedParent = incomingParent && isSpanContextValid(incomingParent) && !this.session.appSession && appRun && incomingParent.traceId === appRun.trace_id && await getRegisteredRunTrace(userId, incomingParent.traceId, appRun.id) ? incomingParent : undefined;
1349
+ finishAppTrace = appRun ? await openAppRunTrace(context, appRun, acceptedParent) : undefined;
1350
+ if (executionOptions.persistence === "job") {
1351
+ await registerWorkflowRunTrace(context, { jobId, workflowId: workflowId ?? null, inlineGraph: Boolean(req.graph), origin: this.session.appSession ? "public" : "ui" });
1352
+ }
1353
+ }
1354
+ catch (error) {
1355
+ await finishAppTrace?.("failed", error instanceof Error ? error.message : String(error));
1356
+ await this.emitBeforeRunFailure(jobId, workflowId, error, executionOptions.persistence === "job");
1357
+ return;
1358
+ }
1137
1359
  let session;
1138
1360
  try {
1139
1361
  session = await ExecutionSession.create(sessionOptions);
1140
1362
  }
1141
1363
  catch (err) {
1364
+ await finishAppTrace?.("failed", err instanceof Error ? err.message : String(err));
1142
1365
  if (!isExecutionPreflightError(err))
1143
1366
  throw err;
1144
1367
  await this.emitBeforeRunFailure(jobId, workflowId, err, executionOptions.persistence === "job");
@@ -1163,18 +1386,14 @@ export class JobExecutionManager {
1163
1386
  persistenceMs,
1164
1387
  kernelStartedAt: performance.now()
1165
1388
  },
1166
- applicationId: req.application_id ?? null
1389
+ applicationId: req.application_id ?? null,
1390
+ ...(appRun && { appRunFold: createAppRunFold(appRun) }),
1391
+ ...(finishAppTrace && { finishAppTrace })
1167
1392
  };
1168
1393
  // Decouple the run from this socket: from here on every frame carrying
1169
1394
  // this job_id is stamped with `job_seq` and buffered, so a client that
1170
1395
  // drops mid-run can `reconnect_job` from a fresh connection and replay
1171
1396
  // the tail — including the terminal job_update.
1172
- //
1173
- // Keyed on the connection's identity, not `userId`: every lookup
1174
- // (`reconnect_job`, `cancel_job`, the slot counts) reads
1175
- // `this.session.requireUserId()`, and a run opened under an explicit differing
1176
- // `req.user_id` would be unreachable — no replay, and a cancel that
1177
- // reports the job as not found.
1178
1397
  const runSession = jobRunRegistry.open(this.session.requireUserId(), jobId, workflowId, {
1179
1398
  cancel: () => session.cancel(),
1180
1399
  pushInput: (input, value, handle) => session.pushInput(input, value, handle),
@@ -1248,6 +1467,10 @@ export class JobExecutionManager {
1248
1467
  // the client UI spinning, and the app ledger holding the estimate.
1249
1468
  const message = error instanceof Error ? error.message : String(error);
1250
1469
  this.session.logError("job message streaming failed", error);
1470
+ // The run is reported failed below, so stop the kernel too: otherwise
1471
+ // it keeps executing (and spending) with nobody reading its output,
1472
+ // and cancel_job can no longer reach it once the session finishes.
1473
+ active.session?.cancel();
1251
1474
  active.finished = true;
1252
1475
  active.status = "failed";
1253
1476
  active.error = message;
@@ -1304,6 +1527,16 @@ export class JobExecutionManager {
1304
1527
  }
1305
1528
  else if (active.status === "failed") {
1306
1529
  job.markFailed(active.error ?? "Unknown error");
1530
+ // The run's error is a string by now. A stack built here would
1531
+ // point at this method, not at the failure, so none is sent.
1532
+ captureError(active.error ?? "Unknown error", {
1533
+ source: "job",
1534
+ userId: job.user_id,
1535
+ context: {
1536
+ job_id: active.jobId,
1537
+ workflow_id: active.workflowId ?? ""
1538
+ }
1539
+ });
1307
1540
  }
1308
1541
  else if (active.status === "cancelled") {
1309
1542
  job.markCancelled();
@@ -1327,6 +1560,38 @@ export class JobExecutionManager {
1327
1560
  * the estimate standing rather than handing the spend back. Never throws.
1328
1561
  */
1329
1562
  async settleApplicationInvocation(active) {
1563
+ await active.finishAppTrace?.(active.status === "failed" ? "failed" : active.status === "cancelled" ? "cancelled" : "completed", active.error, this.runMeasuredCost(active));
1564
+ const identity = active.context.appRunContext;
1565
+ if (identity) {
1566
+ try {
1567
+ const settlement = {
1568
+ status: active.status === "failed"
1569
+ ? "failed"
1570
+ : active.status === "cancelled"
1571
+ ? "cancelled"
1572
+ : "completed",
1573
+ error: active.context.runTraceContext?.policy.contentSuppressed && active.error ? "Execution failed" : active.error ?? null,
1574
+ actualUsd: this.runMeasuredCost(active),
1575
+ outputs: active.appRunFold?.outputs() ?? {},
1576
+ documents: active.context.getAppRunDocuments(),
1577
+ contentSuppressed: active.context.runTraceContext?.policy.contentSuppressed,
1578
+ secretValues: [...active.context.getResolvedSecretValues()]
1579
+ };
1580
+ const llmCost = active.context.getAppRunLlmCost();
1581
+ if (llmCost !== null) {
1582
+ settlement.knownLlmUsd = llmCost;
1583
+ }
1584
+ await settleAppRun(identity.userId, identity.appRunId, settlement);
1585
+ await reconcileAppRunCost(identity.userId, identity.appRunId);
1586
+ return;
1587
+ }
1588
+ catch (error) {
1589
+ if (!(error instanceof AppRunError) || error.code !== "not_found") {
1590
+ this.session.logError("app run settlement failed", error);
1591
+ }
1592
+ }
1593
+ return;
1594
+ }
1330
1595
  if (!active.applicationId)
1331
1596
  return;
1332
1597
  try {
@@ -1587,18 +1852,25 @@ export class JobExecutionManager {
1587
1852
  continue;
1588
1853
  }
1589
1854
  const status = outbound.type === "job_update" ? String(outbound.status ?? "") : "";
1590
- const suppressProvisionalCompletion = active.requireTerminalResult &&
1591
- status === "completed" &&
1592
- outbound.result === undefined;
1855
+ const suppressProvisionalCompletion = (Boolean(active.context.appRunContext) &&
1856
+ TERMINAL_JOB_STATUSES.includes(status)) ||
1857
+ (active.requireTerminalResult &&
1858
+ status === "completed" &&
1859
+ outbound.result === undefined);
1593
1860
  if (!suppressProvisionalCompletion) {
1594
1861
  if (outbound.type === "job_update") {
1595
1862
  if (status === "running") {
1596
1863
  runningSeen = true;
1597
1864
  }
1598
1865
  else if (TERMINAL_JOB_STATUSES.includes(status)) {
1866
+ if (active.context.appRunContext) {
1867
+ await executionSettled;
1868
+ await this.settleApplicationInvocation(active);
1869
+ }
1599
1870
  await ensureRunningFrame();
1600
1871
  }
1601
1872
  }
1873
+ active.appRunFold?.fold(outbound);
1602
1874
  await this.session.send(outbound);
1603
1875
  }
1604
1876
  if (outbound.type === "job_update" && !suppressProvisionalCompletion) {
@@ -1620,12 +1892,30 @@ export class JobExecutionManager {
1620
1892
  if (Object.keys(finalOutputs).length > 0) {
1621
1893
  finalOutputs = await this.normalizeFinalOutputs(active, finalOutputs);
1622
1894
  }
1895
+ if (active.appRunFold) {
1896
+ for (const [key, values] of Object.entries(finalOutputs)) {
1897
+ const nodeId = this.resolveOutputNodeForKey(active, key)?.id ?? key;
1898
+ for (const [index, value] of values.entries()) {
1899
+ active.appRunFold.fold({
1900
+ type: "output_update",
1901
+ job_id: active.jobId,
1902
+ node_id: nodeId,
1903
+ value,
1904
+ disposition: index === 0 ? "replace" : "append",
1905
+ done: true
1906
+ });
1907
+ }
1908
+ }
1909
+ }
1623
1910
  if (active.executionOptions.eventDetail !== "terminal" &&
1624
1911
  !outputUpdateSeen &&
1625
1912
  Object.keys(finalOutputs).length > 0) {
1626
1913
  await this.sendOutputUpdates(active, finalOutputs);
1627
1914
  }
1628
1915
  const relayCompletedAt = performance.now();
1916
+ if (active.context.appRunContext) {
1917
+ await this.settleApplicationInvocation(active);
1918
+ }
1629
1919
  if (!terminalSeen ||
1630
1920
  (!terminalWithResultSeen && Object.keys(finalOutputs).length > 0)) {
1631
1921
  await ensureRunningFrame();
@@ -1706,7 +1996,7 @@ export class JobExecutionManager {
1706
1996
  // indistinguishable from a missing one — it must be neither reported
1707
1997
  // nor settled below.
1708
1998
  const row = (await Job.get(jobId));
1709
- const job = row && row.user_id === (this.session.requireUserId()) ? row : null;
1999
+ const job = row && row.user_id === this.session.requireUserId() ? row : null;
1710
2000
  const settled = job != null &&
1711
2001
  (job.status === "completed" ||
1712
2002
  job.status === "failed" ||
@@ -1781,17 +2071,18 @@ export class JobExecutionManager {
1781
2071
  // and tell the client it's cancelled before it ever starts.
1782
2072
  const queued = this.jobQueue.remove(jobId);
1783
2073
  if (queued) {
2074
+ if (queued.app_run_id) {
2075
+ await settleAppRun(this.session.requireUserId(), queued.app_run_id, {
2076
+ status: "cancelled"
2077
+ });
2078
+ }
1784
2079
  releaseSpend(this.session.requireUserId(), jobId);
1785
2080
  const cancelledWorkflowId = queued.workflow_id ?? workflowId ?? null;
1786
2081
  // Mark the persisted queued row cancelled so it leaves the queue in
1787
2082
  // jobs.list too (not just the in-memory queue).
1788
2083
  if (resolveRunJobExecutionOptions(queued.execution_options, queued.require_terminal_result === true).persistence === "job") {
1789
2084
  try {
1790
- const job = await Job.get(jobId);
1791
- if (job) {
1792
- job.markCancelled();
1793
- await job.save();
1794
- }
2085
+ await Job.markCancelledIfActive(jobId, this.session.requireUserId());
1795
2086
  }
1796
2087
  catch (err) {
1797
2088
  this.session.logError("cancel persistence failed", err);
@@ -1821,11 +2112,7 @@ export class JobExecutionManager {
1821
2112
  if (registered && registered.status === "running") {
1822
2113
  registered.cancel();
1823
2114
  try {
1824
- const job = await Job.get(jobId);
1825
- if (job && job.status !== "cancelled") {
1826
- job.markCancelled();
1827
- await job.save();
1828
- }
2115
+ await Job.markCancelledIfActive(jobId, this.session.requireUserId());
1829
2116
  }
1830
2117
  catch (err) {
1831
2118
  this.session.logError("cancel persistence failed", err);
@@ -1875,11 +2162,7 @@ export class JobExecutionManager {
1875
2162
  if ((active.executionOptions?.persistence ??
1876
2163
  DEFAULT_RUN_JOB_EXECUTION_OPTIONS.persistence) === "job") {
1877
2164
  try {
1878
- const job = await Job.get(jobId);
1879
- if (job && job.status !== "cancelled") {
1880
- job.markCancelled();
1881
- await job.save();
1882
- }
2165
+ await Job.markCancelledIfActive(jobId, this.session.requireUserId());
1883
2166
  }
1884
2167
  catch (err) {
1885
2168
  this.session.logError("cancel persistence failed", err);
@@ -2062,11 +2345,13 @@ export class JobExecutionManager {
2062
2345
  if (!queuedId)
2063
2346
  continue;
2064
2347
  try {
2065
- const job = await Job.get(queuedId);
2066
- if (job) {
2067
- job.markCancelled();
2068
- await job.save();
2348
+ if (queued.app_run_id) {
2349
+ await settleAppRun(this.session.requireUserId(), queued.app_run_id, {
2350
+ status: "cancelled"
2351
+ });
2069
2352
  }
2353
+ releaseSpend(this.session.requireUserId(), queuedId);
2354
+ await Job.markCancelledIfActive(queuedId, this.session.requireUserId());
2070
2355
  }
2071
2356
  catch (err) {
2072
2357
  this.session.logError("disconnect queue cancellation failed", err);
@@ -2074,11 +2359,13 @@ export class JobExecutionManager {
2074
2359
  }
2075
2360
  for (const dequeuedId of this.dequeuedJobs) {
2076
2361
  try {
2077
- const job = await Job.get(dequeuedId);
2078
- if (job) {
2079
- job.markCancelled();
2080
- await job.save();
2362
+ const run = await findAppRunByInvocation(this.session.requireUserId(), dequeuedId);
2363
+ if (run) {
2364
+ await settleAppRun(this.session.requireUserId(), run.id, {
2365
+ status: "cancelled"
2366
+ });
2081
2367
  }
2368
+ await Job.markCancelledIfActive(dequeuedId, this.session.requireUserId());
2082
2369
  }
2083
2370
  catch (err) {
2084
2371
  this.session.logError("disconnect dequeued-job cancellation failed", err);