@nodetool-ai/agents 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 (477) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/analysis/audio-dsp.d.ts +3 -2
  3. package/dist/analysis/audio-dsp.d.ts.map +1 -1
  4. package/dist/analysis/audio-dsp.js +11 -8
  5. package/dist/analysis/audio-dsp.js.map +1 -1
  6. package/dist/analysis/media-decode.d.ts +13 -0
  7. package/dist/analysis/media-decode.d.ts.map +1 -1
  8. package/dist/analysis/media-decode.js +33 -6
  9. package/dist/analysis/media-decode.js.map +1 -1
  10. package/dist/apify/assets.d.ts.map +1 -1
  11. package/dist/apify/assets.js +4 -0
  12. package/dist/apify/assets.js.map +1 -1
  13. package/dist/author-graph.d.ts +2 -3
  14. package/dist/author-graph.d.ts.map +1 -1
  15. package/dist/author-graph.js +3 -5
  16. package/dist/author-graph.js.map +1 -1
  17. package/dist/browser-gate.d.ts +2 -2
  18. package/dist/browser-gate.js +2 -2
  19. package/dist/capabilities/GamePublishRequest.d.ts +14 -0
  20. package/dist/capabilities/GamePublishRequest.d.ts.map +1 -0
  21. package/dist/capabilities/GamePublishRequest.js +2 -0
  22. package/dist/capabilities/GamePublishRequest.js.map +1 -0
  23. package/dist/capabilities/adapters.d.ts +4 -13
  24. package/dist/capabilities/adapters.d.ts.map +1 -1
  25. package/dist/capabilities/adapters.js +9 -14
  26. package/dist/capabilities/adapters.js.map +1 -1
  27. package/dist/capabilities/agent-activity.d.ts +27 -0
  28. package/dist/capabilities/agent-activity.d.ts.map +1 -0
  29. package/dist/capabilities/agent-activity.js +103 -0
  30. package/dist/capabilities/agent-activity.js.map +1 -0
  31. package/dist/capabilities/agentic-storyboard-finish.d.ts +67 -0
  32. package/dist/capabilities/agentic-storyboard-finish.d.ts.map +1 -0
  33. package/dist/capabilities/agentic-storyboard-finish.js +1321 -0
  34. package/dist/capabilities/agentic-storyboard-finish.js.map +1 -0
  35. package/dist/capabilities/agents.d.ts +5 -2
  36. package/dist/capabilities/agents.d.ts.map +1 -1
  37. package/dist/capabilities/agents.js +14 -4
  38. package/dist/capabilities/agents.js.map +1 -1
  39. package/dist/capabilities/agents.specs.d.ts +3 -0
  40. package/dist/capabilities/agents.specs.d.ts.map +1 -1
  41. package/dist/capabilities/agents.specs.js +71 -1
  42. package/dist/capabilities/agents.specs.js.map +1 -1
  43. package/dist/capabilities/analysis.d.ts.map +1 -1
  44. package/dist/capabilities/analysis.js +33 -22
  45. package/dist/capabilities/analysis.js.map +1 -1
  46. package/dist/capabilities/analysis.specs.js +2 -2
  47. package/dist/capabilities/analysis.specs.js.map +1 -1
  48. package/dist/capabilities/apps.d.ts.map +1 -1
  49. package/dist/capabilities/apps.js +5 -3
  50. package/dist/capabilities/apps.js.map +1 -1
  51. package/dist/capabilities/args.d.ts +2 -5
  52. package/dist/capabilities/args.d.ts.map +1 -1
  53. package/dist/capabilities/args.js +2 -5
  54. package/dist/capabilities/args.js.map +1 -1
  55. package/dist/capabilities/assets.d.ts.map +1 -1
  56. package/dist/capabilities/assets.js +40 -10
  57. package/dist/capabilities/assets.js.map +1 -1
  58. package/dist/capabilities/browser.d.ts +1 -1
  59. package/dist/capabilities/browser.js +1 -1
  60. package/dist/capabilities/browser.specs.d.ts +1 -1
  61. package/dist/capabilities/browser.specs.js +1 -1
  62. package/dist/capabilities/code.d.ts +5 -0
  63. package/dist/capabilities/code.d.ts.map +1 -1
  64. package/dist/capabilities/code.js +128 -89
  65. package/dist/capabilities/code.js.map +1 -1
  66. package/dist/capabilities/collections.d.ts +4 -6
  67. package/dist/capabilities/collections.d.ts.map +1 -1
  68. package/dist/capabilities/collections.js +16 -11
  69. package/dist/capabilities/collections.js.map +1 -1
  70. package/dist/capabilities/derive-shot.d.ts +45 -0
  71. package/dist/capabilities/derive-shot.d.ts.map +1 -0
  72. package/dist/capabilities/derive-shot.js +82 -0
  73. package/dist/capabilities/derive-shot.js.map +1 -0
  74. package/dist/capabilities/documents.d.ts +2 -1
  75. package/dist/capabilities/documents.d.ts.map +1 -1
  76. package/dist/capabilities/documents.js +12 -6
  77. package/dist/capabilities/documents.js.map +1 -1
  78. package/dist/capabilities/email.d.ts +2 -1
  79. package/dist/capabilities/email.d.ts.map +1 -1
  80. package/dist/capabilities/email.js +5 -3
  81. package/dist/capabilities/email.js.map +1 -1
  82. package/dist/capabilities/errors.d.ts +19 -0
  83. package/dist/capabilities/errors.d.ts.map +1 -0
  84. package/dist/capabilities/errors.js +109 -0
  85. package/dist/capabilities/errors.js.map +1 -0
  86. package/dist/capabilities/errors.specs.d.ts +11 -0
  87. package/dist/capabilities/errors.specs.d.ts.map +1 -0
  88. package/dist/capabilities/errors.specs.js +100 -0
  89. package/dist/capabilities/errors.specs.js.map +1 -0
  90. package/dist/capabilities/example-timelines.d.ts.map +1 -1
  91. package/dist/capabilities/example-timelines.js +52 -10
  92. package/dist/capabilities/example-timelines.js.map +1 -1
  93. package/dist/capabilities/example-timelines.specs.d.ts +1 -0
  94. package/dist/capabilities/example-timelines.specs.d.ts.map +1 -1
  95. package/dist/capabilities/example-timelines.specs.js +21 -3
  96. package/dist/capabilities/example-timelines.specs.js.map +1 -1
  97. package/dist/capabilities/finish-storyboard.d.ts +5 -0
  98. package/dist/capabilities/finish-storyboard.d.ts.map +1 -0
  99. package/dist/capabilities/finish-storyboard.js +278 -0
  100. package/dist/capabilities/finish-storyboard.js.map +1 -0
  101. package/dist/capabilities/game-asset-browser.d.ts +11 -0
  102. package/dist/capabilities/game-asset-browser.d.ts.map +1 -0
  103. package/dist/capabilities/game-asset-browser.js +152 -0
  104. package/dist/capabilities/game-asset-browser.js.map +1 -0
  105. package/dist/capabilities/game-asset-source.js +1 -1
  106. package/dist/capabilities/game-asset-source.js.map +1 -1
  107. package/dist/capabilities/game.d.ts +44 -2
  108. package/dist/capabilities/game.d.ts.map +1 -1
  109. package/dist/capabilities/game.js +408 -160
  110. package/dist/capabilities/game.js.map +1 -1
  111. package/dist/capabilities/game.specs.d.ts +4 -0
  112. package/dist/capabilities/game.specs.d.ts.map +1 -1
  113. package/dist/capabilities/game.specs.js +42 -13
  114. package/dist/capabilities/game.specs.js.map +1 -1
  115. package/dist/capabilities/game3d.d.ts +17 -0
  116. package/dist/capabilities/game3d.d.ts.map +1 -0
  117. package/dist/capabilities/game3d.js +434 -0
  118. package/dist/capabilities/game3d.js.map +1 -0
  119. package/dist/capabilities/gate-from-context.d.ts +1 -1
  120. package/dist/capabilities/gate-from-context.js +1 -1
  121. package/dist/capabilities/generations.d.ts +2 -0
  122. package/dist/capabilities/generations.d.ts.map +1 -1
  123. package/dist/capabilities/generations.js +14 -23
  124. package/dist/capabilities/generations.js.map +1 -1
  125. package/dist/capabilities/index.d.ts +2 -2
  126. package/dist/capabilities/index.d.ts.map +1 -1
  127. package/dist/capabilities/index.js +2 -2
  128. package/dist/capabilities/index.js.map +1 -1
  129. package/dist/capabilities/invoke.d.ts +14 -25
  130. package/dist/capabilities/invoke.d.ts.map +1 -1
  131. package/dist/capabilities/invoke.js +72 -35
  132. package/dist/capabilities/invoke.js.map +1 -1
  133. package/dist/capabilities/jobs.d.ts.map +1 -1
  134. package/dist/capabilities/jobs.js +47 -3
  135. package/dist/capabilities/jobs.js.map +1 -1
  136. package/dist/capabilities/jobs.specs.d.ts.map +1 -1
  137. package/dist/capabilities/jobs.specs.js +3 -1
  138. package/dist/capabilities/jobs.specs.js.map +1 -1
  139. package/dist/capabilities/js-scripts.d.ts +19 -1
  140. package/dist/capabilities/js-scripts.d.ts.map +1 -1
  141. package/dist/capabilities/js-scripts.js +109 -2
  142. package/dist/capabilities/js-scripts.js.map +1 -1
  143. package/dist/capabilities/js-scripts.specs.d.ts +2 -0
  144. package/dist/capabilities/js-scripts.specs.d.ts.map +1 -1
  145. package/dist/capabilities/js-scripts.specs.js +50 -0
  146. package/dist/capabilities/js-scripts.specs.js.map +1 -1
  147. package/dist/capabilities/lazy-tool-core.d.ts +23 -0
  148. package/dist/capabilities/lazy-tool-core.d.ts.map +1 -0
  149. package/dist/capabilities/lazy-tool-core.js +56 -0
  150. package/dist/capabilities/lazy-tool-core.js.map +1 -0
  151. package/dist/capabilities/lazy-tool.d.ts +3 -23
  152. package/dist/capabilities/lazy-tool.d.ts.map +1 -1
  153. package/dist/capabilities/lazy-tool.js +6 -64
  154. package/dist/capabilities/lazy-tool.js.map +1 -1
  155. package/dist/capabilities/legacy-tools.d.ts +15 -0
  156. package/dist/capabilities/legacy-tools.d.ts.map +1 -0
  157. package/dist/capabilities/legacy-tools.js +98 -0
  158. package/dist/capabilities/legacy-tools.js.map +1 -0
  159. package/dist/capabilities/media.d.ts +0 -9
  160. package/dist/capabilities/media.d.ts.map +1 -1
  161. package/dist/capabilities/media.js +314 -261
  162. package/dist/capabilities/media.js.map +1 -1
  163. package/dist/capabilities/media.specs.d.ts.map +1 -1
  164. package/dist/capabilities/media.specs.js +17 -0
  165. package/dist/capabilities/media.specs.js.map +1 -1
  166. package/dist/capabilities/metadata.d.ts +62 -0
  167. package/dist/capabilities/metadata.d.ts.map +1 -0
  168. package/dist/capabilities/metadata.js +114 -0
  169. package/dist/capabilities/metadata.js.map +1 -0
  170. package/dist/capabilities/model3d.d.ts.map +1 -1
  171. package/dist/capabilities/model3d.js +4 -0
  172. package/dist/capabilities/model3d.js.map +1 -1
  173. package/dist/capabilities/models.d.ts +2 -2
  174. package/dist/capabilities/models.d.ts.map +1 -1
  175. package/dist/capabilities/models.js +5 -3
  176. package/dist/capabilities/models.js.map +1 -1
  177. package/dist/capabilities/registry.d.ts +6 -19
  178. package/dist/capabilities/registry.d.ts.map +1 -1
  179. package/dist/capabilities/registry.js +72 -113
  180. package/dist/capabilities/registry.js.map +1 -1
  181. package/dist/capabilities/run-agent.d.ts +19 -0
  182. package/dist/capabilities/run-agent.d.ts.map +1 -0
  183. package/dist/capabilities/run-agent.js +183 -0
  184. package/dist/capabilities/run-agent.js.map +1 -0
  185. package/dist/capabilities/runs.d.ts +9 -0
  186. package/dist/capabilities/runs.d.ts.map +1 -0
  187. package/dist/capabilities/runs.js +46 -0
  188. package/dist/capabilities/runs.js.map +1 -0
  189. package/dist/capabilities/runs.specs.d.ts +39 -0
  190. package/dist/capabilities/runs.specs.d.ts.map +1 -0
  191. package/dist/capabilities/runs.specs.js +52 -0
  192. package/dist/capabilities/runs.specs.js.map +1 -0
  193. package/dist/capabilities/scripts.d.ts.map +1 -1
  194. package/dist/capabilities/scripts.js +11 -5
  195. package/dist/capabilities/scripts.js.map +1 -1
  196. package/dist/capabilities/settings.d.ts.map +1 -1
  197. package/dist/capabilities/settings.js +4 -2
  198. package/dist/capabilities/settings.js.map +1 -1
  199. package/dist/capabilities/sketches.d.ts.map +1 -1
  200. package/dist/capabilities/sketches.js +4 -2
  201. package/dist/capabilities/sketches.js.map +1 -1
  202. package/dist/capabilities/skills.d.ts.map +1 -1
  203. package/dist/capabilities/skills.js +22 -2
  204. package/dist/capabilities/skills.js.map +1 -1
  205. package/dist/capabilities/storyboard-layout-check.d.ts +33 -0
  206. package/dist/capabilities/storyboard-layout-check.d.ts.map +1 -0
  207. package/dist/capabilities/storyboard-layout-check.js +229 -0
  208. package/dist/capabilities/storyboard-layout-check.js.map +1 -0
  209. package/dist/capabilities/storyboard-measured-sources.d.ts +10 -0
  210. package/dist/capabilities/storyboard-measured-sources.d.ts.map +1 -0
  211. package/dist/capabilities/storyboard-measured-sources.js +67 -0
  212. package/dist/capabilities/storyboard-measured-sources.js.map +1 -0
  213. package/dist/capabilities/storyboard-review-times.d.ts +4 -0
  214. package/dist/capabilities/storyboard-review-times.d.ts.map +1 -0
  215. package/dist/capabilities/storyboard-review-times.js +39 -0
  216. package/dist/capabilities/storyboard-review-times.js.map +1 -0
  217. package/dist/capabilities/storyboards.d.ts +12 -18
  218. package/dist/capabilities/storyboards.d.ts.map +1 -1
  219. package/dist/capabilities/storyboards.js +779 -96
  220. package/dist/capabilities/storyboards.js.map +1 -1
  221. package/dist/capabilities/storyboards.specs.d.ts +9 -0
  222. package/dist/capabilities/storyboards.specs.d.ts.map +1 -1
  223. package/dist/capabilities/storyboards.specs.js +173 -5
  224. package/dist/capabilities/storyboards.specs.js.map +1 -1
  225. package/dist/capabilities/threads.js +1 -1
  226. package/dist/capabilities/threads.js.map +1 -1
  227. package/dist/capabilities/timeline-bridge.d.ts +368 -0
  228. package/dist/capabilities/timeline-bridge.d.ts.map +1 -0
  229. package/dist/capabilities/timeline-bridge.js +1008 -0
  230. package/dist/capabilities/timeline-bridge.js.map +1 -0
  231. package/dist/capabilities/timeline-clip-frames.d.ts +17 -0
  232. package/dist/capabilities/timeline-clip-frames.d.ts.map +1 -0
  233. package/dist/capabilities/timeline-clip-frames.js +84 -0
  234. package/dist/capabilities/timeline-clip-frames.js.map +1 -0
  235. package/dist/capabilities/timeline-media-edit.d.ts +8 -0
  236. package/dist/capabilities/timeline-media-edit.d.ts.map +1 -0
  237. package/dist/capabilities/timeline-media-edit.js +94 -0
  238. package/dist/capabilities/timeline-media-edit.js.map +1 -0
  239. package/dist/capabilities/timeline-native-media.d.ts.map +1 -1
  240. package/dist/capabilities/timeline-native-media.js +40 -0
  241. package/dist/capabilities/timeline-native-media.js.map +1 -1
  242. package/dist/capabilities/timeline-operations.d.ts +52 -0
  243. package/dist/capabilities/timeline-operations.d.ts.map +1 -0
  244. package/dist/capabilities/timeline-operations.js +413 -0
  245. package/dist/capabilities/timeline-operations.js.map +1 -0
  246. package/dist/capabilities/timelines.d.ts +28 -3
  247. package/dist/capabilities/timelines.d.ts.map +1 -1
  248. package/dist/capabilities/timelines.js +410 -294
  249. package/dist/capabilities/timelines.js.map +1 -1
  250. package/dist/capabilities/timelines.specs.d.ts +8 -0
  251. package/dist/capabilities/timelines.specs.d.ts.map +1 -1
  252. package/dist/capabilities/timelines.specs.js +178 -9
  253. package/dist/capabilities/timelines.specs.js.map +1 -1
  254. package/dist/capabilities/types.d.ts +3 -1
  255. package/dist/capabilities/types.d.ts.map +1 -1
  256. package/dist/capabilities/types.js.map +1 -1
  257. package/dist/capabilities/ui.d.ts.map +1 -1
  258. package/dist/capabilities/ui.js +24 -2
  259. package/dist/capabilities/ui.js.map +1 -1
  260. package/dist/capabilities/web.d.ts.map +1 -1
  261. package/dist/capabilities/web.js +4 -0
  262. package/dist/capabilities/web.js.map +1 -1
  263. package/dist/capabilities/workflows.d.ts +3 -1
  264. package/dist/capabilities/workflows.d.ts.map +1 -1
  265. package/dist/capabilities/workflows.js +244 -39
  266. package/dist/capabilities/workflows.js.map +1 -1
  267. package/dist/capabilities/workflows.specs.d.ts +2 -0
  268. package/dist/capabilities/workflows.specs.d.ts.map +1 -1
  269. package/dist/capabilities/workflows.specs.js +72 -2
  270. package/dist/capabilities/workflows.specs.js.map +1 -1
  271. package/dist/codeact/action-diagnostics.d.ts.map +1 -1
  272. package/dist/codeact/action-diagnostics.js +51 -1
  273. package/dist/codeact/action-diagnostics.js.map +1 -1
  274. package/dist/codeact/codeact-executor.d.ts.map +1 -1
  275. package/dist/codeact/codeact-executor.js +16 -8
  276. package/dist/codeact/codeact-executor.js.map +1 -1
  277. package/dist/codeact/compact-ids.d.ts.map +1 -1
  278. package/dist/codeact/compact-ids.js +5 -1
  279. package/dist/codeact/compact-ids.js.map +1 -1
  280. package/dist/codeact/graph-model.d.ts +1 -1
  281. package/dist/codeact/graph-model.d.ts.map +1 -1
  282. package/dist/codeact/graph-model.js +2 -3
  283. package/dist/codeact/graph-model.js.map +1 -1
  284. package/dist/codeact/nodetool-api.d.ts +1 -1
  285. package/dist/codeact/nodetool-api.d.ts.map +1 -1
  286. package/dist/codeact/nodetool-api.js +202 -284
  287. package/dist/codeact/nodetool-api.js.map +1 -1
  288. package/dist/codeact/sandbox-packages.d.ts +0 -7
  289. package/dist/codeact/sandbox-packages.d.ts.map +1 -1
  290. package/dist/codeact/sandbox-packages.js +1 -10
  291. package/dist/codeact/sandbox-packages.js.map +1 -1
  292. package/dist/codeact/tool-api.d.ts +6 -3
  293. package/dist/codeact/tool-api.d.ts.map +1 -1
  294. package/dist/codeact/tool-api.js +22 -15
  295. package/dist/codeact/tool-api.js.map +1 -1
  296. package/dist/evals/codeact-api-cases.d.ts.map +1 -1
  297. package/dist/evals/codeact-api-cases.js +2 -0
  298. package/dist/evals/codeact-api-cases.js.map +1 -1
  299. package/dist/evals/codeact-api-runs.d.ts +3 -0
  300. package/dist/evals/codeact-api-runs.d.ts.map +1 -0
  301. package/dist/evals/codeact-api-runs.js +33 -0
  302. package/dist/evals/codeact-api-runs.js.map +1 -0
  303. package/dist/evals/surfaces/game.d.ts +8 -2
  304. package/dist/evals/surfaces/game.d.ts.map +1 -1
  305. package/dist/evals/surfaces/game.js +460 -2
  306. package/dist/evals/surfaces/game.js.map +1 -1
  307. package/dist/evals/surfaces/sketch.d.ts +2 -0
  308. package/dist/evals/surfaces/sketch.d.ts.map +1 -1
  309. package/dist/evals/surfaces/sketch.js +11 -3
  310. package/dist/evals/surfaces/sketch.js.map +1 -1
  311. package/dist/evals/surfaces/timeline.d.ts +4 -357
  312. package/dist/evals/surfaces/timeline.d.ts.map +1 -1
  313. package/dist/evals/surfaces/timeline.js +9 -2621
  314. package/dist/evals/surfaces/timeline.js.map +1 -1
  315. package/dist/evals/tool-loop-bridge.d.ts +4 -0
  316. package/dist/evals/tool-loop-bridge.d.ts.map +1 -1
  317. package/dist/evals/tool-loop-bridge.js.map +1 -1
  318. package/dist/evals/tool-loop-eval.d.ts +2 -0
  319. package/dist/evals/tool-loop-eval.d.ts.map +1 -1
  320. package/dist/evals/tool-loop-eval.js +6 -1
  321. package/dist/evals/tool-loop-eval.js.map +1 -1
  322. package/dist/evals/tool-loop-permission.d.ts +1 -15
  323. package/dist/evals/tool-loop-permission.d.ts.map +1 -1
  324. package/dist/evals/tool-loop-permission.js +23 -41
  325. package/dist/evals/tool-loop-permission.js.map +1 -1
  326. package/dist/game-authoring.d.ts +9573 -0
  327. package/dist/game-authoring.d.ts.map +1 -0
  328. package/dist/game-authoring.js +146 -0
  329. package/dist/game-authoring.js.map +1 -0
  330. package/dist/game-build.d.ts +3 -0
  331. package/dist/game-build.d.ts.map +1 -0
  332. package/dist/game-build.js +3 -0
  333. package/dist/game-build.js.map +1 -0
  334. package/dist/game-code-bake.d.ts +26 -0
  335. package/dist/game-code-bake.d.ts.map +1 -0
  336. package/dist/game-code-bake.js +98 -0
  337. package/dist/game-code-bake.js.map +1 -0
  338. package/dist/game-examples.d.ts +2227 -18
  339. package/dist/game-examples.d.ts.map +1 -1
  340. package/dist/game-examples.js +5 -4
  341. package/dist/game-examples.js.map +1 -1
  342. package/dist/generation-cancel.d.ts +31 -0
  343. package/dist/generation-cancel.d.ts.map +1 -0
  344. package/dist/generation-cancel.js +28 -0
  345. package/dist/generation-cancel.js.map +1 -0
  346. package/dist/host-access-gate.d.ts +29 -0
  347. package/dist/host-access-gate.d.ts.map +1 -0
  348. package/dist/host-access-gate.js +39 -0
  349. package/dist/host-access-gate.js.map +1 -0
  350. package/dist/host-modules/dispatcher.d.ts +7 -1
  351. package/dist/host-modules/dispatcher.d.ts.map +1 -1
  352. package/dist/host-modules/dispatcher.js +13 -2
  353. package/dist/host-modules/dispatcher.js.map +1 -1
  354. package/dist/host-modules/docx.d.ts.map +1 -1
  355. package/dist/host-modules/docx.js +2 -2
  356. package/dist/host-modules/docx.js.map +1 -1
  357. package/dist/host-modules/epub.d.ts.map +1 -1
  358. package/dist/host-modules/epub.js +2 -2
  359. package/dist/host-modules/epub.js.map +1 -1
  360. package/dist/host-modules/fabric.d.ts.map +1 -1
  361. package/dist/host-modules/fabric.js +1 -1
  362. package/dist/host-modules/fabric.js.map +1 -1
  363. package/dist/host-modules/limits.d.ts +10 -8
  364. package/dist/host-modules/limits.d.ts.map +1 -1
  365. package/dist/host-modules/limits.js +14 -9
  366. package/dist/host-modules/limits.js.map +1 -1
  367. package/dist/host-modules/mammoth.d.ts.map +1 -1
  368. package/dist/host-modules/mammoth.js +2 -2
  369. package/dist/host-modules/mammoth.js.map +1 -1
  370. package/dist/host-modules/ocr.d.ts.map +1 -1
  371. package/dist/host-modules/ocr.js +1 -1
  372. package/dist/host-modules/ocr.js.map +1 -1
  373. package/dist/host-modules/pdf.d.ts.map +1 -1
  374. package/dist/host-modules/pdf.js +2 -2
  375. package/dist/host-modules/pdf.js.map +1 -1
  376. package/dist/host-modules/pdflib.d.ts.map +1 -1
  377. package/dist/host-modules/pdflib.js +2 -2
  378. package/dist/host-modules/pdflib.js.map +1 -1
  379. package/dist/host-modules/pptx.d.ts.map +1 -1
  380. package/dist/host-modules/pptx.js +2 -2
  381. package/dist/host-modules/pptx.js.map +1 -1
  382. package/dist/host-modules/pptxgen.d.ts.map +1 -1
  383. package/dist/host-modules/pptxgen.js +2 -2
  384. package/dist/host-modules/pptxgen.js.map +1 -1
  385. package/dist/host-modules/tfjs.d.ts.map +1 -1
  386. package/dist/host-modules/tfjs.js +4 -4
  387. package/dist/host-modules/tfjs.js.map +1 -1
  388. package/dist/host-modules/xlsx.d.ts.map +1 -1
  389. package/dist/host-modules/xlsx.js +2 -2
  390. package/dist/host-modules/xlsx.js.map +1 -1
  391. package/dist/index.d.ts +18 -4
  392. package/dist/index.d.ts.map +1 -1
  393. package/dist/index.js +17 -3
  394. package/dist/index.js.map +1 -1
  395. package/dist/js-sandbox-worker/engine.d.ts +4 -0
  396. package/dist/js-sandbox-worker/engine.d.ts.map +1 -0
  397. package/dist/js-sandbox-worker/engine.js +45 -0
  398. package/dist/js-sandbox-worker/engine.js.map +1 -0
  399. package/dist/js-sandbox-worker/host.js +1 -1
  400. package/dist/js-sandbox-worker/host.js.map +1 -1
  401. package/dist/js-sandbox-worker/interpreter.d.ts +1 -1
  402. package/dist/js-sandbox-worker/interpreter.d.ts.map +1 -1
  403. package/dist/js-sandbox-worker/interpreter.js +94 -2
  404. package/dist/js-sandbox-worker/interpreter.js.map +1 -1
  405. package/dist/js-sandbox-worker/worker-entry.d.ts.map +1 -1
  406. package/dist/js-sandbox-worker/worker-entry.js +3 -2
  407. package/dist/js-sandbox-worker/worker-entry.js.map +1 -1
  408. package/dist/js-sandbox.d.ts +9 -1
  409. package/dist/js-sandbox.d.ts.map +1 -1
  410. package/dist/js-sandbox.js +76 -15
  411. package/dist/js-sandbox.js.map +1 -1
  412. package/dist/js-script-app-runner.d.ts +2 -0
  413. package/dist/js-script-app-runner.d.ts.map +1 -1
  414. package/dist/js-script-app-runner.js +8 -3
  415. package/dist/js-script-app-runner.js.map +1 -1
  416. package/dist/js-script-sandbox.d.ts +12 -18
  417. package/dist/js-script-sandbox.d.ts.map +1 -1
  418. package/dist/js-script-sandbox.js +3 -49
  419. package/dist/js-script-sandbox.js.map +1 -1
  420. package/dist/prompts/product-knowledge.d.ts +1 -1
  421. package/dist/prompts/product-knowledge.d.ts.map +1 -1
  422. package/dist/prompts/product-knowledge.js +82 -41
  423. package/dist/prompts/product-knowledge.js.map +1 -1
  424. package/dist/sandbox-pack-resolution.d.ts +21 -0
  425. package/dist/sandbox-pack-resolution.d.ts.map +1 -0
  426. package/dist/sandbox-pack-resolution.js +42 -0
  427. package/dist/sandbox-pack-resolution.js.map +1 -0
  428. package/dist/sandbox-toolbelt.d.ts +3 -1
  429. package/dist/sandbox-toolbelt.d.ts.map +1 -1
  430. package/dist/sandbox-toolbelt.js +8 -2
  431. package/dist/sandbox-toolbelt.js.map +1 -1
  432. package/dist/skill-prompt.d.ts +11 -1
  433. package/dist/skill-prompt.d.ts.map +1 -1
  434. package/dist/skill-prompt.js +17 -6
  435. package/dist/skill-prompt.js.map +1 -1
  436. package/dist/system-skills.d.ts +7 -1
  437. package/dist/system-skills.d.ts.map +1 -1
  438. package/dist/system-skills.js +2 -2
  439. package/dist/system-skills.js.map +1 -1
  440. package/dist/timeline-capture.d.ts +21 -0
  441. package/dist/timeline-capture.d.ts.map +1 -0
  442. package/dist/timeline-capture.js +564 -0
  443. package/dist/timeline-capture.js.map +1 -0
  444. package/dist/timeline-code-bake.d.ts +75 -0
  445. package/dist/timeline-code-bake.d.ts.map +1 -0
  446. package/dist/timeline-code-bake.js +327 -0
  447. package/dist/timeline-code-bake.js.map +1 -0
  448. package/dist/timeline-preview/frames.d.ts +26 -0
  449. package/dist/timeline-preview/frames.d.ts.map +1 -1
  450. package/dist/timeline-preview/frames.js +155 -70
  451. package/dist/timeline-preview/frames.js.map +1 -1
  452. package/dist/tools/base-tool.d.ts +1 -0
  453. package/dist/tools/base-tool.d.ts.map +1 -1
  454. package/dist/tools/base-tool.js +1 -1
  455. package/dist/tools/base-tool.js.map +1 -1
  456. package/dist/tools/builtin-tools.d.ts +4 -3
  457. package/dist/tools/builtin-tools.d.ts.map +1 -1
  458. package/dist/tools/builtin-tools.js +24 -3
  459. package/dist/tools/builtin-tools.js.map +1 -1
  460. package/dist/tools/external-capability-tools.d.ts +1 -1
  461. package/dist/tools/external-capability-tools.js +1 -1
  462. package/dist/tools/mcp-tool-support.d.ts +10 -9
  463. package/dist/tools/mcp-tool-support.d.ts.map +1 -1
  464. package/dist/tools/mcp-tool-support.js +14 -13
  465. package/dist/tools/mcp-tool-support.js.map +1 -1
  466. package/dist/tools/mcp-tools.d.ts +6 -4
  467. package/dist/tools/mcp-tools.d.ts.map +1 -1
  468. package/dist/tools/mcp-tools.js +65 -62
  469. package/dist/tools/mcp-tools.js.map +1 -1
  470. package/dist/tools/tool-permissions.d.ts +1 -1
  471. package/dist/tools/tool-permissions.js +1 -1
  472. package/package.json +124 -41
  473. package/dist/capabilities/gate-tools.d.ts +0 -18
  474. package/dist/capabilities/gate-tools.d.ts.map +0 -1
  475. package/dist/capabilities/gate-tools.js +0 -66
  476. package/dist/capabilities/gate-tools.js.map +0 -1
  477. package/dist/tsconfig.tests.tmp.tsbuildinfo +0 -1
@@ -17,8 +17,12 @@
17
17
  *
18
18
  * Design: docs/tool-class-retirement-design.md § "Migration".
19
19
  */
20
- import { listTimelinesSpec, createTimelineSpec, getTimelineSpec, listTimelineVersionsSpec, getTimelineVersionSpec, createTimelineVersionSpec, restoreTimelineVersionSpec, deleteTimelineVersionSpec, editTimelineSpec, validateTimelineSpec, setTimelineDocumentSpec, previewTimelineFrameSpec, compareTimelineFramesSpec, renderTimelineSpec, bakeAudioAnimationSpec, isolateSubjectSpec, ISOLATE_SUBJECT_MODELS, ISOLATE_SUBJECT_RESOLUTIONS, DEFAULT_ISOLATE_SUBJECT_MODEL, DEFAULT_ISOLATE_SUBJECT_RESOLUTION, DEFAULT_BAKE_ATTACK_MS, DEFAULT_BAKE_RELEASE_MS, DEFAULT_BAKE_TOLERANCE, DEFAULT_BAKE_MAX_POINTS, DEFAULT_BAKE_MAX_SECONDS, MAX_BAKE_POINTS, DEFAULT_RENDER_TIMEOUT_MS, MAX_RENDER_TIMEOUT_MS, DEFAULT_PREVIEW_COUNT, DEFAULT_COMPARE_WIDTH, MAX_PREVIEW_TIMES, MAX_PREVIEW_RANGE_COUNT, DEFAULT_VERSION_LIMIT, MAX_VERSION_LIMIT, trackObjectSpec, TRACK_OBJECT_DIRECTIONS, deleteTimelineSpec } from "./timelines.specs.js";
21
- import { AUDIO_BAKED_ANIMATION_KIND, normalizeAuthoredDocument } from "@nodetool-ai/timeline";
20
+ import { parseOps, applyOps, TOOL_PREFIX, READ_ONLY_OPS, timelineModel3DBaker } from "./timeline-operations.js";
21
+ export { parseOps, applyOps } from "./timeline-operations.js";
22
+ import { listTimelinesSpec, createTimelineSpec, getTimelineSpec, listTimelineVersionsSpec, getTimelineVersionSpec, createTimelineVersionSpec, restoreTimelineVersionSpec, deleteTimelineVersionSpec, editTimelineSpec, validateTimelineSpec, setTimelineDocumentSpec, previewTimelineFrameSpec, compareTimelineFramesSpec, renderTimelineSpec, bakeAudioAnimationSpec, isolateSubjectSpec, ISOLATE_SUBJECT_MODELS, ISOLATE_SUBJECT_RESOLUTIONS, DEFAULT_ISOLATE_SUBJECT_MODEL, DEFAULT_ISOLATE_SUBJECT_RESOLUTION, DEFAULT_BAKE_ATTACK_MS, DEFAULT_BAKE_RELEASE_MS, DEFAULT_BAKE_TOLERANCE, DEFAULT_BAKE_MAX_POINTS, DEFAULT_BAKE_MAX_SECONDS, MAX_BAKE_POINTS, DEFAULT_RENDER_TIMEOUT_MS, MAX_RENDER_TIMEOUT_MS, DEFAULT_PREVIEW_COUNT, DEFAULT_COMPARE_WIDTH, MAX_PREVIEW_TIMES, MAX_PREVIEW_RANGE_COUNT, DEFAULT_VERSION_LIMIT, MAX_VERSION_LIMIT, trackObjectSpec, TRACK_OBJECT_DIRECTIONS, getTimelineCodeSpec, setTimelineCodeSpec, editTimelineCodeSpec, rebakeTimelineCodeSpec, detachTimelineCodeSpec, deleteTimelineSpec } from "./timelines.specs.js";
23
+ import { AUDIO_BAKED_ANIMATION_KIND, normalizeAuthoredDocument, hashSceneSubtree, mergeTimelineSource } from "@nodetool-ai/timeline";
24
+ import { bakeTimelineCode, bakedDocumentMatchesSaved } from "../timeline-code-bake.js";
25
+ import { applyJsScriptEditOps, parseJsScriptEditOps } from "./js-scripts.js";
22
26
  import { clipSourceWindowMs } from "./timeline-audio-bake.js";
23
27
  import { TIMELINE_NATIVE_MEDIA_CAPABILITIES } from "./timeline-native-media.js";
24
28
  import { isFiniteNumber, isRecord, isString } from "../utils/type-guards.js";
@@ -193,7 +197,7 @@ const getTimeline = {
193
197
  const seq = await loadTimeline(run, params["timeline_id"]);
194
198
  if (isError(seq))
195
199
  return seq;
196
- return { timeline: seq.toTimelineSequence() };
200
+ return { timeline: seq.toTimelineSequence(), revision: seq.revision };
197
201
  }
198
202
  };
199
203
  const listTimelineVersions = {
@@ -364,266 +368,6 @@ const deleteTimelineVersion = {
364
368
  // ---------------------------------------------------------------------------
365
369
  /** Attempts to land the document write before reporting a conflict. */
366
370
  const CAS_ATTEMPTS = 2;
367
- /** Operations one call may apply, so a runaway script cannot rewrite a cut. */
368
- const MAX_OPS = 60;
369
- const TOOL_PREFIX = "ui_timeline_";
370
- /**
371
- * Tools the browser bridge exposes that this capability cannot run safely.
372
- *
373
- * `edit_timeline` persists document mutations but has no durable media-edit
374
- * generation adapter or callback path. Exposing generative editing here would
375
- * require it to invent an asset id, so it remains browser-only until a server
376
- * generation runner can create and attach the candidate take. `apply_take`
377
- * stays available because it only promotes an existing candidate.
378
- */
379
- const EXCLUDED_OPS = new Set([
380
- `${TOOL_PREFIX}get_clip_frames`,
381
- `${TOOL_PREFIX}generate_clip`,
382
- `${TOOL_PREFIX}generatively_edit_clip`
383
- ]);
384
- /** `add_track`, `ui_add_track`, and `ui_timeline_add_track` all name one tool. */
385
- function normalizeOpName(name) {
386
- const trimmed = name.trim();
387
- if (trimmed.startsWith(TOOL_PREFIX))
388
- return trimmed;
389
- const bare = trimmed.startsWith("ui_")
390
- ? trimmed.slice("ui_".length)
391
- : trimmed;
392
- return `${TOOL_PREFIX}${bare}`;
393
- }
394
- /** An op is `{op, ...args}` — the arguments sit alongside the verb. */
395
- function parseOps(raw) {
396
- if (!Array.isArray(raw) || raw.length === 0) {
397
- return {
398
- error: 'ops must be a non-empty array, e.g. [{"op": "add_track", "type": "audio"}].'
399
- };
400
- }
401
- if (raw.length > MAX_OPS) {
402
- return {
403
- error: `ops holds ${raw.length} entries; at most ${MAX_OPS} per call.`
404
- };
405
- }
406
- const parsed = [];
407
- for (const [index, entry] of raw.entries()) {
408
- if (!isRecord(entry)) {
409
- return { error: `ops[${index}] must be an object.` };
410
- }
411
- const { op, ...input } = entry;
412
- if (!isString(op) || op.trim() === "") {
413
- return { error: `ops[${index}] has no \`op\` name.` };
414
- }
415
- parsed.push({ op: normalizeOpName(op), input });
416
- }
417
- return parsed;
418
- }
419
- /**
420
- * Read one of the caller's assets for `add_media_clip`.
421
- *
422
- * The ref a model has in hand is whatever `list_assets` printed — a bare id or
423
- * an `asset://<id>.<ext>` URI — so both resolve here.
424
- */
425
- async function resolveTimelineAsset(run, ref) {
426
- const id = ref.startsWith("asset://")
427
- ? ref.slice("asset://".length).replace(/\.[A-Za-z0-9]{1,8}$/, "")
428
- : ref;
429
- if (!id)
430
- return null;
431
- const userId = run.context.userId;
432
- if (!userId)
433
- return null;
434
- const { Asset } = await import("@nodetool-ai/models");
435
- // `find` is already user-scoped: someone else's asset reads as missing.
436
- const asset = await Asset.find(userId, id);
437
- if (!asset)
438
- return null;
439
- const thumbnails = isRecord(asset.metadata)
440
- ? asset.metadata["thumbnails"]
441
- : undefined;
442
- const thumbnailAssetId = Array.isArray(thumbnails) && isString(thumbnails[0])
443
- ? thumbnails[0]
444
- : undefined;
445
- const resolved = {
446
- id: asset.id,
447
- name: asset.name,
448
- contentType: asset.content_type
449
- };
450
- let duration = asset.duration;
451
- if ((!isFiniteNumber(duration) || duration <= 0) &&
452
- (asset.content_type.startsWith("audio/") || asset.content_type.startsWith("video/"))) {
453
- try {
454
- const { loadMediaRefBytes, probeVideoDurationSeconds } = await import("@nodetool-ai/runtime");
455
- const bytes = await loadMediaRefBytes({ asset_id: asset.id }, run.context);
456
- if (bytes) {
457
- duration = await probeVideoDurationSeconds(bytes, new AbortController().signal);
458
- if (isFiniteNumber(duration) && duration > 0) {
459
- asset.duration = duration;
460
- await asset.save();
461
- }
462
- }
463
- }
464
- catch {
465
- // An explicit clip duration remains usable when the source cannot be probed.
466
- }
467
- }
468
- if (isFiniteNumber(duration) && duration > 0) {
469
- resolved.durationMs = Math.round(duration * 1000);
470
- }
471
- if (thumbnailAssetId)
472
- resolved.thumbnailAssetId = thumbnailAssetId;
473
- return resolved;
474
- }
475
- /**
476
- * Run a custom animation's body once and return its curves.
477
- *
478
- * The bake is the only place that code runs — the curves are stored and every
479
- * render site samples them — so it goes through `bakeCustomAnimation`, the
480
- * same hermetic path `POST /api/timelines/animations/bake` uses. Imported
481
- * lazily: the sandbox is a heavy dependency for a capability most calls never
482
- * reach.
483
- */
484
- async function bakeTimelineAnimation(run, request) {
485
- const { bakeCustomAnimation } = await import("../custom-animation-bake.js");
486
- const params = {
487
- code: request.code,
488
- role: request.role,
489
- durationMs: request.durationMs,
490
- clipDurationMs: request.clipDurationMs,
491
- canvas: request.canvas
492
- };
493
- if (request.params !== undefined)
494
- params.params = request.params;
495
- if (request.staggerCount !== undefined) {
496
- params.staggerCount = request.staggerCount;
497
- }
498
- const baked = await bakeCustomAnimation(run.context, params);
499
- const result = { ok: baked.ok };
500
- if (baked.curves !== undefined)
501
- result.curves = baked.curves;
502
- if (baked.mask !== undefined)
503
- result.mask = baked.mask;
504
- if (baked.error !== undefined)
505
- result.error = baked.error;
506
- return result;
507
- }
508
- /**
509
- * Run `ops` against a bridge seeded from `document`.
510
- *
511
- * A failing op is recorded and the script continues: stopping at the first
512
- * error hides every problem behind it, and the caller wants the whole picture.
513
- */
514
- async function applyOps(run, sequence, document, ops) {
515
- const { createTimelineToolBridge } = await import("../evals/surfaces/timeline.js");
516
- const bridge = createTimelineToolBridge({
517
- sequenceId: sequence.id,
518
- sequenceName: sequence.name,
519
- projectId: sequence.project_id,
520
- sequence: {
521
- fps: sequence.fps,
522
- width: sequence.width,
523
- height: sequence.height,
524
- tracks: document.tracks,
525
- clips: document.clips,
526
- markers: document.markers,
527
- transcript: document.transcript,
528
- scriptEnabled: document.scriptEnabled,
529
- templateId: document.templateId,
530
- tempo: document.tempo,
531
- camera2d: document.camera2d,
532
- setup: document.setup,
533
- mediaTracks: document.mediaTracks
534
- },
535
- resolveAsset: (ref) => resolveTimelineAsset(run, ref),
536
- bakeAnimation: (request) => bakeTimelineAnimation(run, request),
537
- bakeModel3DClip: async (request) => {
538
- const { bakeModel3DClipOnServer } = await import("./timeline-bake.js");
539
- return bakeModel3DClipOnServer(run.context, request);
540
- },
541
- retargetFormat: async (adapted) => {
542
- const { TimelineSequence } = await import("@nodetool-ai/models");
543
- const derivedDocument = {
544
- tracks: adapted.tracks,
545
- clips: adapted.clips,
546
- markers: adapted.markers
547
- };
548
- if (adapted.transcript !== undefined) {
549
- derivedDocument.transcript = adapted.transcript;
550
- }
551
- if (adapted.scriptEnabled !== undefined) {
552
- derivedDocument.scriptEnabled = adapted.scriptEnabled;
553
- }
554
- if (adapted.tempo !== undefined)
555
- derivedDocument.tempo = adapted.tempo;
556
- if (adapted.camera2d !== undefined)
557
- derivedDocument.camera2d = adapted.camera2d;
558
- if (adapted.setup !== undefined)
559
- derivedDocument.setup = adapted.setup;
560
- if (adapted.templateId !== undefined) {
561
- derivedDocument.templateId = adapted.templateId;
562
- }
563
- if (adapted.mediaTracks !== undefined) {
564
- derivedDocument.mediaTracks = adapted.mediaTracks;
565
- }
566
- const name = `${sequence.name} (${adapted.width}×${adapted.height})`;
567
- const created = await TimelineSequence.create({
568
- user_id: run.context.userId,
569
- project_id: sequence.project_id,
570
- workflow_id: sequence.workflow_id,
571
- name,
572
- fps: adapted.fps,
573
- width: adapted.width,
574
- height: adapted.height,
575
- duration_ms: adapted.durationMs,
576
- document: JSON.stringify(derivedDocument)
577
- });
578
- return { sequenceId: created.id, name };
579
- },
580
- loadComposition: {
581
- get: async (id) => {
582
- const { loadComposition } = await import("./compositions.js");
583
- const found = await loadComposition(run, id);
584
- return found ? found.composition : null;
585
- },
586
- listIds: async () => {
587
- const { loadShippedCompositions, loadUserCompositions } = await import("./compositions.js");
588
- const mine = await loadUserCompositions(run);
589
- return [
590
- ...loadShippedCompositions().map((comp) => comp.id),
591
- ...(Array.isArray(mine) ? mine.map((comp) => comp.id) : [])
592
- ];
593
- }
594
- }
595
- });
596
- const byName = new Map(bridge.tools
597
- .filter((tool) => !EXCLUDED_OPS.has(tool.name))
598
- .map((tool) => [tool.name, tool]));
599
- const records = [];
600
- for (const { op, input } of ops) {
601
- const tool = byName.get(op);
602
- if (!tool) {
603
- const known = [...byName.keys()]
604
- .map((name) => name.slice(TOOL_PREFIX.length))
605
- .sort()
606
- .join(", ");
607
- records.push({
608
- op,
609
- ok: false,
610
- error: `No timeline operation named "${op.slice(TOOL_PREFIX.length)}". Available: ${known}.`
611
- });
612
- continue;
613
- }
614
- try {
615
- records.push({ op, ok: true, result: await tool.execute(input) });
616
- }
617
- catch (e) {
618
- records.push({
619
- op,
620
- ok: false,
621
- error: e instanceof Error ? e.message : String(e)
622
- });
623
- }
624
- }
625
- return { records, state: bridge.finalState() };
626
- }
627
371
  /**
628
372
  * The keys an op names its unit under, and which list each one means.
629
373
  *
@@ -741,7 +485,12 @@ const editTimeline = {
741
485
  "the returned timeline id."
742
486
  };
743
487
  }
744
- const { TimelineSequence } = await import("@nodetool-ai/models");
488
+ const { TimelineSequence, TimelineSequenceVersion } = await import("@nodetool-ai/models");
489
+ const { timelineMediaEditGenerator } = await import("./timeline-media-edit.js");
490
+ const generateMediaEdit = timelineMediaEditGenerator(run);
491
+ // Shared across retries, like the media edit generator: a retry re-applies
492
+ // every op, and a 3D bake already rendered must not render again.
493
+ const bakeModel3DClip = timelineModel3DBaker(run);
745
494
  for (let attempt = 0; attempt < CAS_ATTEMPTS; attempt++) {
746
495
  const sequence = await TimelineSequence.findById(timelineId);
747
496
  // A sequence owned by someone else reads as missing — the rule the tRPC
@@ -750,7 +499,7 @@ const editTimeline = {
750
499
  return { error: `Timeline ${timelineId} was not found.` };
751
500
  }
752
501
  const document = sequence.toDocument();
753
- const { records, state } = await applyOps(run, sequence, document, ops);
502
+ const { records, state } = await applyOps(run, sequence, document, ops, { generateMediaEdit, bakeModel3DClip });
754
503
  // The transcript rides along untouched — no timeline operation edits it,
755
504
  // so the stored copy stays authoritative. Markers come back from the
756
505
  // bridge, which seeded them and which the marker ops write to.
@@ -784,12 +533,12 @@ const editTimeline = {
784
533
  // hand an open editor a merge with nothing in it.
785
534
  const appliedOps = ops
786
535
  .map((parsed, index) => ({ parsed, index }))
787
- .filter(({ index }) => records[index]?.ok);
536
+ .filter(({ parsed, index }) => records[index]?.ok && !READ_ONLY_OPS.has(parsed.op));
788
537
  if (appliedOps.length === 0) {
789
538
  return {
790
539
  timeline_id: timelineId,
791
540
  updated_at: sequence.updated_at,
792
- applied: 0,
541
+ applied: records.filter((record) => record.ok).length,
793
542
  failed: failed.length,
794
543
  ops: records,
795
544
  tracks: state.tracks,
@@ -826,15 +575,23 @@ const editTimeline = {
826
575
  }))
827
576
  };
828
577
  }
578
+ const undo = appliedOps.some(({ parsed }) => parsed.op === `${TOOL_PREFIX}apply_take`)
579
+ ? await TimelineSequenceVersion.snapshot(sequence, { saveType: "manual", name: "Before applying AI edit take" })
580
+ : undefined;
829
581
  const saved = await TimelineSequence.updateDocumentIfUnchanged(sequence.id, sequence.updated_at, next, {
830
582
  ops: appliedOps.map(({ parsed, index }) => ({
831
583
  tool: parsed.op,
832
584
  input: resolveTimelineOpInput(parsed.input, document, state, records[index]?.result)
833
585
  }))
586
+ }).catch(async (error) => {
587
+ await undo?.delete();
588
+ throw error;
834
589
  });
835
- if (!saved)
590
+ if (!saved) {
591
+ await undo?.delete();
836
592
  continue;
837
- return {
593
+ }
594
+ const response = {
838
595
  timeline_id: timelineId,
839
596
  updated_at: saved.updated_at,
840
597
  applied: records.length - failed.length,
@@ -851,6 +608,10 @@ const editTimeline = {
851
608
  animations: clip.animations
852
609
  }))
853
610
  };
611
+ if (undo) {
612
+ Object.assign(response, { undo_version: undo.version });
613
+ }
614
+ return response;
854
615
  }
855
616
  return {
856
617
  error: `Timeline ${timelineId} is being modified concurrently; nothing was saved. Retry the call.`
@@ -978,7 +739,11 @@ const validateTimeline = {
978
739
  * whole-document write is that what was sent is what the sequence becomes.
979
740
  */
980
741
  function documentToStore(raw) {
981
- return normalizeAuthoredDocument(raw);
742
+ const { name, id: _id, projectId: _projectId, workflowId: _workflowId, durationMs: _durationMs, createdAt: _createdAt, updatedAt: _updatedAt, ...document } = raw;
743
+ return {
744
+ ...normalizeAuthoredDocument(document),
745
+ name: isString(name) && name.trim() ? name.trim() : undefined
746
+ };
982
747
  }
983
748
  /** The end of the last clip — what the sequence's stored duration means. */
984
749
  function documentDurationMs(document) {
@@ -1045,7 +810,11 @@ const setTimelineDocument = {
1045
810
  };
1046
811
  }
1047
812
  }
1048
- const { document, settings } = documentToStore(raw);
813
+ // `get_timeline` returns the sequence row's fields beside the document.
814
+ // A caller that sends that object back renames the sequence with `name`.
815
+ // The other row fields are owned by the row, so they are dropped rather
816
+ // than reported as stripped document fields.
817
+ const { document, settings, name } = documentToStore(raw);
1049
818
  // Document-level fps/width/height are sequence settings, so opts win and a
1050
819
  // document that carries them configures the sequence instead of having
1051
820
  // them stripped with a `field_stripped` warning.
@@ -1081,16 +850,19 @@ const setTimelineDocument = {
1081
850
  saveType: "manual",
1082
851
  name: snapshotName
1083
852
  });
1084
- const durationMs = documentDurationMs(document);
853
+ const fields = {
854
+ document: JSON.stringify(document),
855
+ fps,
856
+ width,
857
+ height,
858
+ duration_ms: documentDurationMs(document)
859
+ };
860
+ if (name !== undefined) {
861
+ fields.name = name;
862
+ }
1085
863
  let saved;
1086
864
  try {
1087
- saved = await TimelineSequence.updateFieldsIfUnchanged(sequence.id, sequence.updated_at, {
1088
- document: JSON.stringify(document),
1089
- fps,
1090
- width,
1091
- height,
1092
- duration_ms: durationMs
1093
- });
865
+ saved = await TimelineSequence.updateFieldsIfUnchanged(sequence.id, sequence.updated_at, fields);
1094
866
  }
1095
867
  catch (error) {
1096
868
  // The model rejects a document without tracks/clips/markers arrays. The
@@ -1117,6 +889,7 @@ const setTimelineDocument = {
1117
889
  ok: true,
1118
890
  written: true,
1119
891
  timeline_id: saved.id,
892
+ name: saved.name,
1120
893
  updated_at: saved.updated_at,
1121
894
  undo_version: undo.version,
1122
895
  fps: saved.fps,
@@ -1333,6 +1106,7 @@ const previewTimelineFrame = {
1333
1106
  mime: "image/png"
1334
1107
  });
1335
1108
  sheet = {
1109
+ complete: result.complete,
1336
1110
  columns: tiled.columns,
1337
1111
  rows: tiled.rows,
1338
1112
  cells: tiled.cells,
@@ -1346,12 +1120,15 @@ const previewTimelineFrame = {
1346
1120
  const frames = [];
1347
1121
  for (const frame of result.frames) {
1348
1122
  const entry = {
1123
+ complete: frame.complete,
1349
1124
  time_ms: frame.time_ms,
1350
1125
  width: frame.width,
1351
1126
  height: frame.height,
1352
1127
  layers: frame.layers,
1128
+ failures: frame.failures,
1353
1129
  dropped: frame.dropped,
1354
- degraded: frame.degraded
1130
+ degraded: frame.degraded,
1131
+ degradations: frame.degraded
1355
1132
  };
1356
1133
  if (!wantSheet) {
1357
1134
  const saved = await persistOutput(run.context, frame.png, {
@@ -1363,6 +1140,8 @@ const previewTimelineFrame = {
1363
1140
  frames.push(entry);
1364
1141
  }
1365
1142
  return {
1143
+ complete: result.complete,
1144
+ visual_output_verified: false,
1366
1145
  timeline_id: isString(timelineId) ? timelineId : undefined,
1367
1146
  name,
1368
1147
  fps: meta.fps,
@@ -1372,12 +1151,15 @@ const previewTimelineFrame = {
1372
1151
  frames,
1373
1152
  sheet,
1374
1153
  effects_not_applied: result.effectsNotApplied,
1375
- hint: wantSheet
1154
+ fonts_unavailable: result.fontsUnavailable,
1155
+ hint: (!result.complete
1156
+ ? "Incomplete preview: requested content was skipped or approximated. Inspect failures, dropped, degradations, skipped layers, effects_not_applied and fonts_unavailable. This image cannot verify the complete composition. "
1157
+ : "") + (wantSheet
1376
1158
  ? "Call view_image with the sheet's asset_id to see every frame at " +
1377
1159
  "once; the cells run left to right, labelled with their timecode. " +
1378
1160
  "Each frame's layers are listed top of the stack first."
1379
1161
  : "Call view_image with a frame's asset_id to see it. The layers are " +
1380
- "listed top of the stack first — the first one covers the rest."
1162
+ "listed top of the stack first — the first one covers the rest.")
1381
1163
  };
1382
1164
  }
1383
1165
  };
@@ -1510,10 +1292,15 @@ const compareTimelineFrames = {
1510
1292
  const frames = [];
1511
1293
  const cells = [];
1512
1294
  for (let i = 0; i < times.length; i++) {
1513
- const difference = Number((await frameDifference(left.frames[i].png, right.frames[i].png)).toFixed(4));
1514
- frames.push({ time_ms: times[i], difference });
1295
+ const complete = left.frames[i].complete && right.frames[i].complete;
1296
+ const difference = complete ? Number((await frameDifference(left.frames[i].png, right.frames[i].png)).toFixed(4)) : null;
1297
+ frames.push({
1298
+ time_ms: times[i], complete, difference,
1299
+ a: { failures: left.frames[i].failures, dropped: left.frames[i].dropped, degradations: left.frames[i].degraded, skipped: left.frames[i].layers.filter((layer) => layer.skipped) },
1300
+ b: { failures: right.frames[i].failures, dropped: right.frames[i].dropped, degradations: right.frames[i].degraded, skipped: right.frames[i].layers.filter((layer) => layer.skipped) }
1301
+ });
1515
1302
  cells.push({
1516
- label: `${times[i]}ms ${difference.toFixed(3)}`,
1303
+ label: `${times[i]}ms ${difference === null ? "incomplete" : difference.toFixed(3)}`,
1517
1304
  png: await sideBySide(left.frames[i].png, right.frames[i].png)
1518
1305
  });
1519
1306
  }
@@ -1522,16 +1309,20 @@ const compareTimelineFrames = {
1522
1309
  namePrefix: "timeline-compare",
1523
1310
  mime: "image/png"
1524
1311
  });
1525
- const differences = frames.map((frame) => frame.difference);
1526
- const changed = frames.filter((frame) => frame.difference > 0);
1312
+ const complete = left.complete && right.complete;
1313
+ const differences = frames.flatMap((frame) => frame.difference === null ? [] : [frame.difference]);
1314
+ const changed = frames.filter((frame) => frame.difference !== null && frame.difference > 0);
1527
1315
  return {
1316
+ complete,
1317
+ visual_output_verified: false,
1528
1318
  a: a.source,
1529
1319
  b: b.source,
1530
1320
  frames,
1531
- changed_times_ms: changed.map((frame) => frame.time_ms),
1532
- max_difference: Math.max(...differences),
1533
- mean_difference: Number((differences.reduce((sum, d) => sum + d, 0) / differences.length).toFixed(4)),
1321
+ changed_times_ms: complete ? changed.map((frame) => frame.time_ms) : null,
1322
+ max_difference: complete ? Math.max(...differences) : null,
1323
+ mean_difference: complete ? Number((differences.reduce((sum, d) => sum + d, 0) / differences.length).toFixed(4)) : null,
1534
1324
  sheet: {
1325
+ complete,
1535
1326
  columns: tiled.columns,
1536
1327
  rows: tiled.rows,
1537
1328
  cells: tiled.cells,
@@ -1542,7 +1333,11 @@ const compareTimelineFrames = {
1542
1333
  effects_not_applied: [
1543
1334
  ...new Set([...left.effectsNotApplied, ...right.effectsNotApplied])
1544
1335
  ].sort(),
1545
- hint: "difference is the mean absolute RGB difference, 0 (identical) to 1. " +
1336
+ fonts_unavailable: [
1337
+ ...new Set([...left.fontsUnavailable, ...right.fontsUnavailable])
1338
+ ].sort(),
1339
+ hint: (!complete ? "Incomplete previews cannot establish visual equivalence. Difference scores are null for incomplete pairs and aggregate metrics are unavailable. " : "") +
1340
+ "difference is the mean absolute RGB difference, 0 (identical) to 1. " +
1546
1341
  "Each cell of the sheet is a pair: `a` on the left, `b` on the right, " +
1547
1342
  "labelled with its timecode and score."
1548
1343
  };
@@ -2116,7 +1911,7 @@ const isolateSubject = {
2116
1911
  let expectedUpdatedAt = sequence.updated_at;
2117
1912
  const persist = async (next) => {
2118
1913
  const clips = document.clips.map((c) => (c.id === next.id ? next : c));
2119
- const saved = await TimelineSequence.updateDocumentIfUnchanged(timelineId, expectedUpdatedAt, { ...document, clips }, {
1914
+ const saved = await TimelineSequence.updateDocumentIfUnchanged(sequence.id, expectedUpdatedAt, { ...document, clips }, {
2120
1915
  ops: [
2121
1916
  {
2122
1917
  tool: `${TOOL_PREFIX}set_generated_matte`,
@@ -2238,7 +2033,7 @@ const trackObject = {
2238
2033
  let expectedUpdatedAt = sequence.updated_at;
2239
2034
  let mediaTracks = document.mediaTracks ?? [];
2240
2035
  const persist = async (next) => {
2241
- const saved = await TimelineSequence.updateDocumentIfUnchanged(timelineId, expectedUpdatedAt, { ...document, mediaTracks: next }, { ops: [{ tool: "track_object", input: { clip_id: clip.id, track_id: trackId } }] });
2036
+ const saved = await TimelineSequence.updateDocumentIfUnchanged(sequence.id, expectedUpdatedAt, { ...document, mediaTracks: next }, { ops: [{ tool: "track_object", input: { clip_id: clip.id, track_id: trackId } }] });
2242
2037
  if (!saved)
2243
2038
  return false;
2244
2039
  mediaTracks = next;
@@ -2283,6 +2078,322 @@ const trackObject = {
2283
2078
  return result;
2284
2079
  }
2285
2080
  };
2081
+ /**
2082
+ * The report shape `get_timeline_code`, `set_timeline_code`, `edit_timeline_code`
2083
+ * and `rebake_timeline_code` all answer for `scenes`: `edited` means "kept
2084
+ * as-is rather than reflecting the code" — either the code has never been
2085
+ * baked into a current merge (`get`), or this call's own merge kept it as a
2086
+ * conflict (`set`/`edit`/`rebake`).
2087
+ */
2088
+ function sceneReport(scenes, editedNames) {
2089
+ return Object.entries(scenes).map(([name, recorded]) => ({
2090
+ name,
2091
+ group_id: recorded.groupId,
2092
+ edited: editedNames.has(name)
2093
+ }));
2094
+ }
2095
+ /** `force` is a boolean or an array of scene names; anything else is refused. */
2096
+ function normalizeForceOption(value) {
2097
+ if (value === undefined)
2098
+ return undefined;
2099
+ if (value === true)
2100
+ return true;
2101
+ if (value === false)
2102
+ return undefined;
2103
+ if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
2104
+ return value;
2105
+ }
2106
+ return { error: "force must be a boolean or an array of scene names." };
2107
+ }
2108
+ /**
2109
+ * Validate, snapshot, and CAS-write a document the way `set_timeline_document`
2110
+ * does (see its own docstring for why each step is there): validate first so
2111
+ * a document that would not render never reaches the database, snapshot the
2112
+ * state being replaced so the write is undoable, then a CAS write so a
2113
+ * concurrent edit is reported rather than clobbered.
2114
+ */
2115
+ export async function writeTimelineCodeDocument(sequence, document, snapshotName) {
2116
+ const { validateTimelineSequence } = await import("@nodetool-ai/execution/timeline-debug");
2117
+ const before = validateTimelineSequence(document, { fps: sequence.fps, width: sequence.width, height: sequence.height });
2118
+ const errors = before.errors.map((issue) => issue.message);
2119
+ const warnings = before.warnings.map((issue) => issue.message);
2120
+ if (!before.ok) {
2121
+ return {
2122
+ written: false,
2123
+ error: `The baked document has ${before.errors.length} error${before.errors.length === 1 ? "" : "s"} and was not written to timeline ${sequence.id}.`,
2124
+ errors,
2125
+ warnings
2126
+ };
2127
+ }
2128
+ const { TimelineSequence: TimelineSequenceModel, TimelineSequenceVersion } = await import("@nodetool-ai/models");
2129
+ await TimelineSequenceVersion.snapshot(sequence, {
2130
+ saveType: "manual",
2131
+ name: snapshotName
2132
+ });
2133
+ const saved = await TimelineSequenceModel.updateFieldsIfUnchanged(sequence.id, sequence.updated_at, {
2134
+ document: JSON.stringify(document),
2135
+ duration_ms: documentDurationMs(document)
2136
+ });
2137
+ if (!saved) {
2138
+ return {
2139
+ written: false,
2140
+ error: `Timeline ${sequence.id} was modified concurrently; nothing was written. Read it again and try again.`,
2141
+ errors,
2142
+ warnings
2143
+ };
2144
+ }
2145
+ return { written: true, timeline_id: saved.id, errors, warnings };
2146
+ }
2147
+ /**
2148
+ * Bake `code`, merge the result into `sequence`'s current document (see
2149
+ * `mergeTimelineSource` in `@nodetool-ai/timeline` for the merge rule), and
2150
+ * write it through the same path `set_timeline_document` uses. Shared by
2151
+ * `set_timeline_code`, `edit_timeline_code` and `rebake_timeline_code` — they
2152
+ * differ only in where `code` comes from.
2153
+ */
2154
+ async function bakeAndMergeTimelineCode(run, sequence, code, force) {
2155
+ const current = sequence.toDocument();
2156
+ const baked = await bakeTimelineCode(run.context, code);
2157
+ if (!baked.ok || !baked.document) {
2158
+ return {
2159
+ timeline_id: sequence.id,
2160
+ errors: [baked.error ?? "The code failed to build a document."],
2161
+ warnings: [],
2162
+ conflicts: [],
2163
+ scenes: []
2164
+ };
2165
+ }
2166
+ const previousScenes = current.source?.scenes ?? {};
2167
+ const merged = mergeTimelineSource(current, baked.document, previousScenes, force !== undefined ? { force } : {});
2168
+ const mergedWithSource = {
2169
+ ...merged.document,
2170
+ source: {
2171
+ lang: "js",
2172
+ code,
2173
+ bakedAt: new Date().toISOString(),
2174
+ scenes: merged.scenes
2175
+ }
2176
+ };
2177
+ const editedNames = new Set(merged.conflicts.map((c) => c.scene));
2178
+ const scenes = sceneReport(merged.scenes, editedNames);
2179
+ const write = await writeTimelineCodeDocument(sequence, mergedWithSource, "Before writing timeline code");
2180
+ if (!write.written) {
2181
+ return {
2182
+ timeline_id: sequence.id,
2183
+ errors: [write.error, ...write.errors],
2184
+ warnings: write.warnings,
2185
+ conflicts: merged.conflicts,
2186
+ scenes
2187
+ };
2188
+ }
2189
+ return {
2190
+ timeline_id: write.timeline_id,
2191
+ errors: write.errors,
2192
+ warnings: write.warnings,
2193
+ conflicts: merged.conflicts,
2194
+ scenes
2195
+ };
2196
+ }
2197
+ /**
2198
+ * Attach `code` as `sequence`'s authoring source only when a hermetic bake
2199
+ * of it gives exactly the document that is saved now. This is
2200
+ * `set_timeline_code` with `require_match: true`, which `v.save()` calls
2201
+ * with the retained program it printed (docs/timeline-code-capture.md).
2202
+ *
2203
+ * A mismatch writes nothing and returns a warning. The document stays as it
2204
+ * was saved, only without code, because code that does not rebuild it would
2205
+ * make a later rebake diverge from what the timeline shows.
2206
+ */
2207
+ async function attachMatchingTimelineCode(run, sequence, code) {
2208
+ const current = sequence.toDocument();
2209
+ const notEmbedded = (warning) => ({
2210
+ timeline_id: sequence.id,
2211
+ embedded: false,
2212
+ errors: [],
2213
+ warnings: [warning],
2214
+ conflicts: [],
2215
+ scenes: []
2216
+ });
2217
+ const baked = await bakeTimelineCode(run.context, code);
2218
+ if (!baked.ok || !baked.document) {
2219
+ return notEmbedded(`Code not embedded: the retained program failed to rebake (${baked.error ?? "unknown error"}).`);
2220
+ }
2221
+ if (!bakedDocumentMatchesSaved(current, baked.document)) {
2222
+ return notEmbedded("Code not embedded: the retained program rebakes to a different " +
2223
+ "timeline than the one saved. A scene clip probably changed after " +
2224
+ "v.series(), or a value came from Math.random() or Date.now().");
2225
+ }
2226
+ // Every scene is new here: the saved document was just written from this
2227
+ // same run, so there are no hand edits to keep.
2228
+ const merged = mergeTimelineSource(current, baked.document, {}, { force: true });
2229
+ const write = await writeTimelineCodeDocument(sequence, {
2230
+ ...merged.document,
2231
+ source: {
2232
+ lang: "js",
2233
+ code,
2234
+ bakedAt: new Date().toISOString(),
2235
+ scenes: merged.scenes
2236
+ }
2237
+ }, "Attach authoring code");
2238
+ if (!write.written) {
2239
+ return notEmbedded(`Code not embedded: ${write.error}`);
2240
+ }
2241
+ return {
2242
+ timeline_id: write.timeline_id,
2243
+ embedded: true,
2244
+ errors: write.errors,
2245
+ warnings: write.warnings,
2246
+ conflicts: [],
2247
+ scenes: sceneReport(merged.scenes, new Set())
2248
+ };
2249
+ }
2250
+ const getTimelineCode = {
2251
+ spec: getTimelineCodeSpec,
2252
+ impl: async (run, params) => {
2253
+ const sequence = await loadTimeline(run, params["timeline_id"]);
2254
+ if (isError(sequence))
2255
+ return sequence;
2256
+ const doc = sequence.toDocument();
2257
+ const source = doc.source;
2258
+ if (!source)
2259
+ return { code: null, baked_at: null, scenes: [] };
2260
+ const groupIdByScene = new Map();
2261
+ for (const clip of doc.clips) {
2262
+ if (typeof clip.sourceScene === "string" && clip.sourceScene) {
2263
+ groupIdByScene.set(clip.sourceScene, clip.id);
2264
+ }
2265
+ }
2266
+ const editedNames = new Set();
2267
+ for (const [name, recorded] of Object.entries(source.scenes)) {
2268
+ const groupId = groupIdByScene.get(name);
2269
+ const edited = groupId === undefined ||
2270
+ hashSceneSubtree(doc.clips, groupId) !== recorded.hash;
2271
+ if (edited)
2272
+ editedNames.add(name);
2273
+ }
2274
+ return {
2275
+ code: source.code,
2276
+ baked_at: source.bakedAt,
2277
+ scenes: sceneReport(source.scenes, editedNames)
2278
+ };
2279
+ }
2280
+ };
2281
+ const setTimelineCode = {
2282
+ spec: setTimelineCodeSpec,
2283
+ impl: async (run, params) => {
2284
+ const sequence = await loadTimeline(run, params["timeline_id"]);
2285
+ if (isError(sequence))
2286
+ return sequence;
2287
+ const code = params["code"];
2288
+ if (!isString(code) || !code.trim()) {
2289
+ return { error: "code is required and must be a non-empty script." };
2290
+ }
2291
+ if (params["require_match"] === true) {
2292
+ return attachMatchingTimelineCode(run, sequence, code);
2293
+ }
2294
+ const force = normalizeForceOption(params["force"]);
2295
+ if (isError(force))
2296
+ return force;
2297
+ return bakeAndMergeTimelineCode(run, sequence, code, force);
2298
+ }
2299
+ };
2300
+ const editTimelineCode = {
2301
+ spec: editTimelineCodeSpec,
2302
+ impl: async (run, params) => {
2303
+ const sequence = await loadTimeline(run, params["timeline_id"]);
2304
+ if (isError(sequence))
2305
+ return sequence;
2306
+ const source = sequence.toDocument().source;
2307
+ if (!source) {
2308
+ return {
2309
+ error: `Timeline ${sequence.id} has no authoring code to edit. Call set_timeline_code first.`
2310
+ };
2311
+ }
2312
+ const ops = parseJsScriptEditOps(params["edits"]);
2313
+ if (isError(ops))
2314
+ return ops;
2315
+ const applied = applyJsScriptEditOps(source.code, ops);
2316
+ if (isError(applied))
2317
+ return applied;
2318
+ const force = normalizeForceOption(params["force"]);
2319
+ if (isError(force))
2320
+ return force;
2321
+ return bakeAndMergeTimelineCode(run, sequence, applied.code, force);
2322
+ }
2323
+ };
2324
+ const rebakeTimelineCode = {
2325
+ spec: rebakeTimelineCodeSpec,
2326
+ impl: async (run, params) => {
2327
+ const sequence = await loadTimeline(run, params["timeline_id"]);
2328
+ if (isError(sequence))
2329
+ return sequence;
2330
+ const source = sequence.toDocument().source;
2331
+ if (!source) {
2332
+ return { error: `Timeline ${sequence.id} has no authoring code to rebake.` };
2333
+ }
2334
+ const force = normalizeForceOption(params["force"]);
2335
+ if (isError(force))
2336
+ return force;
2337
+ return bakeAndMergeTimelineCode(run, sequence, source.code, force);
2338
+ }
2339
+ };
2340
+ const detachTimelineCode = {
2341
+ spec: detachTimelineCodeSpec,
2342
+ impl: async (run, params) => {
2343
+ const sequence = await loadTimeline(run, params["timeline_id"]);
2344
+ if (isError(sequence))
2345
+ return sequence;
2346
+ const current = sequence.toDocument();
2347
+ const source = current.source;
2348
+ if (!source)
2349
+ return { scenes: [] };
2350
+ const scenesParam = params["scenes"];
2351
+ // "all" drops the code entirely — there is nothing left to track, and
2352
+ // nothing left worth rebaking. Naming every currently-tracked scene one
2353
+ // by one is a different request: those scenes stop being tracked, but
2354
+ // the code stays, so a later edit that reintroduces a scene (or adds a
2355
+ // new one) still has somewhere to bake into.
2356
+ const dropCode = scenesParam === "all";
2357
+ let detachedNames;
2358
+ if (dropCode) {
2359
+ detachedNames = Object.keys(source.scenes);
2360
+ }
2361
+ else if (Array.isArray(scenesParam) &&
2362
+ scenesParam.length > 0 &&
2363
+ scenesParam.every((s) => typeof s === "string")) {
2364
+ detachedNames = scenesParam.filter((name) => name in source.scenes);
2365
+ }
2366
+ else {
2367
+ return {
2368
+ error: 'scenes must be "all" or a non-empty array of scene names.'
2369
+ };
2370
+ }
2371
+ if (detachedNames.length === 0)
2372
+ return { scenes: [] };
2373
+ const remaining = { ...source.scenes };
2374
+ for (const name of detachedNames)
2375
+ delete remaining[name];
2376
+ const nextDocument = { ...current };
2377
+ if (dropCode) {
2378
+ delete nextDocument["source"];
2379
+ }
2380
+ else {
2381
+ nextDocument["source"] = { ...source, scenes: remaining };
2382
+ }
2383
+ const { TimelineSequence: TimelineSequenceModel, TimelineSequenceVersion } = await import("@nodetool-ai/models");
2384
+ await TimelineSequenceVersion.snapshot(sequence, {
2385
+ saveType: "manual",
2386
+ name: "Before detaching timeline code"
2387
+ });
2388
+ const saved = await TimelineSequenceModel.updateFieldsIfUnchanged(sequence.id, sequence.updated_at, { document: JSON.stringify(nextDocument) });
2389
+ if (!saved) {
2390
+ return {
2391
+ error: `Timeline ${sequence.id} was modified concurrently; nothing was written. Try again.`
2392
+ };
2393
+ }
2394
+ return { timeline_id: saved.id, scenes: detachedNames };
2395
+ }
2396
+ };
2286
2397
  const deleteTimeline = {
2287
2398
  spec: deleteTimelineSpec,
2288
2399
  impl: async (run, params) => {
@@ -2316,11 +2427,16 @@ export const TIMELINE_CAPABILITIES = [
2316
2427
  isolateSubject,
2317
2428
  trackObject,
2318
2429
  ...TIMELINE_NATIVE_MEDIA_CAPABILITIES,
2430
+ getTimelineCode,
2431
+ setTimelineCode,
2432
+ editTimelineCode,
2433
+ rebakeTimelineCode,
2434
+ detachTimelineCode,
2319
2435
  deleteTimeline
2320
2436
  ];
2321
2437
  export const module = {
2322
2438
  module: "timelines",
2323
2439
  exports: TIMELINE_CAPABILITIES
2324
2440
  };
2325
- export { listTimelines, createTimeline, getTimeline, listTimelineVersions, getTimelineVersion, createTimelineVersion, restoreTimelineVersion, deleteTimelineVersion, editTimeline, validateTimeline, setTimelineDocument, previewTimelineFrame, compareTimelineFrames, renderTimeline, bakeAudioAnimation, isolateSubject, trackObject, deleteTimeline };
2441
+ export { listTimelines, createTimeline, getTimeline, listTimelineVersions, getTimelineVersion, createTimelineVersion, restoreTimelineVersion, deleteTimelineVersion, editTimeline, validateTimeline, setTimelineDocument, previewTimelineFrame, compareTimelineFrames, renderTimeline, bakeAudioAnimation, isolateSubject, trackObject, getTimelineCode, setTimelineCode, editTimelineCode, rebakeTimelineCode, detachTimelineCode, deleteTimeline };
2326
2442
  //# sourceMappingURL=timelines.js.map